aboutsummaryrefslogtreecommitdiff
path: root/src/site/components/search/Search.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/site/components/search/Search.vue')
-rw-r--r--src/site/components/search/Search.vue145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/site/components/search/Search.vue b/src/site/components/search/Search.vue
new file mode 100644
index 0000000..1f55691
--- /dev/null
+++ b/src/site/components/search/Search.vue
@@ -0,0 +1,145 @@
+<template>
+ <div class="level-right">
+ <div class="level-item">
+ <b-field>
+ <SearchInput
+ ref="autocomplete"
+ v-model="query"
+ :data="filteredHints"
+ :custom-selector="handleSelect"
+ field="name"
+ class="chibisafe-input search"
+ placeholder="Search"
+ type="search"
+ open-on-focus
+ @typing="handleTyping"
+ @keydown.native.enter="onSubmit">
+ <template slot-scope="props">
+ <b>{{ props.option.name }}:</b>
+ <small>
+ {{ props.option.valueFormat }}
+ </small>
+ </template>
+ </SearchInput>
+ <p class="control">
+ <b-button type="is-chibisafe" @click="onSubmit">
+ Search
+ </b-button>
+ </p>
+ </b-field>
+ </div>
+ </div>
+</template>
+
+<script>
+import SearchInput from '~/components/search-input/SearchInput.vue';
+
+export default {
+ components: {
+ SearchInput
+ },
+ props: {
+ hiddenHints: {
+ 'type': Array,
+ 'default': () => []
+ }
+ },
+ data() {
+ return {
+ query: '',
+ hints: [
+ {
+ name: 'tag',
+ valueFormat: 'name',
+ hint: ''
+ },
+ {
+ name: 'album',
+ valueFormat: 'name',
+ hint: ''
+ },
+ {
+ name: 'before',
+ valueFormat: 'specific date',
+ hint: ''
+ },
+ {
+ name: 'during',
+ valueFormat: 'specific date',
+ hint: ''
+ },
+ {
+ name: 'after',
+ valueFormat: 'specific date',
+ hint: ''
+ },
+ {
+ name: 'file',
+ valueFormat: 'generated name',
+ hint: ''
+ }
+ ],
+ filteredHints: []
+ };
+ },
+ created() {
+ this.hints = this.hints.filter(({ name }) => this.hiddenHints.indexOf(name) === -1);
+ this.filteredHints = this.hints; // fixes the issue where on pageload, suggestions wont load
+ },
+ methods: {
+ handleSelect(selected, currentValue) {
+ this.$refs.autocomplete.focus();
+ if (!currentValue) { return `${selected.name}:`; }
+ if (/[^:][\s|;|,]+$/gi.test(currentValue)) return `${currentValue}${selected.name}:`;
+ return currentValue.replace(/\w+$/gi, `${selected.name}:`);
+ },
+ handleTyping(qry) {
+ qry = qry || '';
+ // get the last word or group of words
+ let lastWord = (qry.match(/("[^"]*")|[^\s]+/g) || ['']).pop().toLowerCase();
+ // if there's an open/unbalanced quote, don't autosuggest
+ if (/^[^"]*("[^"]*"[^"]*)*(")[^"]*$/.test(qry)) {
+ this.filteredHints = [];
+ return;
+ }
+ // don't autosuggest if we have an open query but no text yet
+ if (/:\s+$/gi.test(qry)) {
+ this.filteredHints = [];
+ return;
+ }
+ // if the above query didn't match (all quotes are balanced
+ // and the previous tag has value
+ // check if we're about to start a new tag
+ if (/\s+$/gi.test(qry)) {
+ this.filteredHints = this.hints;
+ return;
+ }
+
+ // ignore starting `-` from lastword, because - is used to
+ // exclude something, so -alb should autosuggest album
+ lastWord = lastWord.replace(/^-/, '');
+
+ // if we got here, then we handled all special cases
+ // now take last word, and check if we can autosuggest a tag
+ this.filteredHints = this.hints.filter(hint => hint.name
+ .toString()
+ .toLowerCase()
+ .indexOf(lastWord) === 0);
+ },
+ onSubmit(event) {
+ if (event.key === 'Enter') {
+ if (/:$/gi.test(this.query)) { return; }
+ }
+ this.$emit('search', this.query, event);
+ }
+ }
+};
+</script>
+
+<style lang="scss" scoped>
+ .search {
+ ::v-deep .dropdown-content {
+ background-color: #323846;
+ }
+ }
+</style>