# List View Group Select - Architecture & Implementation Plan ## Module Overview **Name:** `list_view_group_select` **Version:** 17.0.1.0.0 **Category:** Web **Summary:** Adds group selection feature to Odoo 17 list views with recursive selection support ## Features 1. **Group Header Checkbox** - Add a checkbox in each group header to select all records in that group 2. **Recursive Selection** - Selecting a parent group selects all records in nested sub-groups 3. **Action Menu Integration** - Add "Select All Groups" option in the action menu 4. **Visual Feedback** - Show selection state (none/partial/full) for each group 5. **Compatible with Bulk Operations** - Works seamlessly with Export, Archive, Delete, etc. ## Technical Architecture ### Component Analysis (from Odoo Core) #### 1. ListRenderer (`list_renderer.js`) **Key Observations:** - Line 674-682: `selectAll` getter checks if all records are selected - Line 1867-1873: `toggleSelection()` handles selection of all records - Line 1875-1887: `toggleRecordSelection()` handles individual record selection - Line 1889-1900: `toggleRecordShiftSelection()` handles range selection - Line 661-673: `nbRecordsInGroup()` recursively counts records in groups - Line 1852-1857: `onGroupHeaderClicked()` handles group header clicks #### 2. ListController (`list_controller.js`) **Key Observations:** - Line 317-362: `getStaticActionMenuItems()` defines action menu items - Line 393-406: `onSelectDomain()` handles domain selection - Line 408-413: `onUnselectAll()` clears all selections #### 3. Group Structure Groups have the following structure: ```javascript group = { list: { records: [], // Direct records in this group groups: [], // Sub-groups (for nested grouping) isGrouped: bool // Whether this level has sub-groups }, isFolded: bool, aggregates: {}, displayName: string } ``` ### Module File Structure ``` customaddons/list_view_group_select/ ├── __init__.py # Python package init (empty) ├── __manifest__.py # Module manifest ├── README.md # User documentation ├── ARCHITECTURE.md # This file ├── static/ │ ├── description/ │ │ └── icon.png # Module icon (optional) │ └── src/ │ ├── js/ │ │ ├── list_renderer_group_select.js # Extended ListRenderer │ │ └── list_controller_group_select.js # Extended ListController │ ├── xml/ │ │ └── list_renderer_templates.xml # Template inheritance │ └── scss/ │ └── list_view_group_select.scss # Styling └── views/ └── webclient_templates.xml # Asset bundle definition ``` ## Implementation Plan ### Phase 1: Module Structure Setup #### File: `__manifest__.py` ```python { 'name': 'List View Group Select', 'version': '17.0.1.0.0', 'category': 'Web', 'summary': 'Add group selection feature to list views', 'description': """ List View Group Select ====================== Extends Odoo list views with group selection capabilities: * Add checkbox to group headers for selecting all records in a group * Recursive selection for nested groups * "Select All Groups" action in the action menu * Compatible with all bulk operations (Export, Archive, Delete, etc.) """, 'author': 'Your Company', 'website': 'https://www.example.com', 'license': 'LGPL-3', 'depends': ['web'], 'data': [ 'views/webclient_templates.xml', ], 'assets': { 'web.assets_backend': [ 'list_view_group_select/static/src/js/list_renderer_group_select.js', 'list_view_group_select/static/src/js/list_controller_group_select.js', 'list_view_group_select/static/src/xml/list_renderer_templates.xml', 'list_view_group_select/static/src/scss/list_view_group_select.scss', ], }, 'installable': True, 'application': False, 'auto_install': False, } ``` #### File: `__init__.py` ```python # -*- coding: utf-8 -*- # Empty file - this is a JavaScript-only module ``` ### Phase 2: JavaScript Implementation #### File: `static/src/js/list_renderer_group_select.js` **Key Functions to Implement:** 1. **`getAllRecordsInGroup(group)`** - Recursive helper - Traverses group hierarchy - Collects all records including nested sub-groups - Returns flat array of all records 2. **`toggleGroupSelection(group, ev)`** - Main selection logic - Gets all records using `getAllRecordsInGroup()` - Toggles selection state for all records - Updates selection state tracking 3. **`getGroupSelectionState(group)`** - Visual feedback - Returns: 'none', 'partial', 'full' - Checks if 0, some, or all records are selected - Used for checkbox visual state (unchecked/indeterminate/checked) 4. **`isGroupSelected(group)`** - Helper for templates - Returns boolean for checkbox state - Handles partially selected state **Inheritance Pattern:** ```javascript /** @odoo-module **/ import { ListRenderer } from "@web/views/list/list_renderer"; import { patch } from "@web/core/utils/patch"; patch(ListRenderer.prototype, { // Override/extend methods here getAllRecordsInGroup(group) { // Recursive implementation }, toggleGroupSelection(group, ev) { // Main selection logic }, getGroupSelectionState(group) { // Return 'none', 'partial', or 'full' }, // Other helper methods... }); ``` #### File: `static/src/js/list_controller_group_select.js` **Key Functions to Implement:** 1. **Extend `getStaticActionMenuItems()`** - Add new "Select All in Visible Groups" action - Position it appropriately (sequence ~5, before Export) - Only show when list is grouped 2. **`onSelectAllGroups()`** - New method - Iterates through all visible groups - Uses `getAllRecordsInGroup()` from renderer - Selects all records in all groups **Inheritance Pattern:** ```javascript /** @odoo-module **/ import { ListController } from "@web/views/list/list_controller"; import { patch } from "@web/core/utils/patch"; import { _t } from "@web/core/l10n/translation"; patch(ListController.prototype, { getStaticActionMenuItems() { const items = super.getStaticActionMenuItems(); // Add group selection item items.selectAllGroups = { isAvailable: () => this.model.root.isGrouped, sequence: 5, icon: "fa fa-check-square-o", description: _t("Select All in Visible Groups"), callback: () => this.onSelectAllGroups(), }; return items; }, onSelectAllGroups() { // Implementation }, }); ``` ### Phase 3: XML Template Extensions #### File: `static/src/xml/list_renderer_templates.xml` **Approach:** - Inherit/extend the `web.ListRenderer.GroupRow` template - Add checkbox element before the group name - Bind to `toggleGroupSelection` method - Apply appropriate CSS classes based on selection state **Template Structure:** ```xml
``` ### Phase 4: Styling #### File: `static/src/scss/list_view_group_select.scss` ```scss .o_list_group_selector { display: inline-block; margin-right: 8px; vertical-align: middle; input[type="checkbox"] { cursor: pointer; &:disabled { cursor: not-allowed; opacity: 0.5; } // Indeterminate state styling &:indeterminate { opacity: 0.7; } } } // Ensure group header has proper alignment .o_group_header th { .o_list_group_selector { + * { display: inline-block; } } } ``` ### Phase 5: Asset Bundle Registration #### File: `views/webclient_templates.xml` ```xml