1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-21 21:33:18 +01:00

Adds fuzzy search modal (#1108)

* Adds fuzzy search modal

* Fixes modal bug

* Updates fuzzy with autocomplete component

* Adds better shortcut

* Fixes padding

* Fixes tests
This commit is contained in:
Amir Raminfar
2021-03-27 15:18:27 -07:00
committed by GitHub
parent e37d5b9378
commit f480c28d2a
12 changed files with 118 additions and 6 deletions

View File

@@ -4,7 +4,7 @@
<splitpanes @resized="onResized($event)">
<pane min-size="10" :size="settings.menuWidth" v-if="!isMobile && !collapseNav">
<side-menu></side-menu>
<side-menu @search="showFuzzySearch"></side-menu>
</pane>
<pane min-size="10">
<splitpanes>
@@ -42,11 +42,15 @@
import { mapActions, mapGetters, mapState } from "vuex";
import { Splitpanes, Pane } from "splitpanes";
import hotkeys from "hotkeys-js";
import LogContainer from "./components/LogContainer";
import SideMenu from "./components/SideMenu";
import MobileMenu from "./components/MobileMenu";
import Search from "./components/Search";
import PastTime from "./components/PastTime";
import Icon from "./components/Icon";
import FuzzySearchModal from "./components/FuzzySearchModal";
export default {
name: "App",
@@ -56,6 +60,7 @@ export default {
LogContainer,
MobileMenu,
Splitpanes,
PastTime,
Pane,
Search,
},
@@ -79,6 +84,9 @@ export default {
document.documentElement.setAttribute("data-theme", "light");
}
this.menuWidth = this.settings.menuWidth;
hotkeys("command+k, ctrl+k", (event, handler) => {
this.showFuzzySearch();
});
},
watch: {
hasSmallerScrollbars(newValue, oldValue) {
@@ -100,7 +108,7 @@ export default {
},
},
computed: {
...mapState(["isMobile", "settings"]),
...mapState(["isMobile", "settings", "containers"]),
...mapGetters(["visibleContainers", "activeContainers"]),
hasSmallerScrollbars() {
return this.settings.smallerScrollbars;
@@ -120,6 +128,14 @@ export default {
this.updateSetting({ menuWidth });
}
},
showFuzzySearch() {
this.$buefy.modal.open({
parent: this,
component: FuzzySearchModal,
animation: "false",
width: 600,
});
},
},
};
</script>

View File

@@ -0,0 +1,80 @@
<template>
<div class="panel">
<b-autocomplete
ref="autocomplete"
v-model="query"
placeholder="Search containers using ⌘ + k, ⌃k"
field="name"
open-on-focus
keep-first
expanded
:data="results"
@select="selected"
>
</b-autocomplete>
</div>
</template>
<script>
import { mapState } from "vuex";
import fuzzysort from "fuzzysort";
import PastTime from "./PastTime";
import Icon from "./Icon";
export default {
props: {
maxResults: {
default: 20,
type: Number,
},
},
data() {
return {
query: "",
};
},
name: "FuzzySearchModal",
components: {
Icon,
PastTime,
},
mounted() {
this.$nextTick(() => this.$refs.autocomplete.focus());
},
watch: {},
methods: {
selected(item) {
this.$router.push({ name: "container", params: { id: item.id, name: item.name } });
this.$emit("close");
},
},
computed: {
...mapState(["containers"]),
preparedContainers() {
return this.containers.map((c) => ({
name: c.name,
id: c.id,
created: c.created,
preparedName: fuzzysort.prepare(c.name),
}));
},
results() {
const options = {
limit: this.maxResults,
key: "preparedName",
};
if (this.query) return fuzzysort.go(this.query, this.preparedContainers, options).map((i) => i.obj);
else {
return [...this.containers].sort((a, b) => b.created - a.created);
}
},
},
};
</script>
<style lang="scss" scoped>
.panel {
height: 400px;
}
</style>

View File

@@ -8,7 +8,18 @@
</svg>
</router-link>
</div>
<div class="column is-narrow has-text-right x">
<div class="column is-narrow has-text-right px-1">
<button
class="button is-small is-rounded is-settings-control"
@click="$emit('search')"
title="Search containers (⌘ + k, ⌃k)"
>
<span class="icon">
<icon name="search"></icon>
</span>
</button>
</div>
<div class="column is-narrow has-text-right px-0">
<router-link
:to="{ name: 'settings' }"
active-class="is-active"

View File

@@ -4,6 +4,9 @@ import Meta from "vue-meta";
import Switch from "buefy/dist/esm/switch";
import Radio from "buefy/dist/esm/radio";
import Field from "buefy/dist/esm/field";
import Modal from "buefy/dist/esm/modal";
import Autocomplete from "buefy/dist/esm/autocomplete";
import store from "./store";
import config from "./store/config";
import App from "./App.vue";
@@ -14,6 +17,8 @@ Vue.use(Meta);
Vue.use(Switch);
Vue.use(Radio);
Vue.use(Field);
Vue.use(Modal);
Vue.use(Autocomplete);
const routes = [
{

View File

@@ -6,7 +6,6 @@
import { mapActions, mapGetters, mapState } from "vuex";
import LogContainer from "../components/LogContainer";
import store from "../store";
export default {
props: ["id"],

View File

@@ -70,7 +70,7 @@
</template>
<script>
import { mapActions, mapGetters, mapState } from "vuex";
import { mapState } from "vuex";
import Icon from "../components/Icon";
import PastTime from "../components/PastTime";
import config from "../store/config";

View File

@@ -30,6 +30,8 @@ $link-active: $grey-dark;
@import "~buefy/src/scss/utils/_all";
@import "~buefy/src/scss/components/_switch";
@import "~buefy/src/scss/components/_radio";
@import "~buefy/src/scss/components/_modal";
@import "~buefy/src/scss/components/_autocomplete";
html {
--scheme-main: #{$black};
@@ -141,7 +143,6 @@ html.has-custom-scrollbars {
}
}
.splitpanes__splitter {
z-index: 99;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 70 KiB