Back to Spree

Extending Admin Dashboard UI

docs/developer/admin/extending-ui.mdx

5.4.247.9 KB
Original Source

Spree Admin Dashboard allows you easily extend existing pages and screens with your own code, without any need to modify the core codebase. This allows you to easily inject your custom UI elements without compromising the integrity of the core codebase. Which in effect allows you to safely update your Spree installation to the latest version.

How it works

The entire system works on the basis of injection points which are declared throughout the admin dashboard and allows you to push your own code there. Each injection point is identified by a key, eg. body_end.

Let's say you want to add a new footer to the admin dashboard. You'll need to generate a template in your application:

  1. Ensure you have the proper directory to store your templates:

    bash
    mkdir -p app/views/spree/admin/shared
    
  2. Create a new partial template file (partial templates file names start with underscore)

    bash
    touch app/views/spree/admin/shared/_additional_footer.html.erb
    
  3. Add your own code to the partial

    erb
    <div class="mx-auto bg-light p-3 rounded-lg text-center w-10">
      Copyright <%= current_store.name %> <%= Time.current.year %>
    </div>
    
  4. Register your partial in config/initializers/spree.rb

    <Tabs> <Tab title="Spree 5.2+"> ```ruby config/initializers/spree.rb Rails.application.config.after_initialize do Spree.admin.partials.body_end << 'spree/admin/shared/additional_footer' end ``` </Tab> <Tab title="Spree 5.1 and below"> ```ruby config/initializers/spree.rb Rails.application.config.spree_admin.body_end << 'spree/admin/shared/additional_footer_partials' ```
     <Warning>
       For older versions of Spree you need to add `_partials` suffix for all injection points, 
       eg. `body_end_partials` instead of `body_end`.
     </Warning>
    
    </Tab> </Tabs> <Info> The key is the name of the injection point, eg. `body_end`. </Info> <Info> Remember to use the correct path to your template file and skip the `_` prefix. </Info>
  5. Restart your web server and you should see your new footer.

    <Frame> </Frame> <Info> Making further changes to the partial template will not require you to restart the web server. They will be picked up automatically. </Info>
<Hint> To summarize, we're injecting our code into the `body_end` array. This is a list of partials that will be rendered at the end of the body tag (before the closing `</body>` tag). The order of the partials in the array is the order in which they will be rendered. </Hint>

Partials API

The Spree.admin.partials object provides a clean API for registering partials to injection points. This API is available in Spree 5.2 and later.

Accessing Available Injection Points

You can list all available injection points programmatically:

ruby
# In Rails console or initializer
Spree.admin.partials.keys
# => ["head", "body_start", "body_end", "dashboard_analytics", "product_form", ...]

Registering Partials

Each injection point is an array that you can append to:

ruby

# Add a single partial
Spree.admin.partials.product_form << 'spree/admin/products/erp_section'

# Add multiple partials
Spree.admin.partials.dashboard_sidebar << 'spree/admin/dashboard/analytics_widget'
Spree.admin.partials.dashboard_sidebar << 'spree/admin/dashboard/inventory_widget'

Viewing Registered Partials

To see which partials are registered for a specific injection point:

ruby
Spree.admin.partials.product_form
# => ["spree/admin/products/erp_section"]

Replacing All Partials

You can also replace all partials for an injection point:

ruby
Spree.admin.partials.product_form = ['my/custom/partial']
<Warning> Replacing all partials will remove any partials registered by other extensions. Use this with caution. </Warning>

List of all injection points

Here's a list of all places you can inject your custom code:

Layout

<AccordionGroup> <Accordion title="<head>"> `head`
Injects code into the `<head>` tag
</Accordion> <Accordion title="<body>"> `body_start`
Injects code into the `<body>` tag, before the main content
</Accordion> <Accordion title="</body>"> `body_end`
Injects code into the `<body>` tag, after the main content
</Accordion> </AccordionGroup>

Dashboard

<AccordionGroup> <Accordion title="Analytics"> `dashboard_analytics`
<Frame>
  
</Frame>

Injects code into the dashboard analytics section, eg.

```erb
<div class="card">
  <div class="card-body">
    <h5 class="card-title">Top ERP products</h5>
  </div>
  <div class="card-footer">
    <%# ... my custom content ... %>
  </div>
</div>
```
</Accordion> <Accordion title="Sidebar"> `dashboard_sidebar`
<Frame>
  
</Frame>

Injects code into the dashboard sidebar, eg.

