Skip to content

Commit 7eeea68

Browse files
committed
[IMP] DV: auto focus input
When switching a data validation to "Value In Range", automatically focus the range input to allow selecting a range right away without an additional click to focus the input. We do the same for all validation types that have an associated input. Task: 4862354 Part-of: #7252 Signed-off-by: Rémi Rahir (rar) <rar@odoo.com>
1 parent b0f275b commit 7eeea68

File tree

13 files changed

+84
-7
lines changed

13 files changed

+84
-7
lines changed

src/components/composer/standalone_composer/standalone_composer.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { cssPropertiesToCss } from "@odoo/o-spreadsheet-engine/components/helpers/css";
22
import { Token } from "@odoo/o-spreadsheet-engine/formulas/tokenizer";
33
import { SpreadsheetChildEnv } from "@odoo/o-spreadsheet-engine/types/spreadsheet_env";
4-
import { Component } from "@odoo/owl";
4+
import { Component, onMounted } from "@odoo/owl";
55
import { AutoCompleteProviderDefinition } from "../../../registries/auto_completes";
66
import { Store, useLocalStore, useStore } from "../../../store_engine";
77
import { Color, ComposerFocusType, UID } from "../../../types/index";
@@ -21,6 +21,7 @@ interface Props {
2121
title?: string;
2222
class?: string;
2323
invalid?: boolean;
24+
autofocus?: boolean;
2425
getContextualColoredSymbolToken?: (token: Token) => Color;
2526
}
2627

@@ -36,6 +37,7 @@ export class StandaloneComposer extends Component<Props, SpreadsheetChildEnv> {
3637
title: { type: String, optional: true },
3738
class: { type: String, optional: true },
3839
invalid: { type: Boolean, optional: true },
40+
autofocus: { type: Boolean, optional: true },
3941
getContextualColoredSymbolToken: { type: Function, optional: true },
4042
};
4143
static components = { Composer };
@@ -69,6 +71,12 @@ export class StandaloneComposer extends Component<Props, SpreadsheetChildEnv> {
6971
setCurrentContent: this.standaloneComposerStore.setCurrentContent,
7072
stopEdition: this.standaloneComposerStore.stopEdition,
7173
};
74+
onMounted(() => {
75+
if (this.props.autofocus && this.focus === "inactive") {
76+
this.composerFocusStore.focusComposer(this.composerInterface, {});
77+
this.composerFocusStore.activeComposer.editionMode;
78+
}
79+
});
7280
}
7381

