Date range picker for querying by timestamp
This commit is contained in:
parent
6485e66931
commit
87dee71a8c
@ -21,6 +21,7 @@
|
|||||||
"vue": "^3.2.39",
|
"vue": "^3.2.39",
|
||||||
"vuex": "next",
|
"vuex": "next",
|
||||||
"vue-select": "beta",
|
"vue-select": "beta",
|
||||||
|
"v-calendar": "next",
|
||||||
"@meforma/vue-toaster": "^1.3.0",
|
"@meforma/vue-toaster": "^1.3.0",
|
||||||
"vuetify": "^3.0.0-beta.0",
|
"vuetify": "^3.0.0-beta.0",
|
||||||
"webfontloader": "^1.0.0"
|
"webfontloader": "^1.0.0"
|
||||||
|
81
src/components/Grid/Main/Filter/Datepicker.vue
Normal file
81
src/components/Grid/Main/Filter/Datepicker.vue
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<v-date-picker mode="dateTime" v-model="dateRange" locale="et" :is24hr="true" is-range timezone="UTC">
|
||||||
|
<template v-slot="{ inputValue, inputEvents }">
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<input
|
||||||
|
:value="inputValue.start"
|
||||||
|
v-on="inputEvents.start"
|
||||||
|
class="border px-2 py-1 w-32 rounded focus:outline-none focus:border-indigo-300"
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
class="w-4 h-4 mx-2"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
width="20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M14 5l7 7m0 0l-7 7m7-7H3"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<input
|
||||||
|
:value="inputValue.end"
|
||||||
|
v-on="inputEvents.end"
|
||||||
|
class="border px-2 py-1 w-32 rounded focus:outline-none focus:border-indigo-300"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-date-picker>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {mapActions, mapGetters} from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Datepicker",
|
||||||
|
props: {
|
||||||
|
refresh: {}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters([
|
||||||
|
'filterQuery',
|
||||||
|
]),
|
||||||
|
dateRange: {
|
||||||
|
get() {
|
||||||
|
return {
|
||||||
|
start: this.filterQuery.from ? new Date(this.filterQuery.from) : null,
|
||||||
|
end: this.filterQuery.to ? new Date(this.filterQuery.to) : null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
if (value) {
|
||||||
|
let toDate = new Date(value.end);
|
||||||
|
toDate.setSeconds(59, 999);
|
||||||
|
this.setFilterQueryTimeRange({
|
||||||
|
from: (new Date(value.start).getTime()),
|
||||||
|
to: (toDate.getTime()),
|
||||||
|
})
|
||||||
|
this.refresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions({
|
||||||
|
setFilterQueryTimeRange: 'setFilterQueryTimeRange',
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -1,5 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="height: 100%; width: 100%; text-align: right">
|
<div style="height: 100%; width: 100%;">
|
||||||
|
<v-row no-gutters>
|
||||||
|
<v-col cols="12" sm="4" class="d-flex justify-start flex-wrap">
|
||||||
|
<Datepicker class="ma-2" :refresh="refreshFilterState" />
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="4" class="d-flex justify-center flex-wrap">
|
||||||
|
<h1 class="app-title"> Logmower </h1>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="4" class="d-flex justify-end flex-wrap">
|
||||||
<v-btn
|
<v-btn
|
||||||
color="blue-grey"
|
color="blue-grey"
|
||||||
class="ma-2"
|
class="ma-2"
|
||||||
@ -8,6 +16,8 @@
|
|||||||
>
|
>
|
||||||
Stream new lines
|
Stream new lines
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
<ag-grid-vue
|
<ag-grid-vue
|
||||||
style="width: 100%; height: calc(100% - 52px);"
|
style="width: 100%; height: calc(100% - 52px);"
|
||||||
class="ag-theme-material"
|
class="ag-theme-material"
|
||||||
@ -22,6 +32,8 @@
|
|||||||
:onRowSelected="openExamineLog"
|
:onRowSelected="openExamineLog"
|
||||||
:supress-horisontal-scroll="true"
|
:supress-horisontal-scroll="true"
|
||||||
:enable-scrolling="true"
|
:enable-scrolling="true"
|
||||||
|
:isExternalFilterPresent="() => {return true}"
|
||||||
|
:doesExternalFilterPass="doesExternalFilterPass"
|
||||||
></ag-grid-vue>
|
></ag-grid-vue>
|
||||||
<ExamineLogModal :examine-log-content="examineLogContent" :close-modal="closeExamineLog" />
|
<ExamineLogModal :examine-log-content="examineLogContent" :close-modal="closeExamineLog" />
|
||||||
</div>
|
</div>
|
||||||
@ -32,6 +44,7 @@ import { AgGridVue } from "ag-grid-vue3";
|
|||||||
import "ag-grid-community/styles//ag-grid.css";
|
import "ag-grid-community/styles//ag-grid.css";
|
||||||
import "ag-grid-community/styles//ag-theme-material.css";
|
import "ag-grid-community/styles//ag-theme-material.css";
|
||||||
import { VBtn } from 'vuetify/components/VBtn'
|
import { VBtn } from 'vuetify/components/VBtn'
|
||||||
|
import { VRow, VCol } from 'vuetify/components/VGrid'
|
||||||
import ExamineLogModal from "./Modal/ExamineLogModal.vue";
|
import ExamineLogModal from "./Modal/ExamineLogModal.vue";
|
||||||
import ComboboxFilter from "./Grid/Main/Filter/ComboboxFilter.js";
|
import ComboboxFilter from "./Grid/Main/Filter/ComboboxFilter.js";
|
||||||
import ErrLevelRenderer from "./Grid/Main/ErrLevelRenderer";
|
import ErrLevelRenderer from "./Grid/Main/ErrLevelRenderer";
|
||||||
@ -39,14 +52,18 @@ import flattenObj from "../helpers/flattenObj";
|
|||||||
import parseEventData from "../helpers/parseEventData";
|
import parseEventData from "../helpers/parseEventData";
|
||||||
import {mapActions, mapGetters} from 'vuex';
|
import {mapActions, mapGetters} from 'vuex';
|
||||||
import config from "./Grid/Main/config";
|
import config from "./Grid/Main/config";
|
||||||
|
import Datepicker from "./Grid/Main/Filter/Datepicker.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
Datepicker,
|
||||||
ExamineLogModal,
|
ExamineLogModal,
|
||||||
AgGridVue,
|
AgGridVue,
|
||||||
ComboboxFilter,
|
ComboboxFilter,
|
||||||
ErrLevelRenderer,
|
ErrLevelRenderer,
|
||||||
VBtn
|
VBtn,
|
||||||
|
VRow,
|
||||||
|
VCol
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -62,7 +79,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
'filterQuery',
|
'filterQuery',
|
||||||
'streaming',
|
'streaming'
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -78,6 +95,8 @@ export default {
|
|||||||
queryParams = Object.fromEntries(queryParams);
|
queryParams = Object.fromEntries(queryParams);
|
||||||
this.initialFilter = queryParams
|
this.initialFilter = queryParams
|
||||||
queryParams['initial'] = true
|
queryParams['initial'] = true
|
||||||
|
queryParams['from'] && (queryParams['from'] = Number(queryParams['from']))
|
||||||
|
queryParams['to'] && (queryParams['to'] = Number(queryParams['to']))
|
||||||
this.setFilterQuery(queryParams)
|
this.setFilterQuery(queryParams)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -86,6 +105,9 @@ export default {
|
|||||||
setFilterQuery: 'setFilterQuery',
|
setFilterQuery: 'setFilterQuery',
|
||||||
toggleFilterQueryStreaming: 'toggleFilterQueryStreaming',
|
toggleFilterQueryStreaming: 'toggleFilterQueryStreaming',
|
||||||
}),
|
}),
|
||||||
|
refreshFilterState() {
|
||||||
|
this.gridApi.onFilterChanged();
|
||||||
|
},
|
||||||
setupStream() {
|
setupStream() {
|
||||||
this.es && this.es.close();
|
this.es && this.es.close();
|
||||||
let url = new URL('/events', window.location.href);
|
let url = new URL('/events', window.location.href);
|
||||||
@ -143,6 +165,8 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
query['streaming'] = this.streaming
|
query['streaming'] = this.streaming
|
||||||
|
this.filterQuery.from && (query['from'] = this.filterQuery.from)
|
||||||
|
this.filterQuery.to && (query['to'] = this.filterQuery.to)
|
||||||
this.setFilterQuery(query)
|
this.setFilterQuery(query)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -203,6 +227,13 @@ export default {
|
|||||||
});
|
});
|
||||||
setTimeout(this.$toast.clear, 3000);
|
setTimeout(this.$toast.clear, 3000);
|
||||||
},
|
},
|
||||||
|
doesExternalFilterPass(node) {
|
||||||
|
if (node.data && this.filterQuery.from && this.filterQuery.to) {
|
||||||
|
let ts = new Date(node.data['@timestamp']).getTime()
|
||||||
|
return (ts >= this.filterQuery.from && ts <= this.filterQuery.to)
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
openExamineLog (row) {
|
openExamineLog (row) {
|
||||||
const selectedRow = row.data
|
const selectedRow = row.data
|
||||||
row.node.setSelected(false)
|
row.node.setSelected(false)
|
||||||
|
@ -3,14 +3,17 @@ import store from "./stores";
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import vuetify from './plugins/vuetify'
|
import vuetify from './plugins/vuetify'
|
||||||
import Toaster from "@meforma/vue-toaster";
|
import Toaster from "@meforma/vue-toaster";
|
||||||
|
import VCalendar from 'v-calendar';
|
||||||
import { loadFonts } from './plugins/webfontloader'
|
import { loadFonts } from './plugins/webfontloader'
|
||||||
import './assets/main.css'
|
import './assets/main.css'
|
||||||
import 'vue-select/dist/vue-select.css';
|
import 'vue-select/dist/vue-select.css';
|
||||||
|
import 'v-calendar/dist/style.css';
|
||||||
loadFonts()
|
loadFonts()
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
app.use(store);
|
app.use(store);
|
||||||
app.use(vuetify);
|
app.use(vuetify);
|
||||||
app.use(Toaster);
|
app.use(Toaster);
|
||||||
|
app.use(VCalendar, {});
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
|
|
||||||
|
@ -23,6 +23,13 @@ const store = createStore({
|
|||||||
toggleFilterQueryStreaming(context) {
|
toggleFilterQueryStreaming(context) {
|
||||||
context.commit("TOGGLE_FILTER_QUERY_STREAMING");
|
context.commit("TOGGLE_FILTER_QUERY_STREAMING");
|
||||||
},
|
},
|
||||||
|
setFilterQueryTimeRange({commit, state}, {from, to}) {
|
||||||
|
let query = state.filterQuery
|
||||||
|
query.from = from
|
||||||
|
query.to = to
|
||||||
|
query.streaming = false
|
||||||
|
commit("SET_FILTER_QUERY", query);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
SET_FILTER_OPTIONS(state, payload) {
|
SET_FILTER_OPTIONS(state, payload) {
|
||||||
@ -37,9 +44,15 @@ const store = createStore({
|
|||||||
},
|
},
|
||||||
TOGGLE_FILTER_QUERY_STREAMING(state) {
|
TOGGLE_FILTER_QUERY_STREAMING(state) {
|
||||||
let query = state.filterQuery
|
let query = state.filterQuery
|
||||||
query['streaming'] = (query['streaming'] === undefined) ? false : query['streaming']
|
let streaming = (query['streaming'] === undefined) ? false : query['streaming']
|
||||||
query['streaming'] = !(query['streaming'])
|
query['streaming'] = !(streaming)
|
||||||
query['initial'] = false
|
query['initial'] = false
|
||||||
|
|
||||||
|
if (!streaming) {
|
||||||
|
delete query['from']
|
||||||
|
delete query['to']
|
||||||
|
}
|
||||||
|
|
||||||
state.filterQuery = query
|
state.filterQuery = query
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user