```erb
<div class="card">
  <div class="card-body">
    <h5 class="card-title">Latest ERP syncs</h5>
  </div>
  <div class="card-footer">
    <%# ... my custom content ... %>
  </div>
</div>
```
</Accordion> </AccordionGroup>

Orders

<AccordionGroup> <Accordion title="Orders Actions"> `orders_actions`
Injects code into the page actions area (top right of the page) for the orders list page. This is useful for adding custom buttons, export options, or other actions.

```erb
<%= link_to "Export to ERP", export_orders_to_erp_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Orders Header"> `orders_header`
Injects code between the page header and the main content area for the orders list page. This is useful for adding notifications, alerts, or additional information.

```erb
<div class="alert alert-info">
  <strong>Processing:</strong> Orders are automatically processed and shipped within 24 hours.
</div>
```
</Accordion> <Accordion title="Orders Filters"> `orders_filters`
<Frame>
  
</Frame>

#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the orders list filters, to add custom filters.
This partial has access to the `f` variable, which is the form builder for the filters, eg.

```erb
<%= f.spree_text_field :q_number_cont, data: { filters_target: :input } %>
```

<Tip>
* `q_number_cont` - The name of the filter field. For filtering we're using [ransack](/developer/core-concepts/search-filtering) gem, so the name of the filter field is the name of the attribute we're filtering by.
* `data: { filters_target: :input }` - Needed for the [Stimulus Filters controller](https://github.com/spree/spree/blob/main/admin/app/javascript/spree/admin/controllers/filters_controller.js) to work.
</Tip>
</Accordion> <Accordion title="Order Page Dropdown"> `order_page_dropdown`
<Frame>
  
</Frame>

#### Variables

<ParamField path="order" type="Spree::Order">
  The [Spree::Order](https://github.com/spree/spree/blob/main/core/app/models/spree/order.rb) object.
</ParamField>

Injects code into the order page dropdown. This partial has access to the `order` variable.

To add an additional dropdown item, you can use the following code:

```erb
<%= link_to "View Order in ERP", "https://erp.com/orders/#{order.number}", class: "dropdown-item", target: "_blank" %>
```

<Tip>
* `dropdown-item` is a CSS class for styling the dropdown item
* `target: "_blank"` is used to open the link in a new tab
</Tip>
</Accordion> <Accordion title="Order Page Header"> `order_page_header`
<Frame>
  
</Frame>

#### Variables

<ParamField path="order" type="Spree::Order">
  The [Spree::Order](https://github.com/spree/spree/blob/main/core/app/models/spree/order.rb) object.
</ParamField>

Injects code into the order page header.

To add an additional action button near the `...` button, you can use the following code:

<Frame>
  
</Frame>

Injects code into the order page header.

To add an additional action button near the `...` button, you can use the following code:

```erb
<%= content_for :page_actions do %>
  <%= link_to "Send to ERP", "#", class: "btn btn-primary" %>
<% end %>
```

To add an inline alert to the order page, you can use the following code:

```erb
<%= content_for :page_alerts do %>
  <% if order.sent_to_erp_at.blank? %>
    <div class="alert alert-success">Order sent to ERP at <%= local_time(order.sent_to_erp_at) %></div>
  <% else %>
    <div class="alert alert-danger">Order not sent to ERP</div>
  <% end %>
<% end %>
```

<Tip>
`local_time` is a helper for displaying the time in the user's timezone in a human readable **format** (based on the browser's timezone).
</Tip>
</Accordion> <Accordion title="Order Page Body"> `order_page_body`
<Frame>
  
</Frame>

#### Variables

<ParamField path="order" type="Spree::Order">
  The [Spree::Order](https://github.com/spree/spree/blob/main/core/app/models/spree/order.rb) object.
</ParamField>

Injects code into the order page body. This partial has access to the `order` variable.

To add a new section to the order page, you can use the following code:

```erb
<div class="card mb-6">
  <div class="card-header">
    <h5 class="card-title">ERP Integration</h5>
  </div>
  <div class="card-body">
    <% if order.sent_to_erp_at.blank? %>
      <p class="text-muted text-center">Order not sent to ERP</p>
    <% else %>
      <ul class="list-group list-group-flush">
        <li class="list-group-item">
          <strong>ERP Order ID:</strong> <%= order.erp_order_id %>
        </li>
        <li class="list-group-item">
          <strong>Sent to ERP at:</strong> <%= local_time(order.sent_to_erp_at) %>
        </li>
      </ul>
    <% end %>
  </div>
