Files
Odoo-Modules/fusion_accounting_ai/static/src/components/chat/interactive_table.js
gsinghpal 6c72f2ab49 refactor(fusion_accounting): move AI module code into fusion_accounting_ai sub-module
git mv preserves history. fusion_accounting/ retains only __manifest__.py,
__init__.py, CLAUDE.md, and docs/ — the meta-module shell. All Python,
data, views, security, services, static, tests, wizards, report move to
fusion_accounting_ai/. Manifest data list updated; security.xml move to
_core deferred to Task 12.

Made-with: Cursor
2026-04-18 21:45:06 -04:00

165 lines
4.3 KiB
JavaScript

/** @odoo-module **/
import { Component, useState } from "@odoo/owl";
export class FusionInteractiveTable extends Component {
static template = "fusion_accounting.InteractiveTable";
static props = ["tableData", "onTableAction"];
setup() {
const rows = (this.props.tableData.rows || []).map((row) => ({
...row,
selected: false,
userNote: "",
}));
this.state = useState({
rows,
selectAll: false,
});
}
get isInteractive() {
return this.props.tableData.mode === "interactive";
}
get columns() {
return this.props.tableData.columns || [];
}
get title() {
return this.props.tableData.title || "";
}
get actions() {
return this.props.tableData.actions || [];
}
get selectedCount() {
return this.state.rows.filter((r) => r.selected).length;
}
get hasAction() {
return (action) => this.actions.includes(action);
}
actionAvailable(action) {
return this.actions.includes(action);
}
recommendationClass(action) {
switch (action) {
case "dismiss":
return "bg-success-subtle text-success";
case "flag":
return "bg-warning-subtle text-warning";
case "create_rule":
return "bg-info-subtle text-info";
default:
return "bg-secondary-subtle text-secondary";
}
}
recommendationLabel(action) {
switch (action) {
case "dismiss":
return "Dismiss";
case "flag":
return "Flag";
case "create_rule":
return "Create Rule";
default:
return action || "Review";
}
}
onToggleSelectAll() {
const newVal = !this.state.selectAll;
this.state.selectAll = newVal;
for (const row of this.state.rows) {
row.selected = newVal;
}
}
onToggleRow(rowIndex) {
this.state.rows[rowIndex].selected = !this.state.rows[rowIndex].selected;
this.state.selectAll = this.state.rows.every((r) => r.selected);
}
onNoteInput(rowIndex, ev) {
this.state.rows[rowIndex].userNote = ev.target.value;
}
_collectSelected() {
return this.state.rows
.filter((r) => r.selected)
.map((r) => ({
id: r.id,
cells: r.cells,
recommendation: r.recommendation,
userNote: r.userNote,
}));
}
_collectAllNotes() {
return this.state.rows
.filter((r) => r.userNote.trim())
.map((r) => ({
id: r.id,
cells: r.cells,
recommendation: r.recommendation,
userNote: r.userNote,
}));
}
onApplyRecommendations() {
const selected = this._collectSelected();
if (!selected.length) return;
this.props.onTableAction({
action: "apply_recommendations",
source_tool: this.props.tableData.source_tool,
rows: selected,
});
}
onFlagSelected() {
const selected = this._collectSelected();
if (!selected.length) return;
this.props.onTableAction({
action: "flag",
source_tool: this.props.tableData.source_tool,
rows: selected,
});
}
onCreateRules() {
const selected = this._collectSelected();
if (!selected.length) return;
this.props.onTableAction({
action: "create_rule",
source_tool: this.props.tableData.source_tool,
rows: selected,
});
}
onDismissSelected() {
const selected = this._collectSelected();
if (!selected.length) return;
this.props.onTableAction({
action: "dismiss",
source_tool: this.props.tableData.source_tool,
rows: selected,
});
}
onSubmitNotes() {
const noted = this._collectAllNotes();
if (!noted.length) return;
this.props.onTableAction({
action: "submit_notes",
source_tool: this.props.tableData.source_tool,
rows: noted,
});
}
}