diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 81d8db8..7369030 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,509 +1,509 @@ -# 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 - - -