</div>
```
</Accordion> <Accordion title="Order Page Sidebar"> `order_page_sidebar`
<Frame>
  
</Frame>

#### Variables

<ParamField path="order" type="Spree::Order">
  The [Spree::Order](https://github.com/spree/spree/blob/main/core/app/models/spree/order.rb) object.
</ParamField>

Injects code into the order page sidebar. This partial has access to the `order` variable.
</Accordion> </AccordionGroup>

Customers

<AccordionGroup> <Accordion title="Customers Actions"> `users_actions`
Injects code into the page actions area (top right of the page) for the customers list page. This is useful for adding custom buttons, export options, or other actions.

```erb
<%= link_to "Sync with CRM", sync_customers_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Customers Header"> `users_header`
Injects code between the page header and the main content area for the customers list page. This is useful for adding notifications, alerts, or additional information.

```erb
<div class="alert alert-info">
  <strong>Note:</strong> Customer data is synced with CRM every hour.
</div>
```
</Accordion> <Accordion title="Customers Filters"> `users_filters`
#### Variables

<ParamField path="f" type="ActionView::Helpers::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the customers list filters. This partial has access to the `f` variable, which is the form builder for the filters.

```erb
<%= f.spree_select :custom_field_eq, [["VIP", "vip"], ["Regular", "regular"]], { include_blank: true }, { data: { filters_target: :input } } %>
```

<Tip>
* Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names
* Include `data: { filters_target: :input }` for proper integration with the Stimulus Filters controller
</Tip>
</Accordion> </AccordionGroup>

Stock Items

<AccordionGroup> <Accordion title="Stock Items Actions"> `stock_items_actions`
Injects code into the page actions area for the stock items list page.

```erb
<%= link_to "Export to WMS", export_stock_to_wms_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Stock Items Header"> `stock_items_header`
Injects code between the page header and the main content area for the stock items list page.

```erb
<div class="alert alert-warning">
  <strong>Warning:</strong> Low stock items require attention.
</div>
```
</Accordion> <Accordion title="Stock Items Filters"> `stock_items_filters`
#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the stock items list filters.

```erb
<%= f.spree_number_field :count_on_hand_lt,
    label: "Stock Below",
    data: { filters_target: :input } %>
```

<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names (e.g., `_lt` for "less than").
</Tip>
</Accordion> </AccordionGroup>

Admin Users

<AccordionGroup> <Accordion title="Admin Users Actions"> `admin_users_actions`
Injects code into the page actions area for the admin users list page.

```erb
<%= link_to "Export Users", export_admin_users_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Admin Users Header"> `admin_users_header`
Injects code between the page header and the main content area for the admin users list page.

```erb
<div class="alert alert-info">
  <strong>Security:</strong> Review admin access regularly.
</div>
```
</Accordion> </AccordionGroup>

Classifications

<AccordionGroup> <Accordion title="Classifications Actions"> `classifications_actions`
Injects code into the page actions area for the classifications list page.

```erb
<%= link_to "Bulk Update", bulk_update_classifications_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Classifications Header"> `classifications_header`
Injects code between the page header and the main content area for the classifications list page.

```erb
<div class="alert alert-info">
  <strong>Tip:</strong> Use drag and drop to reorder classifications.
</div>
```
</Accordion> </AccordionGroup>

Coupon Codes

<AccordionGroup> <Accordion title="Coupon Codes Actions"> `coupon_codes_actions`
Injects code into the page actions area for the coupon codes list page.

```erb
<%= link_to "Generate Bulk Codes", bulk_generate_coupons_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Coupon Codes Header"> `coupon_codes_header`
Injects code between the page header and the main content area for the coupon codes list page.

```erb
<div class="alert alert-warning">
  <strong>Notice:</strong> Expired codes will be automatically cleaned up.
</div>
```
</Accordion> </AccordionGroup>

Custom Domains

<AccordionGroup> <Accordion title="Custom Domains Actions"> `custom_domains_actions`
Injects code into the page actions area for the custom domains list page.

```erb
<%= link_to "Verify All Domains", verify_all_domains_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Custom Domains Header"> `custom_domains_header`
Injects code between the page header and the main content area for the custom domains list page.

```erb
<div class="alert alert-info">
  <strong>SSL:</strong> SSL certificates are automatically managed.
</div>
```
</Accordion> </AccordionGroup>

Customer Returns

<AccordionGroup> <Accordion title="Customer Returns Actions"> `customer_returns_actions`
Injects code into the page actions area for the customer returns list page.

```erb
<%= link_to "Export Returns Report", export_returns_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Customer Returns Header"> `customer_returns_header`
Injects code between the page header and the main content area for the customer returns list page.

