Skip to content

Commit 9af50ed

Browse files
committed
Allow double click on presets
1 parent 8c71cf5 commit 9af50ed

9 files changed

Lines changed: 131 additions & 158 deletions

plugins/CoreHome/vue/dist/CoreHome.umd.js

Lines changed: 72 additions & 75 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/CoreHome/vue/dist/CoreHome.umd.min.js

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/CoreHome/vue/src/PeriodSelector/PeriodOptions.component.spec.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ jest.mock('../translate', () => ({
1818
General_DateRangeInPeriodList: 'date range',
1919
General_Custom: 'Custom',
2020
General_ChoosePeriod: 'Choose period',
21-
General_DoubleClickToChangePeriod: 'Double click to change period',
2221
};
2322

2423
return messages[key] || key;
@@ -64,14 +63,6 @@ describe('PeriodOptions', () => {
6463
expect(wrapper.emitted('select')?.[0]).toEqual([{ period: 'month' }]);
6564
});
6665

67-
it('should emit dblclick payload', async () => {
68-
const wrapper = mountComponent();
69-
70-
await wrapper.find('#period_id_week').trigger('dblclick');
71-
72-
expect(wrapper.emitted('dblclick')?.[0]).toEqual([{ period: 'week' }]);
73-
});
74-
7566
it('should expose selected state through checked radio input', async () => {
7667
const wrapper = mountComponent({
7768
checkedPeriodId: 'day',
@@ -99,17 +90,4 @@ describe('PeriodOptions', () => {
9990
expect(wrapper.find('#period_id_month').element.parentElement?.classList.contains('selected-period-label'))
10091
.toBe(true);
10192
});
102-
103-
it('should set empty tooltip for active date period and non-empty for others', () => {
104-
const wrapper = mountComponent({
105-
modelValue: 'day',
106-
activeDatePeriod: 'day',
107-
});
108-
109-
const dayLabel = wrapper.find('#period_id_day').element.parentElement as HTMLLabelElement;
110-
const weekLabel = wrapper.find('#period_id_week').element.parentElement as HTMLLabelElement;
111-
112-
expect(dayLabel.title).toBe('');
113-
expect(weekLabel.title).not.toBe('');
114-
});
11593
});

plugins/CoreHome/vue/src/PeriodSelector/PeriodOptions.vue

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@
1818
<label
1919
class="period-option-label"
2020
:class="{ 'selected-period-label': checkedPeriodId === period }"
21-
:title="period === activeDatePeriod
22-
? ''
23-
: translate('General_DoubleClickToChangePeriod')"
24-
@dblclick="handlePeriodDoubleClick(period)"
2521
>
2622
<input
2723
class="period-option-input"
@@ -77,7 +73,7 @@ export default defineComponent({
7773
periodInputName,
7874
};
7975
},
80-
emits: ['update:modelValue', 'select', 'dblclick'],
76+
emits: ['update:modelValue', 'select'],
8177
computed: {
8278
displayPeriods(): string[] {
8379
if (!this.periods.includes('range')) {
@@ -104,10 +100,6 @@ export default defineComponent({
104100
handlePeriodEnter(period: string) {
105101
this.handlePeriodSelected(period);
106102
},
107-
handlePeriodDoubleClick(period: string) {
108-
const payload: PeriodSelectionPayload = { period };
109-
this.$emit('dblclick', payload);
110-
},
111103
},
112104
});
113105
</script>

plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.selection.spec.ts

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -730,32 +730,23 @@ describe('PeriodSelector', () => {
730730
expect(ignoredVm.appliedRangeEndDate).toBe('2026-01-31');
731731
});
732732

733-
it('keeps legacy immediate apply behavior on non-range period double click', () => {
734-
const vm: any = {
735-
committedPeriod: 'day',
736-
committedAnchorDate: new Date('2026-02-18'),
737-
onPeriodOptionSelected: jest.fn(),
738-
setPiwikPeriodAndDate: jest.fn(),
733+
it('applies preset immediately on double click', () => {
734+
const selection = {
735+
id: 'last30days',
736+
period: 'range',
737+
date: 'last30',
738+
startDate: new Date('2026-01-20'),
739+
endDate: new Date('2026-02-18'),
739740
};
740-
741-
methods.onPeriodOptionDblClick.call(vm, { period: 'month' });
742-
743-
expect(vm.onPeriodOptionSelected).toHaveBeenCalledWith({ period: 'month' });
744-
expect(vm.setPiwikPeriodAndDate).toHaveBeenCalledWith('month', vm.committedAnchorDate);
745-
});
746-
747-
it('does not immediately apply range period double click', () => {
748741
const vm: any = {
749-
committedPeriod: 'day',
750-
committedAnchorDate: new Date('2026-02-18'),
751-
onPeriodOptionSelected: jest.fn(),
752-
setPiwikPeriodAndDate: jest.fn(),
742+
onPresetDateRangeSelected: jest.fn(),
743+
onApplyClicked: jest.fn(),
753744
};
754745

755-
methods.onPeriodOptionDblClick.call(vm, { period: 'range' });
746+
methods.onPresetDateRangeDblClick.call(vm, selection);
756747

757-
expect(vm.onPeriodOptionSelected).toHaveBeenCalledWith({ period: 'range' });
758-
expect(vm.setPiwikPeriodAndDate).not.toHaveBeenCalled();
748+
expect(vm.onPresetDateRangeSelected).toHaveBeenCalledWith(selection);
749+
expect(vm.onApplyClicked).toHaveBeenCalled();
759750
});
760751

761752
it('blocks calendar commit while preset is pending', () => {

plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
@update:ui-selected-period="selectedPeriod = $event"
5555
@update:active-preset-id="activePresetId = $event"
5656
@period-select="onPeriodOptionSelected($event)"
57-
@period-dblclick="onPeriodOptionDblClick($event)"
5857
@preset-select="onPresetDateRangeSelected($event)"
58+
@preset-dblclick="onPresetDateRangeDblClick($event)"
5959
/>
6060
<PeriodSelectorCalendarColumn
6161
:ui-selection="uiSelection"
@@ -509,17 +509,6 @@ export default defineComponent({
509509
? this.committedAnchorDate
510510
: null;
511511
},
512-
onPeriodOptionDblClick(payload: { period: string }) {
513-
this.onPeriodOptionSelected(payload);
514-
if (payload.period === RANGE_PERIOD
515-
|| payload.period === this.committedPeriod
516-
|| !this.committedAnchorDate
517-
) {
518-
return;
519-
}
520-
521-
this.setPiwikPeriodAndDate(payload.period, this.committedAnchorDate);
522-
},
523512
canInteractWithSingleCalendar(): boolean {
524513
// Preset-owned selections are intentionally read-only for calendar interactions.
525514
// Users must switch ownership via period options before single-calendar clicks can commit.
@@ -558,6 +547,10 @@ export default defineComponent({
558547
this.singleCalendarPeriod = selection.period;
559548
}
560549
},
550+
onPresetDateRangeDblClick(selection: PresetDateRangeSelection) {
551+
this.onPresetDateRangeSelected(selection);
552+
this.onApplyClicked();
553+
},
561554
propagateNewUrlParams(date: string, period: string) {
562555
const compareParams = this.selectedComparisonParams;
563556

plugins/CoreHome/vue/src/PeriodSelector/PeriodSelectorOptionsColumn.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
:active-date-period="appliedPeriod"
1717
@update:model-value="$emit('update:uiSelectedPeriod', $event)"
1818
@select="$emit('period-select', $event)"
19-
@dblclick="$emit('period-dblclick', $event)"
2019
/>
2120
<PresetDateRanges
2221
:model-value="activePresetId"
@@ -26,6 +25,7 @@
2625
:max-date="maxAllowedDate"
2726
@update:model-value="$emit('update:activePresetId', $event)"
2827
@select="$emit('preset-select', $event)"
28+
@dblclick="$emit('preset-dblclick', $event)"
2929
/>
3030
</div>
3131
</div>
@@ -77,8 +77,8 @@ export default defineComponent({
7777
'update:uiSelectedPeriod',
7878
'update:activePresetId',
7979
'period-select',
80-
'period-dblclick',
8180
'preset-select',
81+
'preset-dblclick',
8282
],
8383
methods: {
8484
translate,

plugins/CoreHome/vue/src/PeriodSelector/PresetDateRanges.component.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ describe('PresetDateRanges', () => {
109109
expect(selectPayload.date).toBe('last7');
110110
});
111111

112+
it('should emit dblclick payload for presets', async () => {
113+
const wrapper = mountComponent();
114+
115+
await wrapper.find('#preset_date_last7days').trigger('dblclick');
116+
117+
expect(wrapper.emitted('dblclick')?.[0]?.[0]).toMatchObject({
118+
id: 'last7days',
119+
period: 'range',
120+
date: 'last7',
121+
});
122+
});
123+
112124
it('should resolve monday/sunday week behavior correctly', async () => {
113125
const wrapper = mountComponent({ today: new Date('2026-02-15') });
114126

plugins/CoreHome/vue/src/PeriodSelector/PresetDateRanges.vue

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
>
2323
<label
2424
:class="{ 'selected-period-label': checkedPresetId === preset.id }"
25+
@dblclick="handlePresetDoubleClick(preset.id)"
2526
>
2627
<input
2728
type="radio"
@@ -100,7 +101,7 @@ export default defineComponent({
100101
presetInputName,
101102
};
102103
},
103-
emits: ['update:modelValue', 'select'],
104+
emits: ['update:modelValue', 'select', 'dblclick'],
104105
computed: {
105106
presetDateRanges(): PresetDateRangeOption[] {
106107
return PRESET_DATE_RANGES.filter(
@@ -130,6 +131,15 @@ export default defineComponent({
130131
endDate: clampDateToBounds(resolvedPreset.endDate, this.minDate, this.maxDate),
131132
} as PresetDateRangeSelection);
132133
},
134+
handlePresetDoubleClick(presetId: PresetDateRangeId) {
135+
const resolvedPreset = resolvePresetDateRange(presetId, this.today);
136+
137+
this.$emit('dblclick', {
138+
...resolvedPreset,
139+
startDate: clampDateToBounds(resolvedPreset.startDate, this.minDate, this.maxDate),
140+
endDate: clampDateToBounds(resolvedPreset.endDate, this.minDate, this.maxDate),
141+
} as PresetDateRangeSelection);
142+
},
133143
},
134144
});
135145
</script>

0 commit comments

Comments
 (0)