-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[MIG] web_widget_x2_many_2d_matrix: Migration to 16.0
[MIG] web_widget_x2_many_2d_matrix: Migration to 16.0 (WIP, columns) [MIG] web_widget_x2_many_2d_matrix: Migration to 16.0 (WIP, rows) [MIG] web_widget_x2_many_2d_matrix: Migration to 16.0 (WIP, add value component) Aggregated values [MIG] web_widget_x2many_2d_matrix: Fix commitChanges of matrix. [FIX] Fix commitChanges [FIX] setDirty [FIX] Aggregated values [IMP] readonly working [FIX] Update matrix on changing props [FIX] Remove old files [IMP] Run precommit stuff [FIX] Remove deprecated readme sections [MIG] Migrate show_row_totals and show_column_totals attributes [MIG] sticky headers Fixup Fixup Fixup
- Loading branch information
Showing
11 changed files
with
326 additions
and
929 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
...many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.esm.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/** @odoo-module **/ | ||
|
||
import {Component} from "@odoo/owl"; | ||
import {standardFieldProps} from "@web/views/fields/standard_field_props"; | ||
import {registry} from "@web/core/registry"; | ||
import {archParseBoolean} from "@web/views/utils"; | ||
import {X2Many2DMatrixRenderer} from "@web_widget_x2many_2d_matrix/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm"; | ||
|
||
export class X2Many2DMatrixField extends Component { | ||
setup() { | ||
this.activeField = this.props.record.activeFields[this.props.name]; | ||
} | ||
|
||
getList() { | ||
return this.props.value; | ||
} | ||
|
||
get list() { | ||
return this.getList(); | ||
} | ||
|
||
_getDefaultRecordValues() { | ||
return {}; | ||
} | ||
|
||
async commitChange(x, y, value) { | ||
const fields = this.props.matrixFields; | ||
|
||
const values = this._getDefaultRecordValues(); | ||
values[fields.x] = x; | ||
values[fields.y] = y; | ||
|
||
const matchingRecords = this.list.records.filter( | ||
(record) => record.data[fields.x] === x && record.data[fields.y] === y | ||
); | ||
if (matchingRecords.length === 1) { | ||
values[fields.value] = value; | ||
await matchingRecords[0].update(values); | ||
} else { | ||
let total = 0; | ||
if (matchingRecords.length) { | ||
total = matchingRecords | ||
.map((r) => r.data[fields.value]) | ||
.reduce((aggr, v) => aggr + v); | ||
} | ||
const diff = value - total; | ||
values[fields.value] = diff; | ||
const record = await this.list.addNew({ | ||
mode: "edit", | ||
}); | ||
await record.update(values); | ||
} | ||
this.props.setDirty(false); | ||
} | ||
} | ||
|
||
X2Many2DMatrixField.template = "web_widget_x2many_2d_matrix.X2Many2DMatrixField"; | ||
X2Many2DMatrixField.props = { | ||
...standardFieldProps, | ||
matrixFields: Object, | ||
isXClickable: Boolean, | ||
isYClickable: Boolean, | ||
showRowTotals: Boolean, | ||
showColumnTotals: Boolean, | ||
}; | ||
X2Many2DMatrixField.components = {X2Many2DMatrixRenderer}; | ||
X2Many2DMatrixField.extractProps = ({attrs}) => { | ||
return { | ||
matrixFields: { | ||
value: attrs.field_value, | ||
x: attrs.field_x_axis, | ||
y: attrs.field_y_axis, | ||
}, | ||
isXClickable: archParseBoolean(attrs.x_axis_clickable), | ||
isYClickable: archParseBoolean(attrs.y_axis_clickable), | ||
showRowTotals: | ||
"show_row_totals" in attrs ? archParseBoolean(attrs.show_row_totals) : true, | ||
showColumnTotals: | ||
"show_column_totals" in attrs | ||
? archParseBoolean(attrs.show_column_totals) | ||
: true, | ||
}; | ||
}; | ||
|
||
registry.category("fields").add("x2many_2d_matrix", X2Many2DMatrixField); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
..._x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<templates> | ||
<t t-name="web_widget_x2many_2d_matrix.X2Many2DMatrixField" owl="1"> | ||
<div class="table-responsive"> | ||
<X2Many2DMatrixRenderer | ||
list="list" | ||
matrixFields="props.matrixFields" | ||
showRowTotals="props.showRowTotals" | ||
showColumnTotals="props.showColumnTotals" | ||
setDirty="props.setDirty" | ||
onUpdate="(x, y, value) => this.commitChange(x, y, value)" | ||
readonly="props.readonly" | ||
/> | ||
</div> | ||
</t> | ||
</templates> |
144 changes: 144 additions & 0 deletions
144
...d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/** @odoo-module **/ | ||
|
||
import {Component, onWillUpdateProps} from "@odoo/owl"; | ||
import {registry} from "@web/core/registry"; | ||
|
||
export class X2Many2DMatrixRenderer extends Component { | ||
setup() { | ||
this.ValueFieldComponent = this._getValueFieldComponent(); | ||
this.columns = this._getColumns(); | ||
this.rows = this._getRows(); | ||
this.matrix = this._getMatrix(); | ||
|
||
onWillUpdateProps((newProps) => { | ||
this.columns = this._getColumns(newProps.list.records); | ||
this.rows = this._getRows(newProps.list.records); | ||
this.matrix = this._getMatrix(newProps.list.records); | ||
}); | ||
} | ||
|
||
_getColumns(records = this.list.records) { | ||
const columns = []; | ||
records.forEach((record) => { | ||
const column = { | ||
value: record.data[this.matrixFields.x], | ||
text: record.data[this.matrixFields.x], | ||
}; | ||
if (record.fields[this.matrixFields.x].type === "many2one") { | ||
column.value = column.value[0]; | ||
column.text = column.value[1]; | ||
} | ||
if (columns.findIndex((c) => c.value === column.value) !== -1) return; | ||
columns.push(column); | ||
}); | ||
return columns; | ||
} | ||
|
||
_getRows(records = this.list.records) { | ||
const rows = []; | ||
records.forEach((record) => { | ||
const row = { | ||
value: record.data[this.matrixFields.y], | ||
text: record.data[this.matrixFields.y], | ||
}; | ||
if (record.fields[this.matrixFields.y].type === "many2one") { | ||
row.value = row.value[0]; | ||
row.text = row.value[1]; | ||
} | ||
if (rows.findIndex((r) => r.value === row.value) !== -1) return; | ||
rows.push(row); | ||
}); | ||
return rows; | ||
} | ||
|
||
_getPointOfRecord(record) { | ||
let xValue = record.data[this.matrixFields.x]; | ||
if (record.fields[this.matrixFields.x].type === "many2one") { | ||
xValue = xValue[0]; | ||
} | ||
let yValue = record.data[this.matrixFields.y]; | ||
if (record.fields[this.matrixFields.y].type === "many2one") { | ||
yValue = yValue[0]; | ||
} | ||
|
||
const x = this.columns.findIndex((c) => c.value === xValue); | ||
const y = this.rows.findIndex((r) => r.value === yValue); | ||
return {x, y}; | ||
} | ||
|
||
_getMatrix(records = this.list.records) { | ||
const matrix = this.rows.map(() => | ||
new Array(this.columns.length).fill(null).map(() => { | ||
return {value: 0, records: []}; | ||
}) | ||
); | ||
records.forEach((record) => { | ||
const value = record.data[this.matrixFields.value]; | ||
const {x, y} = this._getPointOfRecord(record); | ||
matrix[y][x].value += value; | ||
matrix[y][x].records.push(record); | ||
}); | ||
return matrix; | ||
} | ||
|
||
get list() { | ||
return this.props.list; | ||
} | ||
|
||
get matrixFields() { | ||
return this.props.matrixFields; | ||
} | ||
|
||
_getValueFieldComponent() { | ||
const fieldType = this.list.activeFields[this.matrixFields.value].widget; | ||
return registry.category("fields").get(fieldType); | ||
} | ||
|
||
_aggregateRow(row) { | ||
const y = this.rows.findIndex((r) => r.value === row); | ||
return this.matrix[y].map((r) => r.value).reduce((aggr, x) => aggr + x); | ||
} | ||
|
||
_aggregateColumn(column) { | ||
const x = this.columns.findIndex((c) => c.value === column); | ||
return this.matrix | ||
.map((r) => r[x]) | ||
.map((r) => r.value) | ||
.reduce((aggr, y) => aggr + y); | ||
} | ||
|
||
_aggregateAll() { | ||
return this.matrix | ||
.map((r) => r.map((x) => x.value).reduce((aggr, x) => aggr + x)) | ||
.reduce((aggr, y) => aggr + y); | ||
} | ||
|
||
update(x, y, value) { | ||
this.matrix[y][x].value = value; | ||
const xFieldValue = this.columns[x].value; | ||
const yFieldValue = this.rows[y].value; | ||
|
||
this.props.onUpdate(xFieldValue, yFieldValue, value); | ||
} | ||
|
||
getValueFieldProps(column, row) { | ||
const x = this.columns.findIndex((c) => c.value === column); | ||
const y = this.rows.findIndex((r) => r.value === row); | ||
return { | ||
value: this.matrix[y][x].value, | ||
update: (value) => this.update(x, y, value), | ||
readonly: this.props.readonly, | ||
}; | ||
} | ||
} | ||
|
||
X2Many2DMatrixRenderer.template = "web_widget_x2many_2d_matrix.X2Many2DMatrixRenderer"; | ||
X2Many2DMatrixRenderer.props = { | ||
list: Object, | ||
matrixFields: Object, | ||
setDirty: Function, | ||
onUpdate: Function, | ||
readonly: Boolean, | ||
showRowTotals: Boolean, | ||
showColumnTotals: Boolean, | ||
}; |
66 changes: 66 additions & 0 deletions
66
...y_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<templates> | ||
<t t-name="web_widget_x2many_2d_matrix.X2Many2DMatrixRenderer" owl="1"> | ||
<table | ||
class="o_list_table table table-responsive table-sm table-hover position-relative mb-0 o_list_table_ungrouped table-striped" | ||
t-if="rows.length > 0" | ||
> | ||
<thead> | ||
<tr> | ||
<th /> | ||
<th | ||
t-foreach="columns" | ||
t-as="column" | ||
t-key="column.value" | ||
class="text-center" | ||
> | ||
<t t-esc="column.text" /> | ||
</th> | ||
<th t-if="props.showRowTotals" /> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr t-foreach="rows" t-as="row" t-key="row.value"> | ||
<td> | ||
<t t-esc="row.text" /> | ||
</td> | ||
<td t-foreach="columns" t-as="column" t-key="column.value"> | ||
<t | ||
t-component="ValueFieldComponent" | ||
t-props="getValueFieldProps(column.value, row.value)" | ||
/> | ||
</td> | ||
<td t-if="props.showRowTotals" class="row-total"> | ||
<t | ||
t-component="ValueFieldComponent" | ||
readonly="true" | ||
value="_aggregateRow(row.value)" | ||
/> | ||
</td> | ||
</tr> | ||
</tbody> | ||
<tfoot> | ||
<tr t-if="props.showColumnTotals"> | ||
<th /> | ||
<th t-foreach="columns" t-as="column" t-key="column.value"> | ||
<t | ||
t-component="ValueFieldComponent" | ||
readonly="true" | ||
value="_aggregateColumn(column.value)" | ||
/> | ||
</th> | ||
<th t-if="props.showRowTotals" class="col-total"> | ||
<t | ||
t-component="ValueFieldComponent" | ||
readonly="true" | ||
value="_aggregateAll()" | ||
/> | ||
</th> | ||
</tr> | ||
</tfoot> | ||
</table> | ||
<div t-else="" class="alert alert-info"> | ||
Nothing to display. | ||
</div> | ||
</t> | ||
</templates> |
Oops, something went wrong.