```erb
<div class="alert alert-info">
  <strong>Processing:</strong> Returns are processed within 3-5 business days.
</div>
```
</Accordion> <Accordion title="Customer Returns Filters"> `customer_returns_filters`
#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the customer returns list filters.

```erb
<%= f.spree_select :reason_eq,
    [["Damaged", "damaged"], ["Wrong Item", "wrong_item"]],
    { include_blank: true, label: "Return Reason" },
    { data: { filters_target: :input } } %>
```

<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names (e.g., `_eq` for "equals").
</Tip>
</Accordion> </AccordionGroup>

Digital Assets

<AccordionGroup> <Accordion title="Digital Assets Actions"> `digital_assets_actions`
Injects code into the page actions area for the digital assets list page.

```erb
<%= link_to "Bulk Upload", bulk_upload_assets_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Digital Assets Header"> `digital_assets_header`
Injects code between the page header and the main content area for the digital assets list page.

```erb
<div class="alert alert-info">
  <strong>Storage:</strong> Assets are stored in cloud storage with CDN.
</div>
```
</Accordion> </AccordionGroup>

Exports

<AccordionGroup> <Accordion title="Exports Actions"> `exports_actions`
Injects code into the page actions area for the exports list page.

```erb
<%= link_to "Schedule Export", new_scheduled_export_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Exports Header"> `exports_header`
Injects code between the page header and the main content area for the exports list page.

```erb
<div class="alert alert-info">
  <strong>Retention:</strong> Export files are kept for 30 days.
</div>
```
</Accordion> </AccordionGroup>

Gift Cards

<AccordionGroup> <Accordion title="Gift Cards Actions"> `gift_cards_actions`
Injects code into the page actions area for the gift cards list page.

```erb
<%= link_to "Bulk Generate", bulk_generate_gift_cards_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Gift Cards Header"> `gift_cards_header`
Injects code between the page header and the main content area for the gift cards list page.

```erb
<div class="alert alert-info">
  <strong>Security:</strong> Gift card codes are encrypted at rest.
</div>
```
</Accordion> <Accordion title="Gift Cards Filters"> `gift_cards_filters`
#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the gift cards list filters.

```erb
<%= f.spree_number_field :balance_gt,
    label: "Balance Greater Than",
    step: 0.01,
    data: { filters_target: :input } %>
```

<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names (e.g., `_gt` for "greater than").
</Tip>
</Accordion> </AccordionGroup>

Integrations

<AccordionGroup> <Accordion title="Integrations Actions"> `integrations_actions`
Injects code into the page actions area for the integrations list page.

```erb
<%= link_to "Test All Connections", test_integrations_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Integrations Header"> `integrations_header`
Injects code between the page header and the main content area for the integrations list page.

```erb
<div class="alert alert-warning">
  <strong>Status:</strong> Check integration health regularly.
</div>
```
</Accordion> </AccordionGroup>

Invitations

<AccordionGroup> <Accordion title="Invitations Actions"> `invitations_actions`
Injects code into the page actions area for the invitations list page.

```erb
<%= link_to "Resend All Pending", resend_pending_invitations_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Invitations Header"> `invitations_header`
Injects code between the page header and the main content area for the invitations list page.

```erb
<div class="alert alert-info">
  <strong>Expiry:</strong> Invitations expire after 7 days.
</div>
```
</Accordion> </AccordionGroup>

Option Types

<AccordionGroup> <Accordion title="Option Types Actions"> `option_types_actions`
Injects code into the page actions area for the option types list page.

```erb
<%= link_to "Import Options", import_option_types_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Option Types Header"> `option_types_header`
Injects code between the page header and the main content area for the option types list page.

```erb
<div class="alert alert-info">
  <strong>Variants:</strong> Option types are used to create product variants.
</div>
```
</Accordion> </AccordionGroup>

Pages

<AccordionGroup> <Accordion title="Pages Actions"> `pages_actions`
Injects code into the page actions area for the pages list page.

```erb
<%= link_to "Export Content", export_pages_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Pages Header"> `pages_header`
Injects code between the page header and the main content area for the pages list page.

```erb
<div class="alert alert-info">
  <strong>SEO:</strong> Remember to optimize page content for search engines.
</div>
```
</Accordion> </AccordionGroup>

Payment Methods

<AccordionGroup> <Accordion title="Payment Methods Actions"> `payment_methods_actions`
Injects code into the page actions area for the payment methods list page.

```erb
<%= link_to "Test All Gateways", test_payment_gateways_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Payment Methods Header"> `payment_methods_header`
Injects code between the page header and the main content area for the payment methods list page.

