[REF] spreadsheet, spreadsheet_dashboard: use MultiRecordSelector
This commit replaces the RecordsSelector component by the MultiRecordSelector component in the global filters of the spreadsheet and the spreadsheet dashboard. Thus, the RecordsSelector component is not used anymore and can be removed. Part of task-id 3433922 closes odoo/odoo#138464 Related: odoo/enterprise#48857 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
+12
-6
@@ -1,16 +1,18 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { RecordsSelector } from "../records_selector/records_selector";
|
||||
import { MultiRecordSelector } from "@web/core/record_selectors/multi_record_selector";
|
||||
import { RELATIVE_DATE_RANGE_TYPES } from "@spreadsheet/helpers/constants";
|
||||
import { DateFilterValue } from "../filter_date_value/filter_date_value";
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
export class FilterValue extends Component {
|
||||
setup() {
|
||||
this.getters = this.props.model.getters;
|
||||
this.relativeDateRangesTypes = RELATIVE_DATE_RANGE_TYPES;
|
||||
this.nameService = useService("name");
|
||||
}
|
||||
onDateInput(id, value) {
|
||||
this.props.model.dispatch("SET_GLOBAL_FILTER_VALUE", { id, value });
|
||||
@@ -20,15 +22,19 @@ export class FilterValue extends Component {
|
||||
this.props.model.dispatch("SET_GLOBAL_FILTER_VALUE", { id, value });
|
||||
}
|
||||
|
||||
onTagSelected(id, values) {
|
||||
if (!values.length) {
|
||||
async onTagSelected(id, resIds) {
|
||||
if (!resIds.length) {
|
||||
// force clear, even automatic default values
|
||||
this.clear(id);
|
||||
} else {
|
||||
const displayNames = await this.nameService.loadDisplayNames(
|
||||
this.props.filter.modelName,
|
||||
resIds
|
||||
);
|
||||
this.props.model.dispatch("SET_GLOBAL_FILTER_VALUE", {
|
||||
id,
|
||||
value: values.map((record) => record.id),
|
||||
displayNames: values.map((record) => record.display_name),
|
||||
value: resIds,
|
||||
displayNames: Object.values(displayNames),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -42,7 +48,7 @@ export class FilterValue extends Component {
|
||||
}
|
||||
}
|
||||
FilterValue.template = "spreadsheet_edition.FilterValue";
|
||||
FilterValue.components = { RecordsSelector, DateFilterValue };
|
||||
FilterValue.components = { DateFilterValue, MultiRecordSelector };
|
||||
FilterValue.props = {
|
||||
filter: Object,
|
||||
model: Object,
|
||||
|
||||
+4
-3
@@ -6,7 +6,7 @@
|
||||
<t t-set="filter"
|
||||
t-value="props.filter"/>
|
||||
<t t-set="filterValue"
|
||||
t-value="getters.getGlobalFilterValue(filter.id)"/>
|
||||
t-value="getters.getGlobalFilterValue(filter.id) || []"/>
|
||||
<div t-if="filter.type === 'text'" class="w-100">
|
||||
<input type="text"
|
||||
class="o_input o-text-filter-input"
|
||||
@@ -15,10 +15,11 @@
|
||||
t-on-change="(e) => this.onTextInput(filter.id, e.target.value)"/>
|
||||
</div>
|
||||
<span t-if="filter.type === 'relation'" class="w-100">
|
||||
<RecordsSelector placeholder="' ' + translate(filter.label)"
|
||||
<MultiRecordSelector
|
||||
placeholder="' ' + translate(filter.label)"
|
||||
resModel="filter.modelName"
|
||||
resIds="filterValue"
|
||||
onValueChanged="(value) => this.onTagSelected(filter.id, value)" />
|
||||
update="(resIds) => this.onTagSelected(filter.id, resIds)" />
|
||||
</span>
|
||||
<div t-if="filter.type === 'date'" class="w-100">
|
||||
<DateFilterValue t-if="filter.rangeType !== 'relative'"
|
||||
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Domain } from "@web/core/domain";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { TagsList } from "@web/core/tags_list/tags_list";
|
||||
import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
|
||||
|
||||
import { Component, onWillStart, onWillUpdateProps } from "@odoo/owl";
|
||||
|
||||
export class RecordsSelector extends Component {
|
||||
setup() {
|
||||
/** @type {Record<number, string>} */
|
||||
this.displayNames = {};
|
||||
/** @type {import("@web/core/orm_service").ORM}*/
|
||||
this.orm = useService("orm");
|
||||
onWillStart(() => this.fetchMissingDisplayNames(this.props.resModel, this.props.resIds));
|
||||
onWillUpdateProps((nextProps) =>
|
||||
this.fetchMissingDisplayNames(nextProps.resModel, nextProps.resIds)
|
||||
);
|
||||
}
|
||||
|
||||
get tags() {
|
||||
return this.props.resIds.map((id) => ({
|
||||
text: this.displayNames[id],
|
||||
onDelete: () => this.removeRecord(id),
|
||||
}));
|
||||
}
|
||||
|
||||
onKeydown(ev) {
|
||||
if (this.props.resIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (ev.key.toUpperCase() === "BACKSPACE") {
|
||||
this.removeRecord(this.props.resIds[this.props.resIds.length - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
searchDomain() {
|
||||
return Domain.not([["id", "in", this.props.resIds]]).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} recordId
|
||||
*/
|
||||
removeRecord(recordId) {
|
||||
delete this.displayNames[recordId];
|
||||
this.notifyChange(this.props.resIds.filter((id) => id !== recordId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ id: number; display_name?: string}[]} records
|
||||
*/
|
||||
update(records) {
|
||||
for (const record of records.filter((record) => record.display_name)) {
|
||||
this.displayNames[record.id] = record.display_name;
|
||||
}
|
||||
this.notifyChange(this.props.resIds.concat(records.map(({ id }) => id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number[]} selectedIds
|
||||
*/
|
||||
notifyChange(selectedIds) {
|
||||
this.props.onValueChanged(
|
||||
selectedIds.map((id) => ({ id, display_name: this.displayNames[id] }))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} resModel
|
||||
* @param {number[]} recordIds
|
||||
*/
|
||||
async fetchMissingDisplayNames(resModel, recordIds) {
|
||||
const missingNameIds = recordIds.filter((id) => !(id in this.displayNames));
|
||||
if (missingNameIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
const results = await this.orm.read(resModel, missingNameIds, ["display_name"]);
|
||||
for (const { id, display_name } of results) {
|
||||
this.displayNames[id] = display_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
RecordsSelector.components = { TagsList, Many2XAutocomplete };
|
||||
RecordsSelector.template = "spreadsheet.RecordsSelector";
|
||||
RecordsSelector.props = {
|
||||
/**
|
||||
* Callback called when a record is selected or removed.
|
||||
* (selectedRecords: Array<{ id: number; display_name: string }>) => void
|
||||
**/
|
||||
onValueChanged: Function,
|
||||
resModel: String,
|
||||
/**
|
||||
* Array of selected record ids
|
||||
*/
|
||||
resIds: {
|
||||
optional: true,
|
||||
type: Array,
|
||||
},
|
||||
placeholder: {
|
||||
optional: true,
|
||||
type: String,
|
||||
},
|
||||
};
|
||||
RecordsSelector.defaultProps = {
|
||||
resIds: [],
|
||||
};
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
<div t-name="spreadsheet.RecordsSelector" class="o_field_widget o_field_many2many_tags">
|
||||
<div class="o_field_tags d-inline-flex flex-wrap mw-100 o_tags_input o_input w-100 gap-1">
|
||||
<TagsList tags="tags"/>
|
||||
<div
|
||||
class="o_field_many2many_selection d-inline-flex w-100"
|
||||
t-on-keydown="onKeydown">
|
||||
<Many2XAutocomplete
|
||||
placeholder="props.placeholder"
|
||||
resModel="props.resModel"
|
||||
fieldString="props.placeholder"
|
||||
activeActions="{}"
|
||||
update.bind="update"
|
||||
getDomain.bind="searchDomain"
|
||||
isToMany="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</templates>
|
||||
@@ -14,7 +14,7 @@
|
||||
.o-selection-statistic {
|
||||
background-color: #fff !important;
|
||||
}
|
||||
.o_field_tags .badge {
|
||||
.o_multi_record_selector .badge {
|
||||
background-color: #e6dddd !important;
|
||||
color: #3c3c3c !important;
|
||||
}
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@
|
||||
min-height: 25px;
|
||||
min-width: 100px;
|
||||
|
||||
.o_field_many2many_tags {
|
||||
.o_multi_record_selector {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ QUnit.test("Can delete record tag in the filter by hitting Backspace", async fun
|
||||
const serverData = getServerData(spreadsheetData);
|
||||
const fixture = getFixture();
|
||||
await createSpreadsheetDashboard({ serverData });
|
||||
const filter = fixture.querySelector(".o_control_panel_actions div.o_field_tags");
|
||||
const filter = fixture.querySelector(".o_control_panel_actions div.o_multi_record_selector");
|
||||
const autoCompleteInput = filter.querySelector(".o-autocomplete--input.o_input");
|
||||
assert.equal(filter.querySelectorAll(".o_tag").length, 1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user