Skip to content

Commit 787bf70

Browse files
authored
Add some key listeners to improve quality of life (#74)
Co-authored-by: frankdekker <frankdekker@users.noreply.github.com>
1 parent 1a3c097 commit 787bf70

File tree

9 files changed

+103
-66
lines changed

9 files changed

+103
-66
lines changed

frontend/src/components/SearchFilter.vue

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,31 @@
11
<script setup lang="ts">
2-
import {ref} from 'vue';
2+
import SearchFilterService from '@/services/SearchFilterService';
3+
import {onMounted, onUnmounted, ref} from 'vue';
34
4-
const expanded = ref(false);
5-
const emit = defineEmits(['add']);
5+
const filterService = new SearchFilterService();
6+
const expanded = ref(false);
7+
const emit = defineEmits(['add']);
68
7-
const addFilter = (event: MouseEvent) => {
9+
const addFilter = (event: UIEvent) => {
810
const target = event.target as HTMLElement;
911
const filter = target.closest('[data-role=filter]') as HTMLInputElement;
1012
const fields = Array.from(filter.querySelectorAll('input'));
11-
let pattern = String(filter.dataset.pattern);
12-
const strip = filter.dataset.strip;
13-
let replaced = false;
14-
15-
for (const input of fields) {
16-
const key = input.name;
17-
let val = input.value.trim();
18-
if (strip !== undefined) {
19-
val = val.replace(strip, '');
20-
}
21-
22-
const escapeVal = (val.indexOf(' ') === -1 ? val : '"' + val + '"');
23-
const matches = pattern.match('\\{' + key + '(=)?\\}');
24-
if (matches !== null) {
25-
pattern = pattern.replace(matches[0], val === '' ? '' : escapeVal + (matches[1] ?? ''));
26-
replaced = replaced || val !== '';
27-
}
28-
input.value = '';
29-
}
3013
14+
const [pattern, replaced] = filterService.createFilter(fields, filter.dataset.strip, String(filter.dataset.pattern));
3115
if (replaced) {
3216
emit('add', pattern);
3317
}
3418
}
19+
20+
// on escape, close the dropdown if visible
21+
const closeListener = function(event: KeyboardEvent) {
22+
if (event.key === 'Escape' && expanded.value === true) {
23+
event.preventDefault();
24+
expanded.value = !expanded.value;
25+
}
26+
}
27+
onMounted(() => document.addEventListener('keyup', closeListener));
28+
onUnmounted(() => document.removeEventListener('keyup', closeListener));
3529
</script>
3630

3731
<template>
@@ -59,6 +53,7 @@ const addFilter = (event: MouseEvent) => {
5953
type="text"
6054
class="form-control"
6155
placeholder="Separate multiple by pipe symbol"
56+
@keyup.enter="addFilter"
6257
aria-label="Severity"
6358
aria-describedby="filter-severity">
6459
<button class="btn btn-outline-primary" type="button" @click="addFilter">Add</button>
@@ -69,13 +64,19 @@ const addFilter = (event: MouseEvent) => {
6964
type="text"
7065
class="form-control"
7166
placeholder="Separate multiple by pipe symbol"
67+
@keyup.enter="addFilter"
7268
aria-label="Severity"
7369
aria-describedby="filter-severity">
7470
<button class="btn btn-outline-primary" type="button" @click="addFilter">Add</button>
7571
</div>
7672
<div class="input-group mb-1" data-role="filter" data-pattern="exclude:{value}">
7773
<span class="slv-input-label input-group-text" id="filter-exclude">Exclude</span>
78-
<input name="value" type="text" class="form-control" aria-label="Exclude string" aria-describedby="filter-exclude">
74+
<input name="value"
75+
type="text"
76+
class="form-control"
77+
@keyup.enter="addFilter"
78+
aria-label="Exclude string"
79+
aria-describedby="filter-exclude">
7980
<button class="btn btn-outline-primary" type="button" @click="addFilter">Add</button>
8081
</div>
8182
<div class="input-group mb-1" data-role="filter" data-pattern="context:{key=}{value}">
@@ -86,7 +87,13 @@ const addFilter = (event: MouseEvent) => {
8687
placeholder="key (optional)"
8788
aria-label="Context key (optional)"
8889
aria-describedby="filter-context">
89-
<input name="value" type="text" class="form-control" placeholder="search" aria-label="Context" aria-describedby="filter-context">
90+
<input name="value"
91+
type="text"
92+
class="form-control"
93+
placeholder="search"
94+
@keyup.enter="addFilter"
95+
aria-label="Context"
96+
aria-describedby="filter-context">
9097
<button class="btn btn-outline-primary" type="button" @click="addFilter">Add</button>
9198
</div>
9299
<div class="input-group mb-1" data-role="filter" data-pattern="extra:{key=}{value}">
@@ -97,7 +104,13 @@ const addFilter = (event: MouseEvent) => {
97104
placeholder="key (optional)"
98105
aria-label="Extra key (optional)"
99106
aria-describedby="filter-extra">
100-
<input name=value type="text" class="form-control" placeholder="search" aria-label="Extra" aria-describedby="filter-extra">
107+
<input name=value
108+
type="text"
109+
class="form-control"
110+
placeholder="search"
111+
@keyup.enter="addFilter"
112+
aria-label="Extra"
113+
aria-describedby="filter-extra">
101114
<button class="btn btn-outline-primary" type="button" @click="addFilter">Add</button>
102115
</div>
103116
<div>

frontend/src/components/SearchForm.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ defineExpose({focus});
2929
placeholder="Search log entries."
3030
aria-label="Search log entries."
3131
aria-describedby="button-search"
32-
@change="emit('navigate')"
32+
@keyup.enter="emit('navigate')"
3333
v-model="query">
3434

3535
<select class="slv-menu-sort-direction form-control"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export default class SearchFilterService {
2+
3+
public createFilter(fields: HTMLInputElement[], strip: string | undefined, pattern: string) {
4+
let replaced = false;
5+
6+
for (const input of fields) {
7+
const key = input.name;
8+
let val = input.value.trim();
9+
if (strip !== undefined) {
10+
val = val.replace(strip, '');
11+
}
12+
13+
const escapeVal = (val.indexOf(' ') === -1 ? val : '"' + val + '"');
14+
const matches = pattern.match('\\{' + key + '(=)?\\}');
15+
if (matches !== null) {
16+
pattern = pattern.replace(matches[0], val === '' ? '' : escapeVal + (matches[1] ?? ''));
17+
replaced = replaced || val !== '';
18+
}
19+
input.value = '';
20+
}
21+
22+
return [pattern, replaced];
23+
}
24+
}

frontend/src/stores/search.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import {ref} from 'vue'
55

66
export const useSearchStore = defineStore('search', () => {
77
const query = ref('');
8-
const perPage = ref('50');
8+
const perPage = ref('100');
99
const sort = ref('desc');
1010
const hostsStore = useHostsStore();
1111

1212
function toQueryString(params: { [key: string]: string } = {}): string {
1313
const bag = new ParameterBag(params);
1414
bag.set('query', query.value, '');
15-
bag.set('per_page', perPage.value, '50');
15+
bag.set('per_page', perPage.value, '100');
1616
bag.set('sort', sort.value, 'desc');
1717
bag.set('host', hostsStore.selected, 'localhost');
1818
return bag.toString();

frontend/src/views/LogView.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const navigate = () => {
2626
.set('host', hostsStore.selected, 'localhost')
2727
.set('file', file.value)
2828
.set('query', searchStore.query, '')
29-
.set('per_page', searchStore.perPage, '50')
29+
.set('per_page', searchStore.perPage, '100')
3030
.set('sort', searchStore.sort, 'desc')
3131
.set('offset', fileOffset, 0);
3232
router.push({query: params.all()});
@@ -39,7 +39,7 @@ const load = () => {
3939
.set('host', hostsStore.selected, 'localhost')
4040
.set('file', file.value)
4141
.set('query', searchStore.query, '')
42-
.set('per_page', searchStore.perPage, '50')
42+
.set('per_page', searchStore.perPage, '100')
4343
.set('sort', searchStore.sort, 'desc')
4444
.set('offset', offset.value, 0))
4545
.catch((error: Error) => {
@@ -58,7 +58,7 @@ onMounted(() => {
5858
file.value = String(route.query.file);
5959
hostsStore.selected = String(route.query.host ?? 'localhost');
6060
searchStore.query = String(route.query.query ?? '');
61-
searchStore.perPage = String(route.query.per_page ?? '50');
61+
searchStore.perPage = String(route.query.per_page ?? '100');
6262
searchStore.sort = String(route.query.sort ?? 'desc');
6363
offset.value = parseInt(String(route.query.offset ?? '0'));
6464
load();
@@ -90,7 +90,7 @@ onMounted(() => {
9090
<footer class="pt-1 pb-1 d-flex" v-show="!logRecordStore.loading">
9191
<button class="btn btn-sm btn-outline-secondary"
9292
@click="offset = 0; navigate()"
93-
v-bind:disabled="logRecordStore.records.paginator?.first !== false">
93+
v-bind:disabled="logRecordStore.records.paginator?.first !== true">
9494
First
9595
</button>
9696
<button class="ms-2 btn btn-sm btn-outline-secondary"
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"src/main.ts": {
3-
"file": "assets/main-DmmJen3C.js",
3+
"file": "assets/main-qJSxBxpi.js",
44
"name": "main",
55
"src": "src/main.ts",
66
"isEntry": true
77
},
88
"style.css": {
9-
"file": "assets/style-BG1K9lyT.css",
9+
"file": "assets/style-Bkbs4Mf9.css",
1010
"src": "style.css"
1111
}
1212
}

0 commit comments

Comments
 (0)