```erb
<div class="alert alert-warning">
  <strong>Configuration:</strong> Ensure all payment methods are properly configured.
</div>
```
</Accordion> </AccordionGroup>

Post Categories

<AccordionGroup> <Accordion title="Post Categories Actions"> `post_categories_actions`
Injects code into the page actions area for the post categories list page.

```erb
<%= link_to "Reorder Categories", reorder_post_categories_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Post Categories Header"> `post_categories_header`
Injects code between the page header and the main content area for the post categories list page.

```erb
<div class="alert alert-info">
  <strong>Organization:</strong> Use categories to organize your blog posts.
</div>
```
</Accordion> </AccordionGroup>

Posts

<AccordionGroup> <Accordion title="Posts Actions"> `posts_actions`
Injects code into the page actions area for the posts list page.

```erb
<%= link_to "Schedule Posts", schedule_posts_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Posts Header"> `posts_header`
Injects code between the page header and the main content area for the posts list page.

```erb
<div class="alert alert-info">
  <strong>Publishing:</strong> Posts can be scheduled for future publication.
</div>
```
</Accordion> <Accordion title="Posts Filters"> `posts_filters`
#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the posts list filters.

```erb
<%= f.spree_select :published_eq,
    [["Published", true], ["Draft", false]],
    { include_blank: true, label: "Publication Status" },
    { data: { filters_target: :input } } %>
```

<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names.
</Tip>
</Accordion> </AccordionGroup>

Promotions

<AccordionGroup> <Accordion title="Promotions Actions"> `promotions_actions`
Injects code into the page actions area for the promotions list page.

```erb
<%= link_to "Clone Selected", clone_promotions_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Promotions Header"> `promotions_header`
Injects code between the page header and the main content area for the promotions list page.

```erb
<div class="alert alert-info">
  <strong>Scheduling:</strong> Promotions can be scheduled to start and end automatically.
</div>
```
</Accordion> <Accordion title="Promotions Filters"> `promotions_filters`
#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the promotions list filters.

```erb
<%= f.spree_select :active_eq,
    [["Active", true], ["Inactive", false]],
    { include_blank: true, label: "Active Status" },
    { data: { filters_target: :input } } %>
```

<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names.
</Tip>
</Accordion> </AccordionGroup>

Properties

<AccordionGroup> <Accordion title="Properties Actions"> `properties_actions`
Injects code into the page actions area for the properties list page.

```erb
<%= link_to "Import Properties", import_properties_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Properties Header"> `properties_header`
Injects code between the page header and the main content area for the properties list page.

```erb
<div class="alert alert-info">
  <strong>Usage:</strong> Properties are used to add custom attributes to products.
</div>
```
</Accordion> </AccordionGroup>

Refund Reasons

<AccordionGroup> <Accordion title="Refund Reasons Actions"> `refund_reasons_actions`
Injects code into the page actions area for the refund reasons list page.

```erb
<%= link_to "Export Reasons", export_refund_reasons_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Refund Reasons Header"> `refund_reasons_header`
Injects code between the page header and the main content area for the refund reasons list page.

```erb
<div class="alert alert-info">
  <strong>Analytics:</strong> Track refund reasons to identify common issues.
</div>
```
</Accordion> </AccordionGroup>

Reimbursement Types

<AccordionGroup> <Accordion title="Reimbursement Types Actions"> `reimbursement_types_actions`
Injects code into the page actions area for the reimbursement types list page.

```erb
<%= link_to "Configure Defaults", configure_reimbursement_defaults_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Reimbursement Types Header"> `reimbursement_types_header`
Injects code between the page header and the main content area for the reimbursement types list page.

```erb
<div class="alert alert-info">
  <strong>Processing:</strong> Define how customers are reimbursed for returns.
</div>
```
</Accordion> </AccordionGroup>

Reports

<AccordionGroup> <Accordion title="Reports Actions"> `reports_actions`
Injects code into the page actions area for the reports list page.

```erb
<%= link_to "Schedule Report", schedule_report_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Reports Header"> `reports_header`
Injects code between the page header and the main content area for the reports list page.

```erb
<div class="alert alert-info">
  <strong>Automation:</strong> Reports can be scheduled to run automatically.
</div>
```
</Accordion> </AccordionGroup>

Return Authorization Reasons

<AccordionGroup> <Accordion title="Return Authorization Reasons Actions"> `return_authorization_reasons_actions`
Injects code into the page actions area for the return authorization reasons list page.

```erb
<%= link_to "Export Reasons", export_return_reasons_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Return Authorization Reasons Header"> `return_authorization_reasons_header`
Injects code between the page header and the main content area for the return authorization reasons list page.

