|
| 1 | +<template lang="pug"> |
| 2 | + |
| 3 | +div |
| 4 | + h3 Search |
| 5 | + |
| 6 | + div.alert.alert-danger(v-if="error") |
| 7 | + | {{error}} |
| 8 | + |
| 9 | + b-input-group(size="lg") |
| 10 | + b-input(v-model="pattern" placeholder="Regex pattern to search for") |
| 11 | + b-input-group-append |
| 12 | + b-button(type="button", @click="search()" variant="success") |
| 13 | + icon(name="search") |
| 14 | + | Search |
| 15 | + |
| 16 | + div.d-flex.mt-1 |
| 17 | + span.mr-auto.small(style="color: #666") Hostname: {{hostname}} |
| 18 | + b-button(size="sm", variant="outline-dark" style="border: 0" @click="show_options = !show_options") |
| 19 | + span(v-if="!show_options") |
| 20 | + | #[icon(name="angle-double-down")] Show options |
| 21 | + span(v-else) |
| 22 | + | #[icon(name="angle-double-up")] Hide options |
| 23 | + |
| 24 | + div(v-if="show_options") |
| 25 | + h4 Options |
| 26 | + div Hostname |
| 27 | + select(v-model="hostname") |
| 28 | + option(v-for="hostname in Object.keys($store.getters['buckets/bucketsByHostname'])") |
| 29 | + | {{hostname}} |
| 30 | + div Start: {{start.format()}} |
| 31 | + div End: {{stop.format()}} |
| 32 | + //div |
| 33 | + label Use regex |
| 34 | + input(type="checkbox" v-model="use_regex") |
| 35 | + div |
| 36 | + label Filter AFK |
| 37 | + input(type="checkbox" v-model="filter_afk") |
| 38 | + //div.form-row |
| 39 | + div.form-group.col-md-6 |
| 40 | + | Start |
| 41 | + input.form-control(type="date", :max="today", v-model="startdate") |
| 42 | + div.form-group.col-md-6 |
| 43 | + | End |
| 44 | + input.form-control(type="date", :max="tomorrow", v-model="enddate") |
| 45 | +
|
| 46 | + div.form-inline |
| 47 | + |
| 48 | + div(v-if="status == 'searching'") |
| 49 | + div #[icon(name="spinner" pulse)] Searching... |
| 50 | + |
| 51 | + div(v-if="events != null") |
| 52 | + hr |
| 53 | + |
| 54 | + div.form-group |
| 55 | + select.form-control(v-model="vis_method") |
| 56 | + option(value="eventlist") Event List |
| 57 | + option(value="timeline") Timeline |
| 58 | + option(value="summary") Summary |
| 59 | + option(value="raw") Raw JSON |
| 60 | + |
| 61 | + div(v-if="vis_method == 'timeline'") |
| 62 | + aw-timeline(type="simple", :event_type="event_type", :events="events") |
| 63 | + div(v-if="vis_method == 'eventlist'") |
| 64 | + aw-eventlist(:events="events") |
| 65 | + div(v-if="vis_method == 'summary'") |
| 66 | + input.form-control(type="text" v-model.lazy.trim="summaryKey" placeholder="data key" style="margin-bottom: 1em;") |
| 67 | + aw-summary(:fields="events", :colorfunc="colorfunc", :namefunc="namefunc") |
| 68 | + div(v-if="vis_method == 'raw'") |
| 69 | + pre {{ events }} |
| 70 | + |
| 71 | + div |
| 72 | + | Didn't find what you were looking for? |
| 73 | + br |
| 74 | + | Add a week to the search: #[b-button(size="sm" variant="outline-dark" @click="start = start.subtract(1, 'week'); search()") +1 week] |
| 75 | + |
| 76 | +</template> |
| 77 | + |
| 78 | +<style scoped lang="scss"></style> |
| 79 | + |
| 80 | +<script> |
| 81 | +import _ from 'lodash'; |
| 82 | +import moment from 'moment'; |
| 83 | +import { canonicalEvents } from '~/queries'; |
| 84 | +
|
| 85 | +import 'vue-awesome/icons/search'; |
| 86 | +import 'vue-awesome/icons/spinner'; |
| 87 | +import 'vue-awesome/icons/angle-double-down'; |
| 88 | +import 'vue-awesome/icons/angle-double-up'; |
| 89 | +
|
| 90 | +export default { |
| 91 | + name: 'Search', |
| 92 | + data() { |
| 93 | + return { |
| 94 | + pattern: '', |
| 95 | + vis_method: 'eventlist', |
| 96 | + event_type: 'currentwindow', |
| 97 | + events: null, |
| 98 | + error: '', |
| 99 | + status: null, |
| 100 | + hostname: '', |
| 101 | +
|
| 102 | + // Options |
| 103 | + show_options: false, |
| 104 | + use_regex: true, |
| 105 | + filter_afk: true, |
| 106 | + start: moment().subtract(1, 'day'), |
| 107 | + stop: moment().add(1, 'day'), |
| 108 | +
|
| 109 | + /* Summary props */ |
| 110 | + summaryKey: 'title', |
| 111 | + colorfunc: null, |
| 112 | + namefunc: null, |
| 113 | + }; |
| 114 | + }, |
| 115 | + mounted: async function () { |
| 116 | + this.colorfunc = this.summaryKeyFunc; |
| 117 | + this.namefunc = this.summaryKeyFunc; |
| 118 | + await this.$store.dispatch('buckets/ensureBuckets'); |
| 119 | + this.hostname = Object.keys(this.$store.getters['buckets/bucketsByHostname'])[0]; |
| 120 | + }, |
| 121 | + methods: { |
| 122 | + search: async function () { |
| 123 | + let query = canonicalEvents({ |
| 124 | + bid_window: 'aw-watcher-window_' + this.hostname, |
| 125 | + bid_afk: 'aw-watcher-afk_' + this.hostname, |
| 126 | + filter_afk: this.filter_afk, |
| 127 | + classes: [[['searched'], { type: 'regex', regex: this.pattern }]], |
| 128 | + filter_classes: [['searched']], |
| 129 | + }); |
| 130 | + query += '; RETURN = events;'; |
| 131 | +
|
| 132 | + const query_array = query.split(';').map(s => s.trim() + ';'); |
| 133 | + const timeperiods = [this.start.format() + '/' + this.stop.format()]; |
| 134 | + try { |
| 135 | + this.status = 'searching'; |
| 136 | + const data = await this.$aw.query(timeperiods, query_array); |
| 137 | + this.events = _.orderBy(data[0], ['timestamp'], ['desc']); |
| 138 | + this.error = ''; |
| 139 | + } catch (e) { |
| 140 | + console.error(e); |
| 141 | + this.error = e.response.data.message; |
| 142 | + } finally { |
| 143 | + this.status = null; |
| 144 | + } |
| 145 | + }, |
| 146 | + summaryKeyFunc: function (e) { |
| 147 | + return e.data[this.summaryKey]; |
| 148 | + }, |
| 149 | + }, |
| 150 | +}; |
| 151 | +</script> |
0 commit comments