search_ui/components/entity/sidebar-panels/TextSearch.vue

221 lines
5.6 KiB
Vue
Raw Permalink Normal View History

2025-02-01 11:06:10 +00:00
<template>
<div class="search-main py-3">
<form
class="entity-search-filter"
role="search"
@submit.prevent="sendQuery"
>
<div class="mb-3">
<div style="border-bottom: 1px solid var(--primary-color) !important">
<div
class="d-flex justify-content-between align-items-center mb-2 header_div"
>
<h6 style="font-family: sahel-semi-bold" class="m-0">
جستجوی در متن
</h6>
<button @click.prevent="closeList" class="btn" type="button">
<svg class="icon icon-Component-21--1">
<use xlink:href="#icon-Component-21--1"></use>
</svg>
</button>
</div>
</div>
<div class="input-group mt-2">
<div class="input-group-append">
<span class="tavasi tavasi-Component-198--1"></span>
</div>
<input
ref="search-input"
dir="rtl"
v-model.trim="searchText"
type="search"
required
class="form-control"
id="search-query"
placeholder="جستجو..."
name="search-query"
aria-label="جستجو در اسناد، عناوین و واژگان"
aria-describedby="basic-addon1"
size="50"
@keyup="sendQuery()"
@keydown="onKeyDown()"
/>
<button
v-if="searchText.length"
@click="clearSearchAndGetList"
type="button"
class="btn clear-search p-0"
>
<svg class="icon icon-search_off">
<use xlink:href="#icon-search_off"></use>
</svg>
</button>
<div class="input-group-prepend">
<span>&nbsp;&nbsp;</span>
</div>
</div>
<!-- <button
@click.prevent="isSearchModes()"
type="button"
class="btn close-search p-0 pe-1"
>
<svg class="icon icon-Component-71--1">
<use xlink:href="#icon-Component-71--1"></use>
</svg>
</button> -->
<small v-if="searchInCurrentGroup && listGetter">
جستجو در :
{{ listGetter?.title }}
</small>
</div>
</form>
<ul class="search-list firefox-scrollbar">
<li v-for="(item, index) in searchResult" :key="index">
<button
@click.prevent="jumpTo(item)"
class="btn text-end text__13"
type="button"
v-html="highLight(item)"
></button>
</li>
</ul>
</div>
</template>
<script>
// import entityViewMixin from "~/entity/mixins/entityViewMixin.js";
import searchApi from "@apis/searchApi";
export default {
props: {
item: {
default() {
return {};
},
},
},
// mixins: [entityViewMixin],
data() {
return {
typingTimer: 0,
doneTypingInterval: 800,
searchText: "",
searchInCurrentGroup: false,
searchResult: [],
};
},
methods: {
closeList() {
this.$emit("showListHeadline", {
isSearchMode: false,
isHeadingMode: false,
});
},
highLight(item, key = "content") {
let text = "";
if (item.highlight) {
if (item.highlight[key])
if (Array.isArray(item.highlight[key])) text = item.highlight[key][0];
else text = item.highlight[key];
}
if (text == "") {
let qText = this.searchText.trim();
if (qText.length >= 2) {
if (item._source[key])
text = item._source[key].replaceAll(
this.searchText,
`<span class="high-lighted">${this.searchText}</span>`
);
}
}
return (
`<span class="text__bold">${item._source?.other_info?.full_path} : </span> ` +
text
);
},
// highLightSearch(text) {
// return text.replace(
// this.searchText,
// `<span class="highlight">${this.searchText}</span>`
// );
// },
jumpTo(item) {
const { $eventBus } = useNuxtApp();
$eventBus.emit("jump-to-item", item);
},
clearSearchAndGetList() {
this.searchText = "";
this.searchResult = [];
},
sendQuery() {
clearTimeout(this.typingTimer);
this.typingTimer = setTimeout(() => {
this.searchInRules();
}, this.doneTypingInterval);
},
onKeyDown() {
clearTimeout(this.typingTimer);
},
async searchInRules() {
let qText = this.searchText.trim();
if (qText.length < 2) {
return;
}
let url = searchApi.search.textSearch;
url = url.replace("{{appname}}", import.meta.env.VITE_BUILD_NAME);
url = url.replace("{{index_key}}", this.$route.params.key);
url = url.replace("{{offset}}", 0);
url = url.replace("{{limit}}", 100);
url = url.replace("{{field}}", "content");
let filter = `qanon_id=${this.$route.params.id}&q=${qText}`;
url = url.replace("{{filter}}", filter);
try {
const { $api } = useNuxtApp();
const response = await $api(url, {
baseURL: repoUrl(),
});
this.searchResult = response.hits.hits;
} catch (err) {}
},
},
};
</script>
<style lang="scss">
.search-main {
.search-list {
height: calc(100dvh - 16em);
overflow-y: auto;
}
.high-lighted {
background-color: yellow;
padding: 0 5px;
font-weight: bold;
}
}
.header_div {
button {
&:hover {
color: #ef4444;
}
}
}
.clear-search {
&:hover {
color: #ef4444;
}
}
</style>