```erb
<div class="alert alert-info">
  <strong>Policy:</strong> Define clear return reasons to streamline the process.
</div>
```
</Accordion> </AccordionGroup>

Return Authorizations

<AccordionGroup> <Accordion title="Return Authorizations Actions"> `return_authorizations_actions`
Injects code into the page actions area for the return authorizations list page.

```erb
<%= link_to "Bulk Process", bulk_process_returns_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Return Authorizations Header"> `return_authorizations_header`
Injects code between the page header and the main content area for the return authorizations list page.

```erb
<div class="alert alert-info">
  <strong>Processing:</strong> Returns are processed in order of submission.
</div>
```
</Accordion> </AccordionGroup>

Roles

<AccordionGroup> <Accordion title="Roles Actions"> `roles_actions`
Injects code into the page actions area for the roles list page.

```erb
<%= link_to "Export Permissions", export_role_permissions_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Roles Header"> `roles_header`
Injects code between the page header and the main content area for the roles list page.

```erb
<div class="alert alert-warning">
  <strong>Security:</strong> Review role permissions regularly for security.
</div>
```
</Accordion> </AccordionGroup>

Shipping Categories

<AccordionGroup> <Accordion title="Shipping Categories Actions"> `shipping_categories_actions`
Injects code into the page actions area for the shipping categories list page.

```erb
<%= link_to "Calculate Rates", calculate_shipping_rates_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Shipping Categories Header"> `shipping_categories_header`
Injects code between the page header and the main content area for the shipping categories list page.

```erb
<div class="alert alert-info">
  <strong>Organization:</strong> Use categories to group products with similar shipping requirements.
</div>
```
</Accordion> </AccordionGroup>

Shipping Methods

<AccordionGroup> <Accordion title="Shipping Methods Actions"> `shipping_methods_actions`
Injects code into the page actions area for the shipping methods list page.

```erb
<%= link_to "Test Integrations", test_shipping_integrations_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Shipping Methods Header"> `shipping_methods_header`
Injects code between the page header and the main content area for the shipping methods list page.

```erb
<div class="alert alert-info">
  <strong>Configuration:</strong> Ensure shipping methods are properly configured for all zones.
</div>
```
</Accordion> </AccordionGroup>

Stock Locations

<AccordionGroup> <Accordion title="Stock Locations Actions"> `stock_locations_actions`
Injects code into the page actions area for the stock locations list page.

```erb
<%= link_to "Sync Inventory", sync_all_locations_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Stock Locations Header"> `stock_locations_header`
Injects code between the page header and the main content area for the stock locations list page.

```erb
<div class="alert alert-info">
  <strong>Management:</strong> Stock locations help manage inventory across multiple warehouses.
</div>
```
</Accordion> </AccordionGroup>

Stock Transfers

<AccordionGroup> <Accordion title="Stock Transfers Actions"> `stock_transfers_actions`
Injects code into the page actions area for the stock transfers list page.

```erb
<%= link_to "Bulk Transfer", bulk_stock_transfer_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Stock Transfers Header"> `stock_transfers_header`
Injects code between the page header and the main content area for the stock transfers list page.

```erb
<div class="alert alert-info">
  <strong>Tracking:</strong> All stock transfers are logged for audit purposes.
</div>
```
</Accordion> <Accordion title="Stock Transfers Filters"> `stock_transfers_filters`
#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the stock transfers list filters.

```erb
<%= f.spree_select :status_eq,
    [["Pending", "pending"], ["Completed", "completed"]],
    { include_blank: true, label: "Transfer Status" },
    { data: { filters_target: :input } } %>
```

<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names.
</Tip>
</Accordion> </AccordionGroup>

Store Credit Categories

<AccordionGroup> <Accordion title="Store Credit Categories Actions"> `store_credit_categories_actions`
Injects code into the page actions area for the store credit categories list page.

```erb
<%= link_to "Set Default Category", set_default_credit_category_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Store Credit Categories Header"> `store_credit_categories_header`
Injects code between the page header and the main content area for the store credit categories list page.

```erb
<div class="alert alert-info">
  <strong>Organization:</strong> Use categories to organize different types of store credits.
</div>
```
</Accordion> </AccordionGroup>

Store Credits

<AccordionGroup> <Accordion title="Store Credits Actions"> `store_credits_actions`
Injects code into the page actions area for the store credits list page.

```erb
<%= link_to "Bulk Issue Credits", bulk_issue_credits_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Store Credits Header"> `store_credits_header`
Injects code between the page header and the main content area for the store credits list page.