7482
get focus(): ComposerFocusType {

src/components/selection_input/selection_input.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface Props {
1212
ranges: string[];
1313
hasSingleRange?: boolean;
1414
required?: boolean;
15+
autofocus?: boolean;
1516
isInvalid?: boolean;
1617
class?: string;
1718
onSelectionChanged?: (ranges: string[]) => void;
@@ -50,6 +51,7 @@ export class SelectionInput extends Component<Props, SpreadsheetChildEnv> {
5051
ranges: Array,
5152
hasSingleRange: { type: Boolean, optional: true },
5253
required: { type: Boolean, optional: true },
54+
autofocus: { type: Boolean, optional: true },
5355
isInvalid: { type: Boolean, optional: true },
5456
class: { type: String, optional: true },
5557
onSelectionChanged: { type: Function, optional: true },
@@ -105,6 +107,9 @@ export class SelectionInput extends Component<Props, SpreadsheetChildEnv> {
105107
this.props.colors,
106108
this.props.disabledRanges
107109
);
110+
if (this.props.autofocus) {
111+
this.store.focusById(this.store.selectionInputs[0]?.id);
112+
}
108113
onWillUpdateProps((nextProps) => {
109114
if (nextProps.ranges.join() !== this.store.selectionInputValues.join()) {
110115
this.triggerChange();

src/components/side_panel/criterion_form/criterion_form.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { SpreadsheetChildEnv } from "@odoo/o-spreadsheet-engine/types/spreadsheet_env";
2-
import { Component, onMounted } from "@odoo/owl";
2+
import { Component } from "@odoo/owl";
33
import { useStore } from "../../../store_engine";
44
import { GenericCriterion } from "../../../types";
55
import { ComposerFocusStore } from "../../composer/composer_focus_store";
@@ -8,6 +8,7 @@ interface Props<T extends GenericCriterion> {
88
criterion: T;
99
onCriterionChanged: (criterion: T) => void;
1010
disableFormulas?: boolean;
11+
autofocus?: boolean;
1112
}
1213

1314
export abstract class CriterionForm<
@@ -17,12 +18,13 @@ export abstract class CriterionForm<
1718
criterion: Object,
1819
onCriterionChanged: Function,
1920
disableFormulas: { type: Boolean, optional: true },
21+
autofocus: { type: Boolean, optional: true },
2022
};
2123
setup() {
2224
const composerFocusStore = useStore(ComposerFocusStore);
23-
onMounted(() => {
25+
if (composerFocusStore.activeComposer.editionMode !== "inactive") {
2426
composerFocusStore.activeComposer.stopEdition();
25-
});
27+
}
2628
}
2729

2830
updateCriterion(criterion: Partial<T>) {

src/components/side_panel/criterion_form/criterion_input/criterion_input.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ export class CriterionInput extends Component<Props, SpreadsheetChildEnv> {
4141
setup() {
4242
useEffect(
4343
() => {
44-
if (this.props.focused) {
45-
this.inputRef.el!.focus();
44+
if (this.props.focused && this.inputRef.el) {
45+
this.inputRef.el.focus();
4646
}
4747
},
4848
() => [this.props.focused, this.inputRef.el]
@@ -94,6 +94,7 @@ export class CriterionInput extends Component<Props, SpreadsheetChildEnv> {
9494
defaultRangeSheetId: this.env.model.getters.getActiveSheetId(),
9595
invalid: this.state.shouldDisplayError && !!this.errorMessage,
9696
defaultStatic: true,
97+
autofocus: this.props.focused,
9798
};
9899
}
99100

src/components/side_panel/criterion_form/date_criterion/date_criterion.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
onValueChanged.bind="onValueChanged"
1818
criterionType="props.criterion.type"
1919
disableFormulas="props.disableFormulas"
20+
focused="props.autofocus"
2021
/>
2122
</t>
2223
</templates>

src/components/side_panel/criterion_form/double_input_criterion/double_input_criterion.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
onValueChanged.bind="onFirstValueChanged"
66
criterionType="props.criterion.type"
77
disableFormulas="props.disableFormulas"
8+
focused="props.autofocus"
89
/>
910
<CriterionInput
1011
value="props.criterion.values[1]"

src/components/side_panel/criterion_form/single_input_criterion/single_input_criterion.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
onValueChanged.bind="onValueChanged"
66
criterionType="props.criterion.type"
77
disableFormulas="props.disableFormulas"
8+
focused="props.autofocus"
89
/>
910
</t>
1011
</templates>

src/components/side_panel/criterion_form/value_in_list_criterion/value_in_list_criterion.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export class ListCriterionForm extends CriterionForm<IsValueInListCriterion> {
1515

1616
state = useState<State>({
1717
numberOfValues: Math.max(this.props.criterion.values.length, 2),
18+
focusedValueIndex: this.props.autofocus ? 0 : undefined,
1819
});
1920

2021
setup() {

src/components/side_panel/criterion_form/value_in_range_criterion/value_in_range_criterion.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
onSelectionChanged="(ranges) => this.onRangeChanged(ranges[0])"
66
required="true"
77
hasSingleRange="true"
8+
autofocus="props.autofocus"
89
/>
910
<t t-foreach="values" t-as="value" t-key="value_index">
1011
<div class="o-dv-list-values p-1 d-flex align-items-center">

src/components/side_panel/data_validation/dv_editor/dv_editor.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ interface Props {
3333
interface State {
3434
rule: DataValidationRuleData;
3535
errors: CancelledReason[];
36+
isTypeUpdated: boolean;
3637
}
3738

3839
export class DataValidationEditor extends Component<Props, SpreadsheetChildEnv> {
@@ -44,7 +45,11 @@ export class DataValidationEditor extends Component<Props, SpreadsheetChildEnv>
4445
onCloseSidePanel: { type: Function, optional: true },
4546
};
4647

47-
state = useState<State>({ rule: this.defaultDataValidationRule, errors: [] });
48+
state = useState<State>({
49+
rule: this.defaultDataValidationRule,
50+
errors: [],
51+
isTypeUpdated: false,
52+
});
4853
private editingSheetId!: UID;
4954

5055
setup() {
@@ -62,6 +67,7 @@ export class DataValidationEditor extends Component<Props, SpreadsheetChildEnv>
6267

6368
onCriterionTypeChanged(type: DataValidationCriterionType) {
6469
this.state.rule.criterion.type = type;
70+
this.state.isTypeUpdated = true;
6571
}
6672

6773
onRangesChanged(ranges: string[]) {

0 commit comments

Comments
 (0)