From e3f56f531cf02c8abed61b450e89e7dcd0736874 Mon Sep 17 00:00:00 2001 From: Bob Date: Mon, 31 Aug 2026 02:07:56 +0000 Subject: [PATCH 1/3] fix(query): use native date inputs in query options Git-Session-Id: 7ccb --- src/components/QueryOptions.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/QueryOptions.vue b/src/components/QueryOptions.vue index 566eb4389..48047f7af 100644 --- a/src/components/QueryOptions.vue +++ b/src/components/QueryOptions.vue @@ -5,9 +5,9 @@ div option(v-for="hostname in hostnameChoices") | {{hostname}} b-form-group(label="Start" label-cols=2) - b-form-datepicker(v-model="queryOptionsData.start") + input.form-control(type="date" v-model="queryOptionsData.start") b-form-group(label="Stop" label-cols=2) - b-form-datepicker(v-model="queryOptionsData.stop") + input.form-control(type="date" v-model="queryOptionsData.stop") b-form-group(label="Toggles" label-cols=2) b-form-checkbox(type="checkbox" v-model="queryOptionsData.filter_afk" label="Filter AFK" description="") label Exclude time away from computer From b31bca3899c3118f62419a5f749e378abd20600e Mon Sep 17 00:00:00 2001 From: Bob Date: Mon, 31 Aug 2026 02:28:25 +0000 Subject: [PATCH 2/3] fix(query): normalize date input values Git-Session-Id: 7ccb --- src/components/QueryOptions.vue | 2 ++ test/unit/QueryOptions.test.js | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 test/unit/QueryOptions.test.js diff --git a/src/components/QueryOptions.vue b/src/components/QueryOptions.vue index 48047f7af..4e9ca6497 100644 --- a/src/components/QueryOptions.vue +++ b/src/components/QueryOptions.vue @@ -60,6 +60,8 @@ export default Vue.extend({ ...this.queryOptionsData, hostname: this.hostnameChoices[0], ...this.queryOptions, + start: moment(this.queryOptions?.start || this.queryOptionsData.start).format('YYYY-MM-DD'), + stop: moment(this.queryOptions?.stop || this.queryOptionsData.stop).format('YYYY-MM-DD'), }; this.$emit('input', this.queryOptionsData); }, diff --git a/test/unit/QueryOptions.test.js b/test/unit/QueryOptions.test.js new file mode 100644 index 000000000..4fb3976d1 --- /dev/null +++ b/test/unit/QueryOptions.test.js @@ -0,0 +1,44 @@ +import moment from 'moment'; +import { createPinia, setActivePinia } from 'pinia'; +import { shallowMount } from '@vue/test-utils'; +import QueryOptions from '~/components/QueryOptions.vue'; + +const mockEnsureLoaded = jest.fn().mockResolvedValue(undefined); + +jest.mock('~/stores/buckets', () => ({ + useBucketsStore: () => ({ + ensureLoaded: mockEnsureLoaded, + hosts: ['laptop'], + }), +})); + +describe('QueryOptions', () => { + beforeEach(() => { + setActivePinia(createPinia()); + mockEnsureLoaded.mockClear(); + }); + + test('normalizes Moment date props for native date inputs', async () => { + const wrapper = shallowMount(QueryOptions, { + propsData: { + queryOptions: { + start: moment('2026-08-15'), + stop: moment('2026-08-16'), + }, + }, + stubs: { + 'b-form-group': { template: '
' }, + 'b-form-select': true, + 'b-form-checkbox': true, + }, + }); + + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + + const dateInputs = wrapper.findAll('input[type="date"]'); + expect(dateInputs).toHaveLength(2); + expect(dateInputs.at(0).element.value).toBe('2026-08-15'); + expect(dateInputs.at(1).element.value).toBe('2026-08-16'); + }); +}); From f7b0a8e21e59b43c879e430924938f54d55841bf Mon Sep 17 00:00:00 2001 From: Bob Date: Mon, 31 Aug 2026 02:40:06 +0000 Subject: [PATCH 3/3] fix(query): preserve native date value format Git-Session-Id: 7ccb --- src/components/QueryOptions.vue | 2 -- src/views/Graph.vue | 4 +++- src/views/Report.vue | 4 +++- src/views/Search.vue | 8 +++++--- src/views/settings/CategoryBuilder.vue | 4 ++-- test/unit/QueryOptions.test.js | 26 +++++++++++++++++++++++--- 6 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/components/QueryOptions.vue b/src/components/QueryOptions.vue index 4e9ca6497..48047f7af 100644 --- a/src/components/QueryOptions.vue +++ b/src/components/QueryOptions.vue @@ -60,8 +60,6 @@ export default Vue.extend({ ...this.queryOptionsData, hostname: this.hostnameChoices[0], ...this.queryOptions, - start: moment(this.queryOptions?.start || this.queryOptionsData.start).format('YYYY-MM-DD'), - stop: moment(this.queryOptions?.stop || this.queryOptionsData.stop).format('YYYY-MM-DD'), }; this.$emit('input', this.queryOptionsData); }, diff --git a/src/views/Graph.vue b/src/views/Graph.vue index 5cb6b4dd4..b57723ce7 100644 --- a/src/views/Graph.vue +++ b/src/views/Graph.vue @@ -207,7 +207,9 @@ export default { return { nodes, links }; }, extendByWeek() { - this.queryOptions.start = moment(this.queryOptions.start).subtract(1, 'week'); + this.queryOptions.start = moment(this.queryOptions.start) + .subtract(1, 'week') + .format('YYYY-MM-DD'); this.generate(); }, }, diff --git a/src/views/Report.vue b/src/views/Report.vue index 6357fff79..21d0afb91 100644 --- a/src/views/Report.vue +++ b/src/views/Report.vue @@ -176,7 +176,9 @@ export default { }, extendByWeek() { - this.queryOptions.start = moment(this.queryOptions.start).subtract(1, 'week'); + this.queryOptions.start = moment(this.queryOptions.start) + .subtract(1, 'week') + .format('YYYY-MM-DD'); this.generate(); }, }, diff --git a/src/views/Search.vue b/src/views/Search.vue index 3ae97bcac..8283e379b 100644 --- a/src/views/Search.vue +++ b/src/views/Search.vue @@ -64,8 +64,8 @@ export default { // Options show_options: false, queryOptions: { - start: moment().subtract(1, 'day'), - stop: moment().add(1, 'day'), + start: moment().subtract(1, 'day').format('YYYY-MM-DD'), + stop: moment().add(1, 'day').format('YYYY-MM-DD'), }, }; }, @@ -97,7 +97,9 @@ export default { } }, extendByWeek() { - this.queryOptions.start = moment(this.queryOptions.start).subtract(1, 'week'); + this.queryOptions.start = moment(this.queryOptions.start) + .subtract(1, 'week') + .format('YYYY-MM-DD'); this.search(); }, }, diff --git a/src/views/settings/CategoryBuilder.vue b/src/views/settings/CategoryBuilder.vue index 8081d0650..77d25a9b4 100644 --- a/src/views/settings/CategoryBuilder.vue +++ b/src/views/settings/CategoryBuilder.vue @@ -150,8 +150,8 @@ export default { show_options: false, queryOptions: { hostname: '', - start: moment().subtract(1, 'day'), - stop: moment().add(1, 'day'), + start: moment().subtract(1, 'day').format('YYYY-MM-DD'), + stop: moment().add(1, 'day').format('YYYY-MM-DD'), }, // TODO: Support inspecting a different category than Uncategorized (e.g. to make some category more precise) diff --git a/test/unit/QueryOptions.test.js b/test/unit/QueryOptions.test.js index 4fb3976d1..309a4027e 100644 --- a/test/unit/QueryOptions.test.js +++ b/test/unit/QueryOptions.test.js @@ -2,6 +2,7 @@ import moment from 'moment'; import { createPinia, setActivePinia } from 'pinia'; import { shallowMount } from '@vue/test-utils'; import QueryOptions from '~/components/QueryOptions.vue'; +import Search from '~/views/Search.vue'; const mockEnsureLoaded = jest.fn().mockResolvedValue(undefined); @@ -18,12 +19,12 @@ describe('QueryOptions', () => { mockEnsureLoaded.mockClear(); }); - test('normalizes Moment date props for native date inputs', async () => { + test('renders date range values in native date inputs', async () => { const wrapper = shallowMount(QueryOptions, { propsData: { queryOptions: { - start: moment('2026-08-15'), - stop: moment('2026-08-16'), + start: '2026-08-15', + stop: '2026-08-16', }, }, stubs: { @@ -41,4 +42,23 @@ describe('QueryOptions', () => { expect(dateInputs.at(0).element.value).toBe('2026-08-15'); expect(dateInputs.at(1).element.value).toBe('2026-08-16'); }); + + test.each([Search])('initializes date ranges as YYYY-MM-DD strings', view => { + const data = view.data(); + + expect(data.queryOptions.start).toMatch(/^\d{4}-\d{2}-\d{2}$/); + expect(data.queryOptions.stop).toMatch(/^\d{4}-\d{2}-\d{2}$/); + }); + + test.each([Search])('keeps extended ranges compatible with date inputs', view => { + const vm = { + queryOptions: { start: moment('2026-08-15') }, + search: jest.fn(), + generate: jest.fn(), + }; + + view.methods.extendByWeek.call(vm); + + expect(vm.queryOptions.start).toBe('2026-08-08'); + }); });