```erb
<div class="alert alert-info">
  <strong>Management:</strong> Store credits can be issued for returns, promotions, or customer service.
</div>
```
</Accordion> </AccordionGroup>

Tax Categories

<AccordionGroup> <Accordion title="Tax Categories Actions"> `tax_categories_actions`
Injects code into the page actions area for the tax categories list page.

```erb
<%= link_to "Update Tax Rates", update_all_tax_rates_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Tax Categories Header"> `tax_categories_header`
Injects code between the page header and the main content area for the tax categories list page.

```erb
<div class="alert alert-warning">
  <strong>Compliance:</strong> Ensure tax categories comply with local regulations.
</div>
```
</Accordion> </AccordionGroup>

Tax Rates

<AccordionGroup> <Accordion title="Tax Rates Actions"> `tax_rates_actions`
Injects code into the page actions area for the tax rates list page.

```erb
<%= link_to "Import Tax Updates", import_tax_updates_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Tax Rates Header"> `tax_rates_header`
Injects code between the page header and the main content area for the tax rates list page.

```erb
<div class="alert alert-warning">
  <strong>Updates:</strong> Tax rates should be reviewed and updated regularly.
</div>
```
</Accordion> </AccordionGroup>

Taxonomies

<AccordionGroup> <Accordion title="Taxonomies Actions"> `taxonomies_actions`
Injects code into the page actions area for the taxonomies list page.

```erb
<%= link_to "Rebuild Tree", rebuild_taxonomy_tree_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Taxonomies Header"> `taxonomies_header`
Injects code between the page header and the main content area for the taxonomies list page.

```erb
<div class="alert alert-info">
  <strong>Navigation:</strong> Taxonomies are used to create product category navigation.
</div>
```
</Accordion> </AccordionGroup>

Themes

<AccordionGroup> <Accordion title="Themes Actions"> `themes_actions`
Injects code into the page actions area for the themes list page.

```erb
<%= link_to "Preview All", preview_all_themes_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Themes Header"> `themes_header`
Injects code between the page header and the main content area for the themes list page.

```erb
<div class="alert alert-info">
  <strong>Customization:</strong> Themes control the visual appearance of your storefront.
</div>
```
</Accordion> </AccordionGroup>

Webhooks Subscribers

<AccordionGroup> <Accordion title="Webhooks Subscribers Actions"> `webhooks_subscribers_actions`
Injects code into the page actions area for the webhooks subscribers list page.

```erb
<%= link_to "Test All Webhooks", test_all_webhooks_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Webhooks Subscribers Header"> `webhooks_subscribers_header`
Injects code between the page header and the main content area for the webhooks subscribers list page.

```erb
<div class="alert alert-warning">
  <strong>Monitoring:</strong> Monitor webhook delivery status and failures.
</div>
```
</Accordion> </AccordionGroup>

Zones

<AccordionGroup> <Accordion title="Zones Actions"> `zones_actions`
Injects code into the page actions area for the zones list page.

```erb
<%= link_to "Import Zones", import_zones_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Zones Header"> `zones_header`
Injects code between the page header and the main content area for the zones list page.

```erb
<div class="alert alert-info">
  <strong>Geography:</strong> Zones define geographic regions for shipping and taxation.
</div>
```
</Accordion> </AccordionGroup>

Products

<AccordionGroup> <Accordion title="Products Actions"> `products_actions`
Injects code into the page actions area (top right of the page) for the products list page. This is useful for adding custom buttons, export options, or other actions.

```erb
<%= link_to "Sync with PIM", sync_products_path, class: "btn btn-secondary" %>
```
</Accordion> <Accordion title="Products Header"> `products_header`
Injects code between the page header and the main content area for the products list page. This is useful for adding notifications, alerts, or additional information.

```erb
<div class="alert alert-info">
  <strong>Inventory:</strong> Product inventory is synced with warehouse systems every 15 minutes.
</div>
```
</Accordion> <Accordion title="Products Filters"> `products_filters`
<Frame>
  
</Frame>

#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

Injects code into the products list filters. This partial has access to the `f` variable, which is the form builder for the filters.

To add a new filter field, you can use the following code:

```erb
<%= f.spree_text_field :q_name_cont, data: { filters_target: :input } %>
```

