Repository: cetmix/cetmix-tower
Pull request #295: [16.0][IMP] cetmix_tower_server-command_log_view_update
Author: login: Mohajiro
Labels: name: needs review
name: merged 🎉
name: approved
Created: 2025-05-19T09:33:55Z | Merged: 2025-05-24T08:02:20Z

Reorder Exit Code, hide Plan Log when opened from plan, 
add triggered_plan_command_ids field and view.

Task: 4697

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
	- Added a "Triggered Commands" page in the command log view, displaying related triggered commands for flight plans.
- **Improvements**
	- Reorganized field visibility and layout in the command log form for clearer information display.
	- Updated the plan log view to pass additional context when viewing command logs.
	- Renamed the "Code" page to "Commands" in the plan view for improved clarity.
- **Bug Fixes**
	- Corrected spelling of "license" to "licence" in README and description badge.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/cetmix_tower_server/README.rst b/cetmix_tower_server/README.rst
index e09e8e941..1eccc79a5 100644
--- a/cetmix_tower_server/README.rst
+++ b/cetmix_tower_server/README.rst
@@ -13,7 +13,7 @@ Cetmix Tower Server
 .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
     :target: https://odoo-community.org/page/development-status
     :alt: Beta
-.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
     :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
     :alt: License: AGPL-3
 .. |badge3| image:: https://img.shields.io/badge/github-cetmix%2Fcetmix--tower-lightgray.png?logo=github
diff --git a/cetmix_tower_server/models/cx_tower_command_log.py b/cetmix_tower_server/models/cx_tower_command_log.py
index 771ec1434..a193716b2 100644
--- a/cetmix_tower_server/models/cx_tower_command_log.py
+++ b/cetmix_tower_server/models/cx_tower_command_log.py
@@ -85,6 +85,14 @@ class CxTowerCommandLog(models.Model):
     plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log", ondelete="cascade")
     triggered_plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log")
 
+    triggered_plan_command_log_ids = fields.One2many(
+        comodel_name="cx.tower.command.log",
+        inverse_name="plan_log_id",
+        related="triggered_plan_log_id.command_log_ids",
+        readonly=True,
+        string="Triggered Flight Plan Commands",
+    )
+
     @api.depends("name", "command_id.name")
     def _compute_name(self):
         for rec in self:
diff --git a/cetmix_tower_server/readme/newsfragments/4697.feature b/cetmix_tower_server/readme/newsfragments/4697.feature
new file mode 100644
index 000000000..ffb48ef84
--- /dev/null
+++ b/cetmix_tower_server/readme/newsfragments/4697.feature
@@ -0,0 +1 @@
+Improve command log and flight plan form views
diff --git a/cetmix_tower_server/static/description/index.html b/cetmix_tower_server/static/description/index.html
index 30b37ef9d..33ab59bfc 100644
--- a/cetmix_tower_server/static/description/index.html
+++ b/cetmix_tower_server/static/description/index.html
@@ -369,7 +369,7 @@ <h1 class="title">Cetmix Tower Server</h1>
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 !! source digest: sha256:de43ff20ef97cd8b8687f6abe243cfc4b118e4a1de5851c42834db2af6fa807c
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/cetmix/cetmix-tower/tree/16.0/cetmix_tower_server"><img alt="cetmix/cetmix-tower" src="https://img.shields.io/badge/github-cetmix%2Fcetmix--tower-lightgray.png?logo=github" /></a></p>
+<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/cetmix/cetmix-tower/tree/16.0/cetmix_tower_server"><img alt="cetmix/cetmix-tower" src="https://img.shields.io/badge/github-cetmix%2Fcetmix--tower-lightgray.png?logo=github" /></a></p>
 <p><a class="reference external" href="https://cetmix.com/tower">Cetmix Tower</a> offers a streamlined
 solution for managing remote servers and applications via SSH or API
 calls directly from <a class="reference external" href="https://odoo.com">Odoo</a>. It is designed for
diff --git a/cetmix_tower_server/views/cx_tower_command_log_view.xml b/cetmix_tower_server/views/cx_tower_command_log_view.xml
index 721f748a0..8d6c743b0 100644
--- a/cetmix_tower_server/views/cx_tower_command_log_view.xml
+++ b/cetmix_tower_server/views/cx_tower_command_log_view.xml
@@ -56,8 +56,8 @@
                                 attrs="{'invisible': [('use_sudo', '=', False)]}"
                             />
                             <field
-                                name="command_status"
-                                attrs="{'invisible': [('is_running', '=', True)]}"
+                                name="plan_log_id"
+                                invisible="context.get('opened_from_plan', False)"
                             />
                             <field
                                 name="triggered_plan_log_id"