<Tip>
* `q_name_cont` is the name of the filter field. For filtering we're using [ransack](/developer/core-concepts/search-filtering) gem, so the name of the filter field is the name of the attribute we're filtering by.
* `data: { filters_target: :input }` is needed for the [Stimulus Filters controller](https://github.com/spree/spree/blob/main/admin/app/javascript/spree/admin/controllers/filters_controller.js) to work.
</Tip>
</Accordion> <Accordion title="Products Page Dropdown"> `product_dropdown`
<Frame>
  
</Frame>

Injects code into the products page dropdown. This partial has access to the `product` variable.

To add an additional dropdown item, you can use the following code:

```erb
<%= link_to "View Product in WMS", "https://wms.com/products/#{product.id}", class: "dropdown-item", target: "_blank" %>
```

<Info>
Your code will be placed before the dropdown divider.
</Info>
</Accordion> <Accordion title="Products Page Form"> `product_form`
<Frame>
  
</Frame>

#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

<ParamField path="product" type="Spree::Product">
  The [Spree::Product](https://github.com/spree/spree/blob/main/core/app/models/spree/product.rb) object.
</ParamField>

Injects code into the product form. This partial has access to the `f` variable, which is the form builder for the product form, and the `product` variable.

To add a new section to the product form, you can use the following code:

```erb
<div class="card mb-6">
  <div class="card-header">
    <h5 class="card-title">ERP Integration</h5>
  </div>
  <div class="card-body">
    <%= f.spree_text_field :erp_product_id %>
  </div>
</div>
```

<Info>
  The partial will be displayed for both new product form and edit product form.
</Info>

<Tip>
  If you want to display the partial only on the edit product form, you can use the following code:

  ```erb
  <% if product.persisted? %>
    <%# ... your code ... %>
  <% end %>
  ```

  And similarly for the new product form.

  ```erb
  <% if product.new_record? %>
    <%# ... your code ... %>
  <% end %>
  ```
</Tip>
</Accordion> <Accordion title="Products Page Sidebar"> `product_form_sidebar`
<Frame>
  
</Frame>

#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

<ParamField path="product" type="Spree::Product">
  The [Spree::Product](https://github.com/spree/spree/blob/main/core/app/models/spree/product.rb) object.
</ParamField>

Injects code into the product form sidebar. This partial has access to the `f` variable, which is the form builder for the product form, and the `product` variable.

To add a new section to the product form sidebar, you can use the following code:

```erb
<div class="card mb-6">
  <div class="card-header">
    <h5 class="card-title">ERP Integration</h5>
  </div>
  <div class="card-body">
    <%= f.spree_text_field :erp_product_id %>
  </div>
</div>
```

<Info>
  The partial will be displayed for both new product form and edit product form.
</Info>

<Tip>
  If you want to display the partial only on the edit product form, you can use the following code:

  ```erb
  <% if product.persisted? %>
    <%# ... your code ... %>
  <% end %>
  ```

  And similarly for the new product form.

  ```erb
  <% if product.new_record? %>
    <%# ... your code ... %>
  <% end %>
  ```
</Tip>
</Accordion> </AccordionGroup>

Shipping Methods

<AccordionGroup> <Accordion title="Shipping Methods Form"> `shipping_method_form`
#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

<ParamField path="shipping_method" type="Spree::ShippingMethod">
  The [Spree::ShippingMethod](https://github.com/spree/spree/blob/main/core/app/models/spree/shipping_method.rb) object.
</ParamField>

Injects code into the shipping method form. This partial has access to the `f` variable, which is the form builder for the shipping method form, and the `shipping_method` variable.

To add a new section to the shipping method form, you can use the following code:

```erb
<div class="card mb-6">
  <div class="card-header">
    <h5 class="card-title">ERP Integration</h5>
  </div>
  <div class="card-body">
    <%= f.spree_text_field :erp_shipping_method_id %>
  </div>
</div>
```
</Accordion> </AccordionGroup>

Store Settings

<AccordionGroup> <Accordion title="Store Settings Form"> `store_form`
<Frame>
  
</Frame>

#### Variables

<ParamField path="f" type="Spree::Admin::FormBuilder">
  The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>

<ParamField path="store" type="Spree::Store">
  The [Spree::Store](https://github.com/spree/spree/blob/main/core/app/models/spree/store.rb) object.
</ParamField>

Injects code into the store settings form. This partial has access to the `f` variable, which is the form builder for the store form, and the `store` variable.

To add a new section to the store form, you can use the following code:

```erb
<div class="card mb-6">
  <div class="card-header">
    <h5 class="card-title">ERP Integration</h5>
  </div>
  <div class="card-body">
    <%= f.spree_text_field :erp_store_id %>
  </div>
</div>
```
</Accordion> </AccordionGroup>