@@ -72,16 +72,18 @@
                             <field name="start_date" />
                             <field name="finish_date" />
                             <field name="duration_current" />
+                             <field
+                                name="command_status"
+                                attrs="{'invisible': [('is_running', '=', True)]}"
+                            />
                         </group>
                     </group>
-                    <group>
-                        <field
-                            name="plan_log_id"
-                            attrs="{'invisible': [('plan_log_id', '=', False)]}"
-                        />
-                    </group>
-                    <notebook attrs="{'invisible': [('command_action', '=', 'plan')]}">
-                        <page name="result" string="Result">
+                    <notebook>
+                        <page
+                            name="result"
+                            string="Result"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field
                                 name="command_response"
                                 attrs="{'invisible': [('command_response', '=', False)]}"
@@ -91,9 +93,19 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
+                            <field name="triggered_plan_command_log_ids" />
+                        </page>
                     </notebook>
                 </sheet>
             </form>
diff --git a/cetmix_tower_server/views/cx_tower_plan_log_view.xml b/cetmix_tower_server/views/cx_tower_plan_log_view.xml
index 56664aef4..d69d88f1c 100644
--- a/cetmix_tower_server/views/cx_tower_plan_log_view.xml
+++ b/cetmix_tower_server/views/cx_tower_plan_log_view.xml
@@ -54,7 +54,10 @@
                             <field name="finish_date" />
                             <field name="duration_current" />
                         </group>
-                        <field name="command_log_ids">
+                        <field
+                            name="command_log_ids"
+                            context="{'opened_from_plan': True}"
+                        >
                             <tree
                                 decoration-danger="command_status not in [0, -205]"
                                 decoration-info="is_running == True"
diff --git a/cetmix_tower_server/views/cx_tower_plan_view.xml b/cetmix_tower_server/views/cx_tower_plan_view.xml
index 24279411f..b752d917b 100644
--- a/cetmix_tower_server/views/cx_tower_plan_view.xml
+++ b/cetmix_tower_server/views/cx_tower_plan_view.xml
@@ -71,7 +71,7 @@
                         </group>
                     </group>
                     <notebook>
-                        <page name="plan_lines" string="Code">
+                        <page name="plan_lines" string="Commands">
                             <field name="line_ids">
                                 <tree decoration-bf="action=='plan'">
                                     <field name="sequence" widget="handle" />


Reviews:
user: login: ivs-cetmix
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T10:35:37Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T17:29:31Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T17:29:38Z
user: login: ivs-cetmix
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T08:59:16Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro (Legacy)**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 0514f2a4dfaa7751266cca6b0e159cb9a428ff4a and 72af8cbe072658a6586359fba7b7d123af51b055.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `cetmix_tower_server/views/cx_tower_command_log_view.xml` (3 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: test with OCB
* GitHub Check: test with Odoo

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>cetmix_tower_server/views/cx_tower_command_log_view.xml (3)</summary>

`75-78`: **Conditional visibility for status is appropriate**  
Hiding the `command_status` field while the command is running keeps the focus on progress. The `attrs="{'invisible': [('is_running','=',True)]}"` rule aligns with the desired UX.

---

`81-85`: **Page-level invisibility for 'Result' improves clarity**  
Removing the notebook’s global `attrs` in favor of page-specific `attrs` on the "Result" page cleanly hides it for plan commands (`command_action='plan'`) and makes the view easier to maintain.

---

`96-100`: **Hide 'Command' page for plan actions**  
Applying `attrs="{'invisible': [('command_action','=','plan')]}"` on the "Command" page ensures it only appears for execution-type commands, matching the updated UX flow.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-20T13:51:19Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T13:58:47Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-20T13:59:11Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T13:59:33Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-20T13:59:50Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T14:10:03Z
user: login: ivs-cetmix
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T15:23:51Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T16:34:08Z
user: login: ivs-cetmix
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T16:36:39Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T17:39:41Z
user: login: ivs-cetmix
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T17:52:42Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T06:50:53Z
user: login: ivs-cetmix
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T09:53:02Z
user: login: ivs-cetmix
body: Code review LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T11:09:51Z
user: login: Aldeigja
body: Functional LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T21:55:14Z
user: login: ivs-cetmix
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T10:24:08Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T12:06:46Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between e5a24ec758a06060379ee1d09cf7884df126d3e9 and c66ac3cf7947c4480d01178f2b8e5eff8f75a8a8.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `cetmix_tower_server/README.rst` (1 hunks)
* `cetmix_tower_server/models/cx_tower_command_log.py` (1 hunks)
* `cetmix_tower_server/readme/newsfragments/4697.feature` (1 hunks)
* `cetmix_tower_server/static/description/index.html` (1 hunks)
* `cetmix_tower_server/views/cx_tower_command_log_view.xml` (3 hunks)
* `cetmix_tower_server/views/cx_tower_plan_log_view.xml` (1 hunks)
* `cetmix_tower_server/views/cx_tower_plan_view.xml` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/static/description/index.html`: Never check this file.</summary>

> `**/static/description/index.html`: Never check this file.

- `cetmix_tower_server/static/description/index.html`

</details>
<details>
<summary>`**/README.rst`: Never check this file</summary>

> `**/README.rst`: Never check this file

- `cetmix_tower_server/README.rst`

</details>

</details><details>
<summary>🪛 GitHub Actions: pre-commit</summary>

<details>
<summary>cetmix_tower_server/readme/newsfragments/4697.feature</summary>

[error] 1-1: fix end of files hook failed and modified the file to add a newline at the end. Run 'pre-commit run --all-files' locally to reproduce.

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: test with OCB
* GitHub Check: test with Odoo

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>cetmix_tower_server/models/cx_tower_command_log.py (1)</summary>

`88-94`: **LGTM! Field implementation follows previous review feedback.**

The `triggered_plan_command_log_ids` field has been correctly implemented as a related One2many field, incorporating all the suggestions from previous reviews:
- Uses related field approach instead of compute method
- Has proper naming with `_log_ids` suffix 
- Is appropriately marked as readonly
- Provides clear string description

</details>
<details>
<summary>cetmix_tower_server/views/cx_tower_plan_log_view.xml (1)</summary>

`57-60`: **Context Propagation for Nested Logs:** Passing `{'opened_from_plan': True}` to `command_log_ids` ensures the nested command log widget can adjust its behavior (e.g., hiding the plan link). The key matches usage in the command log view; this change aligns with the PR goal of hiding the plan link when opened from a plan.

</details>
<details>
<summary>cetmix_tower_server/views/cx_tower_command_log_view.xml (4)</summary>

`59-61`: **Hide Plan Link When Context Indicates Plan Origin:** Using `invisible="context.get('opened_from_plan', False)"` on `plan_log_id` respects the incoming context to conditionally hide this field when navigating from a plan. This aligns with the PR objective.

---

`75-78`: **Conditional Visibility for Command Status:** The `command_status` field is now hidden while `is_running == True`, which simplifies the UI during execution. This change improves clarity by only showing status once the command finishes.

---

`81-100`: **Granular Page Visibility:** Removed global notebook invisibility and added per-page `attrs` to hide the "Result" and "Command" pages when `command_action == 'plan'`. This modular approach enhances maintainability and makes each page's visibility rule explicit.

---

`103-107`: **Triggered Commands Tab:** The new page for `triggered_plan_command_log_ids` is correctly conditionally shown when `command_action == 'plan'` and inherits the global tree view configuration. Verify that the default layout meets requirements; if a custom column set or default ordering (e.g., by `start_date`) is needed for clarity, consider adding an inline `<tree>`.

</details>
<details>
<summary>cetmix_tower_server/static/description/index.html (1)</summary>

`372-372`: **Skipped review per coding guidelines.**  
This file matches `**/static/description/index.html` and should not be reviewed.

</details>
<details>
<summary>cetmix_tower_server/README.rst (1)</summary>

`16-16`: **Skipped review per coding guidelines.**  
This file matches `**/README.rst` and should not be reviewed.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-24T07:45:42Z
user: login: Mohajiro
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-24T07:56:46Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-24T07:57:14Z
user: login: ivs-cetmix
body: /ocabot merge patch
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-24T07:58:56Z

Review comments:
diff_hunk: @@ -222,3 +228,14 @@ def _command_finished(self):
         for rec in self:
             if rec.plan_log_id:  # type: ignore
                 rec.plan_log_id._plan_command_finished(rec)  # type: ignore
+
+    @api.depends("command_action", "triggered_plan_log_id")
+    def _compute_triggered_plan_commands(self):
+        """Set triggered_plan_command_ids to commands of the triggered flight plan."""
+        for rec in self:
+            if rec.command_action == "plan" and rec.triggered_plan_log_id:
+                rec.triggered_plan_command_ids = self.search(
path: cetmix_tower_server/models/cx_tower_command_log.py
user: login: ivs-cetmix
body: You should use "mapped" instead because it will benefit from ORM caching:

```python
rec.triggered_plan_command_ids = rec.triggered_plan_log_id.mapped("command_log_ids")
```

Starting Odoo 16.0 you can do it even easier:

```Python
rec.triggered_plan_command_ids = rec.triggered_plan_log_id.command_log_ids
```
created_at: 2025-05-19T10:34:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -85,6 +85,12 @@ class CxTowerCommandLog(models.Model):
     plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log", ondelete="cascade")
     triggered_plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log")
 
+    triggered_plan_command_ids = fields.One2many(
+        "cx.tower.command.log",
+        "plan_log_id",
+        compute="_compute_triggered_plan_commands",
path: cetmix_tower_server/models/cx_tower_command_log.py
user: login: ivs-cetmix
body: try to use related field instead:

```python
related=triggered_plan_log_id.command_log_ids,
readonly=True
```
created_at: 2025-05-19T10:35:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -222,3 +228,14 @@ def _command_finished(self):
         for rec in self:
             if rec.plan_log_id:  # type: ignore
                 rec.plan_log_id._plan_command_finished(rec)  # type: ignore
+
+    @api.depends("command_action", "triggered_plan_log_id")
+    def _compute_triggered_plan_commands(self):
+        """Set triggered_plan_command_ids to commands of the triggered flight plan."""
+        for rec in self:
+            if rec.command_action == "plan" and rec.triggered_plan_log_id:
+                rec.triggered_plan_command_ids = self.search(
path: cetmix_tower_server/models/cx_tower_command_log.py
user: login: Mohajiro
body: Thank you, done.
created_at: 2025-05-19T17:29:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -85,6 +85,12 @@ class CxTowerCommandLog(models.Model):
     plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log", ondelete="cascade")
     triggered_plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log")
 
+    triggered_plan_command_ids = fields.One2many(
+        "cx.tower.command.log",
+        "plan_log_id",
+        compute="_compute_triggered_plan_commands",
path: cetmix_tower_server/models/cx_tower_command_log.py
user: login: Mohajiro
body: Done, thanks.
created_at: 2025-05-19T17:29:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -91,9 +97,28 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
+                            <field name="triggered_plan_command_ids">
+                            <tree>
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: ivs-cetmix
body: Please use the same tree view configuration as it is used in the Flight Plan log:
![image](https://github.com/user-attachments/assets/71a4b448-09df-4521-bbf9-c7633e3ae0f6)

created_at: 2025-05-20T08:59:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -91,9 +93,35 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Add `name` attribute to new 'Triggered Commands' page**  
The new page correctly appears only for plan actions, but omits a `name` attribute. Defining `name="triggered_commands"` (or a similar unique identifier) helps with future overrides and consistency:  
```xml
<page name="triggered_commands" string="Triggered Commands" attrs="{'invisible':[('command_action','!=','plan')]}">
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In cetmix_tower_server/views/cx_tower_command_log_view.xml around lines 103 to
106, the new page element for "Triggered Commands" is missing a name attribute.
Add a unique name attribute such as name="triggered_commands" to the page tag to
ensure consistency and enable easier future overrides.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-20T13:51:18Z
author_association: NONE
diff_hunk: @@ -56,8 +56,8 @@
                                 attrs="{'invisible': [('use_sudo', '=', False)]}"
                             />
                             <field
-                                name="command_status"
-                                attrs="{'invisible': [('is_running', '=', True)]}"
+                                name="plan_log_id"
+                                invisible="context.get('opened_from_plan', False)"
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Use model boolean field for dynamic invisibility**  
You're using a static `invisible` attribute with a Python context lookup:  
```xml
<field name="plan_log_id" invisible="context.get('opened_from_plan', False)"/>
```  
Odoo's UI layering favors the `attrs` mechanism and your computed boolean field `opened_from_plan`. This improves readability and ensures consistency with other dynamic field visibility rules.  
Proposed diff:  
```diff
- <field name="plan_log_id" invisible="context.get('opened_from_plan', False)"/>
+ <field name="plan_log_id" attrs="{'invisible': [('opened_from_plan', '=', True)]}"/>
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In cetmix_tower_server/views/cx_tower_command_log_view.xml around lines 59 to
60, replace the static invisible attribute using context.get with a dynamic
visibility rule using the attrs mechanism tied to the model's boolean field
opened_from_plan. Change the field definition to use attrs with {'invisible':
[('opened_from_plan', '=', True)]} to leverage Odoo's UI layering and improve
readability and consistency.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-20T13:51:18Z
author_association: NONE
diff_hunk: @@ -91,9 +93,35 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
+                            <field name="triggered_plan_command_ids">
+                                <tree
+                                    decoration-danger="command_status not in [0, -205]"
+                                    decoration-info="is_running == True"
+                                    decoration-muted="command_status == -205"
+                                    default_order="id asc"
+                                >
+                                    <field name="id" invisible="1" />
+                                    <field name="command_id" optional="show" />
+                                    <field name="command_action" optional="show" />
+                                    <field name="start_date" optional="hide" />
+                                    <field name="finish_date" optional="hide" />
+                                    <field name="duration_current" optional="show" />
+                                    <field name="command_status" optional="show" />
+                                    <field name="is_running" optional="hide" />
+                                </tree>
+                            </field>
+                        </page>
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Optional: Use chronological ordering for triggered commands**  
The inline tree orders by `id asc`, which may not reflect actual execution time. Consider sorting by `start_date` for a more intuitive timeline:  

```diff
- <tree
-     decoration-danger="command_status not in [0, -205]"
-     decoration-info="is_running == True"
-     decoration-muted="command_status == -205"
-     default_order="id asc"
->
+ <tree
+     decoration-danger="command_status not in [0, -205]"
+     decoration-info="is_running == True"
+     decoration-muted="command_status == -205"
+     default_order="start_date asc"
+>
```  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
    <field name="triggered_plan_command_ids">
        <tree
            decoration-danger="command_status not in [0, -205]"
            decoration-info="is_running == True"
            decoration-muted="command_status == -205"
            default_order="start_date asc"
        >
            <field name="id" invisible="1" />
            <field name="command_id" optional="show" />
            <field name="command_action" optional="show" />
            <field name="start_date" optional="hide" />
            <field name="finish_date" optional="hide" />
            <field name="duration_current" optional="show" />
            <field name="command_status" optional="show" />
            <field name="is_running" optional="hide" />
        </tree>
    </field>
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In cetmix_tower_server/views/cx_tower_command_log_view.xml between lines 107 and
124, the inline tree for triggered_plan_command_ids currently orders by id
ascending, which may not represent the actual execution timeline. Change the
default_order attribute from "id asc" to "start_date asc" to sort the commands
chronologically by their start date for better clarity.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 53544ee
created_at: 2025-05-20T13:51:18Z
author_association: NONE
diff_hunk: @@ -56,8 +56,8 @@
                                 attrs="{'invisible': [('use_sudo', '=', False)]}"
                             />
                             <field
-                                name="command_status"
-                                attrs="{'invisible': [('is_running', '=', True)]}"
+                                name="plan_log_id"
+                                invisible="context.get('opened_from_plan', False)"
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: Mohajiro
body: In this case we intentionally chose this option because it allows us to avoid adding a purely UI-related computed field to the model
created_at: 2025-05-20T13:58:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -56,8 +56,8 @@
                                 attrs="{'invisible': [('use_sudo', '=', False)]}"
                             />
                             <field
-                                name="command_status"
-                                attrs="{'invisible': [('is_running', '=', True)]}"
+                                name="plan_log_id"
+                                invisible="context.get('opened_from_plan', False)"
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: coderabbitai[bot]
body: The model file doesn't contain this computed field, so I understand that's why you're using the context approach instead. You're right that this avoids adding a purely UI-related computed field to the model, which is a cleaner solution in this case.

The context-based visibility is perfectly valid when the condition is truly a UI-level concern (like "opened from another view") rather than a business logic property of the record itself.

@Mohajiro I'll make note of your approach. Thanks for explaining your implementation choice!

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: Mohajiro
PR: cetmix/cetmix-tower#295
File: cetmix_tower_server/views/cx_tower_command_log_view.xml:59-60
Timestamp: 2025-05-20T13:59:09.668Z
Learning: In Odoo views, using `invisible="context.get('some_key', False)"` is preferred over adding a purely UI-related computed field to the model when the visibility condition is specific to the UI context rather than being an intrinsic property of the record.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-20T13:59:11Z
author_association: NONE
diff_hunk: @@ -91,9 +93,35 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: Mohajiro
body: I don't want to touch existing code, mate.
created_at: 2025-05-20T13:59:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -91,9 +93,35 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: coderabbitai[bot]
body: @Mohajiro I understand your preference not to touch existing code beyond what's necessary. That's a valid approach to minimize risk. The missing name attribute is just a nitpick for consistency, not a functional issue, so it's perfectly fine to proceed without it.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: Mohajiro
PR: cetmix/cetmix-tower#295
File: cetmix_tower_server/views/cx_tower_command_log_view.xml:103-106
Timestamp: 2025-05-20T13:59:49.655Z
Learning: Mohajiro prefers to minimize changes to existing code beyond what's necessary for the PR's objectives, focusing only on the required functionality changes.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-20T13:59:50Z
author_association: NONE
diff_hunk: @@ -91,9 +97,28 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
+                            <field name="triggered_plan_command_ids">
+                            <tree>
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: Mohajiro
body: Done. 
created_at: 2025-05-20T14:10:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -91,9 +93,35 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
+                            <field name="triggered_plan_command_ids">
+                                <tree
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: ivs-cetmix
body: You don't need to add these fields explicitly. Just `<field name="triggered_plan_command_ids"/>` will do the job.
The [default tree view](https://github.com/cetmix/cetmix-tower/blob/0b064a622fa9ee992fe7027cf261173c2414ddba/cetmix_tower_server/views/cx_tower_command_log_view.xml#L103) will be used automatically.
created_at: 2025-05-20T15:21:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -91,9 +93,35 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
+                            <field name="triggered_plan_command_ids">
+                                <tree
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: Mohajiro
body: We will keep the standard tree view for the model globally.
If we need the exact same columns and decorations as in the Flight Plan Log, we can simply embed that inline <tree> definition directly under <field name="triggered_plan_command_ids"/>.
In your last comment, did you mean to replace the <tree> for the entire Command Log view, rather than just the one under the ‘Triggered Commands’ tab?
created_at: 2025-05-20T16:34:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -91,9 +93,35 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
+                            <field name="triggered_plan_command_ids">
+                                <tree
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: ivs-cetmix
body: You simply don't need to add the `<tree>` element. Just the field definition. As this is a o2m field Odoo will use a list view of that model automatically.
created_at: 2025-05-20T16:36:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -91,9 +93,35 @@
                                 attrs="{'invisible': [('command_error', '=', False)]}"
                             />
                         </page>
-                        <page name="code" string="Command">
+                        <page
+                            name="code"
+                            string="Command"
+                            attrs="{'invisible': [('command_action', '=', 'plan')]}"
+                        >
                             <field name="code" />
                         </page>
+                          <page
+                            string="Triggered Commands"
+                            attrs="{'invisible': [('command_action','!=','plan')]}"
+                        >
+                            <field name="triggered_plan_command_ids">
+                                <tree
path: cetmix_tower_server/views/cx_tower_command_log_view.xml
user: login: Mohajiro
body: If I remove the <tree> definition under triggered_plan_command_ids, Odoo will fall back to the global tree (cx_tower_command_log_view_tree) for the cx.tower.command.log model. However, in your [comment](https://github.com/cetmix/cetmix-tower/pull/295#discussion_r2097418777) you asked to “use the same tree view configuration as it is used in the Flight Plan log.” Removing the inline <tree> means it will not inherit the Flight Plan Log’s columns and decorations.

Did you actually mean that I should override the global tree view for the entire cx.tower.command.log model to match the Flight Plan Log configuration?

PS I deleted <tree></tree> for <field name="triggered_plan_command_ids" />
created_at: 2025-05-20T17:39:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -85,6 +85,14 @@ class CxTowerCommandLog(models.Model):
     plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log", ondelete="cascade")
     triggered_plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log")
 
+    triggered_plan_command_ids = fields.One2many(
path: cetmix_tower_server/models/cx_tower_command_log.py
user: login: ivs-cetmix
body: `triggered_plan_command_log_ids` because `comodel_name="cx.tower.command.log"`
created_at: 2025-05-20T17:52:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -85,6 +85,14 @@ class CxTowerCommandLog(models.Model):
     plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log", ondelete="cascade")
     triggered_plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log")
 
+    triggered_plan_command_ids = fields.One2many(
path: cetmix_tower_server/models/cx_tower_command_log.py
user: login: Mohajiro
body: Thanks you for tour proposal, done.
created_at: 2025-05-21T06:50:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -85,6 +85,14 @@ class CxTowerCommandLog(models.Model):
     plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log", ondelete="cascade")
     triggered_plan_log_id = fields.Many2one(comodel_name="cx.tower.plan.log")
 
+    triggered_plan_log_command_ids = fields.One2many(
path: cetmix_tower_server/models/cx_tower_command_log.py
user: login: ivs-cetmix
body: `triggered_plan_command_log_ids`
created_at: 2025-05-21T09:52:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -111,7 +111,7 @@
                     <notebook>
                         <page
                             name="code"
-                            string="Code"
+                            string="Commands"
path: cetmix_tower_server/views/cx_tower_command_view.xml
user: login: ivs-cetmix
body: This is a wrong view. You need to update the flight [plan view](https://github.com/cetmix/cetmix-tower/blob/4445855415892935f062d165de85d8d322ada2d7/cetmix_tower_server/views/cx_tower_plan_view.xml#L74) instead.
created_at: 2025-05-23T10:24:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -111,7 +111,7 @@
                     <notebook>
                         <page
                             name="code"
-                            string="Code"
+                            string="Commands"
path: cetmix_tower_server/views/cx_tower_command_view.xml
user: login: Mohajiro
body: I see, it's fixed. 
Thanks!
created_at: 2025-05-23T12:06:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1 @@
+Improve command log and flight plan form views
path: cetmix_tower_server/readme/newsfragments/4697.feature
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix missing newline at end of file.**

The pre-commit hook failed because the file is missing a trailing newline. This is a standard requirement for text files.



Add a newline at the end of the file:

```diff
-Improve command log and flight plan form views
+Improve command log and flight plan form views

```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
Improve command log and flight plan form views

```

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Actions: pre-commit</summary>

[error] 1-1: fix end of files hook failed and modified the file to add a newline at the end. Run 'pre-commit run --all-files' locally to reproduce.

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In cetmix_tower_server/readme/newsfragments/4697.feature at line 1, the file is
missing a trailing newline at the end, which causes the pre-commit hook to fail.
Add a single newline character at the end of the file to comply with standard
text file formatting requirements.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 939fe0b
created_at: 2025-05-24T07:45:41Z
author_association: NONE
diff_hunk: @@ -71,7 +71,7 @@
                         </group>
                     </group>
                     <notebook>
-                        <page name="plan_lines" string="Code">
+                        <page name="plan_lines" string="Commands">
path: cetmix_tower_server/views/cx_tower_plan_view.xml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**UI Label Update:** Changed the notebook page label from "Code" to "Commands" to better reflect its contents. Remember to update any translation entries to localize this new label.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In cetmix_tower_server/views/cx_tower_plan_view.xml at line 74, the notebook
page label was changed from "Code" to "Commands". To fix this, update the
corresponding translation entries in the localization files to reflect the new
label "Commands" so that it is properly localized in all supported languages.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-24T07:45:42Z
author_association: NONE
diff_hunk: @@ -71,7 +71,7 @@
                         </group>
                     </group>
                     <notebook>
-                        <page name="plan_lines" string="Code">
+                        <page name="plan_lines" string="Commands">
path: cetmix_tower_server/views/cx_tower_plan_view.xml
user: login: Mohajiro
body: Thank you, I'll ask my team-leader.
created_at: 2025-05-24T07:56:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -71,7 +71,7 @@
                         </group>
                     </group>
                     <notebook>
-                        <page name="plan_lines" string="Code">
+                        <page name="plan_lines" string="Commands">
path: cetmix_tower_server/views/cx_tower_plan_view.xml
user: login: coderabbitai[bot]
body: @Mohajiro sounds good! Translation updates are definitely worth coordinating with the team, especially if you have established localization workflows or specific translation files to maintain consistency across the application.


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@Mohajiro sounds good! Translation updates are definitely worth coordinating with the team, especially if you have established localization workflows or specific translation files to maintain consistency across the application.</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-24T07:57:13Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-19T09:34:01Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

A new readonly one2many related field was introduced to the command log model for accessing triggered command logs. The command log form view was reorganized for improved field visibility and now includes a new page to display triggered commands. Minor UI and context updates were made in related plan log and plan views. Additionally, spelling corrections were applied to license badges in documentation and static files, and a new feature newsfragment was added.

## Changes

| File(s)                                                                                       | Change Summary                                                                                                                                                                                                                                    |
|----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| cetmix_tower_server/models/cx_tower_command_log.py                                           | Added a readonly one2many related field `triggered_plan_command_log_ids` to the `CxTowerCommandLog` model for accessing command logs linked by `plan_log_id` to the referenced flight plan.                                                       |
| cetmix_tower_server/views/cx_tower_command_log_view.xml                                      | Updated the form view: reorganized field visibility, moved fields between groups, added a new "Triggered Commands" page with a tree view of the new field, and adjusted notebook/page visibility conditions.                                       |
| cetmix_tower_server/views/cx_tower_plan_log_view.xml                                         | Added a context attribute `{'opened_from_plan': True}` to the `command_log_ids` field in the plan log form view for context-aware rendering of the nested command log tree view.                                                                  |
| cetmix_tower_server/views/cx_tower_plan_view.xml                                             | Changed the notebook page label from "Code" to "Commands" in the plan form view; no structural or behavioral modifications.                                                                                                                       |
| cetmix_tower_server/README.rst, cetmix_tower_server/static/description/index.html            | Corrected spelling of "license" to "licence" in badge URLs and alt text in README and static HTML description files.                                                                                                                             |
| cetmix_tower_server/readme/newsfragments/4697.feature                                       | Added a new feature newsfragment describing improvements to command log and flight plan form views.                                                                                                                                               |

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between c66ac3cf7947c4480d01178f2b8e5eff8f75a8a8 and 939fe0b1a9a7cec1f044b6778ca7b080b429f428.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `cetmix_tower_server/README.rst` (1 hunks)
* `cetmix_tower_server/models/cx_tower_command_log.py` (1 hunks)
* `cetmix_tower_server/readme/newsfragments/4697.feature` (1 hunks)
* `cetmix_tower_server/static/description/index.html` (1 hunks)
* `cetmix_tower_server/views/cx_tower_command_log_view.xml` (3 hunks)
* `cetmix_tower_server/views/cx_tower_plan_log_view.xml` (1 hunks)
* `cetmix_tower_server/views/cx_tower_plan_view.xml` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/README.rst`: Never check this file</summary>

> `**/README.rst`: Never check this file

- `cetmix_tower_server/README.rst`

</details>
<details>
<summary>`**/static/description/index.html`: Never check this file.</summary>

> `**/static/description/index.html`: Never check this file.

- `cetmix_tower_server/static/description/index.html`

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: test with OCB
* GitHub Check: test with Odoo

</details>

<details>
<summary>🔇 Additional comments (10)</summary><blockquote>

<details>
<summary>cetmix_tower_server/README.rst (1)</summary>

`1-137`: The file `cetmix_tower_server/README.rst` matches the ignore pattern `**/README.rst` and is auto-generated; skipping review as per coding guidelines.

</details>
<details>
<summary>cetmix_tower_server/static/description/index.html (1)</summary>

`1-503`: The file `cetmix_tower_server/static/description/index.html` matches the ignore pattern `**/static/description/index.html`; skipping review as per coding guidelines.

</details>
<details>
<summary>cetmix_tower_server/models/cx_tower_command_log.py (1)</summary>

`88-94`: **LGTM! Field implementation follows best practices.**

The `triggered_plan_command_log_ids` field is correctly implemented as a readonly related field, which is more efficient than using computed fields. The field properly links to command logs of the triggered flight plan.

</details>
<details>
<summary>cetmix_tower_server/readme/newsfragments/4697.feature (1)</summary>

`1-2`: **LGTM! Newsfragment properly formatted.**

The trailing newline issue from the previous review has been addressed, and the content appropriately describes the feature improvements.

</details>
<details>
<summary>cetmix_tower_server/views/cx_tower_plan_log_view.xml (1)</summary>

`57-60`: **LGTM! Context-aware UI enhancement.**

Adding the `opened_from_plan` context is a clean approach to enable conditional field visibility in the command log form view when accessed from a plan log. This enhances the user experience by providing contextual information.

</details>
<details>
<summary>cetmix_tower_server/views/cx_tower_command_log_view.xml (5)</summary>

`59-61`: **Accept context-based field invisibility**  
Using `invisible="context.get('opened_from_plan', False)"` on the `plan_log_id` field is appropriate for this UI-level condition and aligns with the preference to avoid adding model-level computed fields for purely visual logic.

---

`75-78`: **Correct repositioning and visibility of command status**  
Moving `command_status` into the second group and hiding it when `is_running` is true ensures the status isn’t shown while a command is in progress, complementing the ribbon display above.

---

`81-86`: **Hide Result page for plan actions**  
The `Result` page is now correctly invisible when `command_action='plan'`, keeping the UI focused on relevant data per action type.

---

`96-100`: **Hide Command code page for plan actions**  
The `Command` (code) page is also properly hidden for plan-triggered commands, matching the updated `Result` page behavior.

---

`103-108`: **Triggered Commands page added**  
The new “Triggered Commands” page appears only for plan actions and surfaces the related one2many field `triggered_plan_command_log_ids`. This satisfies the PR objective of exposing triggered commands without over-modifying existing views.

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=cetmix/cetmix-tower&utm_content=295):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: CetmixGitDrone
created_at: 2025-05-24T07:59:01Z
body: What a great day to merge this nice PR. Let's do it!
Prepared branch [16.0-ocabot-merge-pr-295-by-ivs-cetmix-bump-patch](https://github.com/cetmix/cetmix-tower/commits/16.0-ocabot-merge-pr-295-by-ivs-cetmix-bump-patch), awaiting test results.
author_association: NONE
user: login: CetmixGitDrone
created_at: 2025-05-24T08:02:20Z
body: Congratulations, your PR was merged at fd8881fc54375eff05cb6e2322ef535752b91404. Thanks a lot for contributing to cetmix. ❤️
author_association: NONE