- autocomplete vor search inputs
- composer updates
This commit is contained in:
parent
e3ea9847a3
commit
300c8a13a9
16 changed files with 424 additions and 71 deletions
|
@ -22,7 +22,7 @@
|
|||
<!-- Search input section -->
|
||||
<div class="row">
|
||||
<div class="twelve columns">
|
||||
<vs-input @search="onSearch"></vs-input>
|
||||
<vs-input @search="onSearch" title="searching solr datasets" placeholder="Enter your search term..."></vs-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ export default class App extends Vue {
|
|||
numFound: number;
|
||||
|
||||
async onPaginate(start: number): Promise<void> {
|
||||
console.log(start);
|
||||
// console.log(start);
|
||||
var res = await rdrApi.search(this.searchTerm, this.activeFilterItems, start.toString());
|
||||
this.results = res.response.docs;
|
||||
}
|
||||
|
@ -65,9 +65,9 @@ export default class App extends Vue {
|
|||
if (filter.value == facetValue) {
|
||||
rObj = filter;
|
||||
} else if (this.facets[prop].some(e => e.value === facetValue)) {
|
||||
console.log(facetValue + " is included")
|
||||
// console.log(facetValue + " is included")
|
||||
var indexOfFacetValue = this.facets[prop].findIndex(i => i.value === facetValue);
|
||||
console.log(indexOfFacetValue);
|
||||
// console.log(indexOfFacetValue);
|
||||
rObj = this.facets[prop][indexOfFacetValue];
|
||||
rObj.count = facet_fields[prop][i + 1];
|
||||
} else {
|
||||
|
|
|
@ -32,12 +32,12 @@ export default {
|
|||
var limit = "&rows=" + SOLR_CONFIG["limit"];
|
||||
// var limit = solrConfig.limit;
|
||||
|
||||
var dismaxFields = "title^3 abstract^2 subject^1";
|
||||
var qfFields = "title^3 author^3 subject^2";
|
||||
var params = "fl=" + fields;
|
||||
if (term == "*%3A*") {
|
||||
params += "&defType=edismax&wt=json&indent=on"; //edismax
|
||||
} else {
|
||||
params += "&defType=dismax&qf=" + dismaxFields + "&wt=json&indent=on"; //dismax
|
||||
params += "&defType=dismax&qf=" + qfFields + "&wt=json&indent=on"; //dismax
|
||||
}
|
||||
|
||||
if (start === undefined) start = "0";
|
||||
|
@ -70,6 +70,39 @@ export default {
|
|||
let res = await axios.get(api);
|
||||
// let { data } = res.data;
|
||||
return res.data;//.response;//.docs;
|
||||
},
|
||||
|
||||
async searchTerm(term: string): Promise<any> {
|
||||
// solr endpoint
|
||||
// const host = 'http://voyagerdemo.com/';
|
||||
const host = 'https://repository.geologie.ac.at/';
|
||||
const path = 'solr/rdr_data/select?';
|
||||
var base = host + path;
|
||||
|
||||
//const fields = 'id,server_date_published,abstract_output,title_output,title_additional,author,subject'; // fields we want returned
|
||||
var fields = ["id",
|
||||
"server_date_published",
|
||||
"abstract_output",
|
||||
"title_output",
|
||||
"title_additional",
|
||||
"author",
|
||||
"subject"].toString();
|
||||
|
||||
|
||||
//var dismaxFields = "title^3 abstract^2 subject^1";
|
||||
var qfFields = "title^3 author^2 subject^1";
|
||||
var params = "fl=" + fields;
|
||||
// if (term == "*%3A*") {
|
||||
// params += "&defType=edismax&wt=json&indent=on"; //edismax
|
||||
// } else {
|
||||
params += "&defType=edismax&qf=" + qfFields + "&wt=json&indent=on"; //dismax
|
||||
// }
|
||||
|
||||
var query = "&q=" + term + "*";
|
||||
var api = base + params + query;
|
||||
|
||||
let res = await axios.get(api);
|
||||
return res.data;//.response;//.docs;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { Vue, Component, Prop } from 'vue-property-decorator';
|
||||
// import Vue from "vue";
|
||||
import { Component, Prop } from 'vue-property-decorator';
|
||||
import Vue from "vue";
|
||||
|
||||
@Component
|
||||
export default class VsPagination extends Vue {
|
||||
|
|
|
@ -1,12 +1,263 @@
|
|||
import Vue from "vue";
|
||||
import { Component, Provide } from "vue-property-decorator";
|
||||
import { Component, Prop, Watch } from 'vue-property-decorator';
|
||||
import debounce from 'lodash/debounce';
|
||||
import rdrApi from '../search-results/dataservice';
|
||||
|
||||
|
||||
|
||||
@Component({})
|
||||
export default class VsInput extends Vue {
|
||||
term = "";
|
||||
|
||||
@Prop()
|
||||
title: string;
|
||||
|
||||
@Prop({ default: 'Search' })
|
||||
placeholder: string;
|
||||
|
||||
display: string = "";
|
||||
value = null;
|
||||
error: string = null;
|
||||
//search: null,
|
||||
results: Array<any> = [];
|
||||
// suggestions: Object = {};
|
||||
//showResults: boolean = false;
|
||||
loading: boolean = false;
|
||||
isAsync: boolean = true;
|
||||
items: Array<any> = [];
|
||||
selectedIndex: number = null;
|
||||
selectedDisplay = null;
|
||||
isFocussed: boolean = false;
|
||||
|
||||
// get results() {
|
||||
// return this.items;
|
||||
// }
|
||||
|
||||
get showResults(): boolean {
|
||||
return this.results.length > 0;
|
||||
}
|
||||
|
||||
get noResults(): boolean {
|
||||
return Array.isArray(this.results) && this.results.length === 0
|
||||
}
|
||||
|
||||
get isLoading(): boolean {
|
||||
return this.loading === true
|
||||
}
|
||||
|
||||
get hasError(): boolean {
|
||||
return this.error !== null
|
||||
}
|
||||
|
||||
get suggestions(): any[] {
|
||||
var suggestion = {
|
||||
titles: [],
|
||||
authors: [],
|
||||
subjects: []
|
||||
};
|
||||
|
||||
for (let key in this.results) {
|
||||
let obj = this.results[key];
|
||||
|
||||
if (obj["title_output"].toLowerCase().indexOf(this.display) !== -1) {
|
||||
var title = obj["title_output"];
|
||||
if (!suggestion["titles"].find(value => value === title)) {
|
||||
suggestion.titles.push(title);
|
||||
}
|
||||
}
|
||||
if (this.find(obj["author"], this.display.toLowerCase()) !== "") {
|
||||
var author = this.find(obj["author"], this.display.toLowerCase());
|
||||
if (!suggestion["authors"].find(value => value === author)) {
|
||||
suggestion.authors.push(author);
|
||||
}
|
||||
|
||||
}
|
||||
if (this.find(obj["subject"], this.display.toLowerCase()) != "") {
|
||||
var subject = this.find(obj["subject"], this.display.toLowerCase());
|
||||
if (!suggestion["subjects"].find(value => value === subject)) {
|
||||
suggestion.subjects.push(subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
var suggestions = Array.prototype.concat(suggestion.titles, suggestion.authors, suggestion.subjects);
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
// @Watch('items')
|
||||
// onItemsChanged(val: Array<any>, oldVal: Array<any>) {
|
||||
// this.results = val;
|
||||
// this.loading = false;
|
||||
// }
|
||||
|
||||
// reset() {
|
||||
// this.display = "";
|
||||
// this.items = [];
|
||||
// this.showResults = false;
|
||||
// }
|
||||
/**
|
||||
* Clear all values, results and errors
|
||||
*/
|
||||
clear() {
|
||||
this.display = null;
|
||||
// this.value = null
|
||||
this.results = [];
|
||||
this.error = null;
|
||||
this.$emit('clear');
|
||||
}
|
||||
|
||||
search() {
|
||||
this.$emit("search", this.term);
|
||||
this.$emit("search", this.display);
|
||||
}
|
||||
|
||||
|
||||
searchChanged() {
|
||||
this.selectedIndex = null
|
||||
// Let's warn the parent that a change was made
|
||||
// this.$emit("input", this.display);
|
||||
if (this.display.length >= 2) {
|
||||
this.loading = true;
|
||||
this.resourceSearch();
|
||||
} else {
|
||||
this.results = [];
|
||||
}
|
||||
}
|
||||
|
||||
resourceSearch = debounce(function () {
|
||||
if (!this.display) {
|
||||
this.results = []
|
||||
return
|
||||
}
|
||||
this.loading = true;
|
||||
// this.setEventListener();
|
||||
this.request();
|
||||
}, 200);
|
||||
|
||||
async request() {
|
||||
try {
|
||||
var res = await rdrApi.searchTerm(this.display);
|
||||
this.error = null
|
||||
this.results = res.response.docs;
|
||||
this.loading = false;
|
||||
} catch (error) {
|
||||
this.error = error.message;
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the component as focussed
|
||||
*/
|
||||
focus() {
|
||||
this.isFocussed = true
|
||||
}
|
||||
/**
|
||||
* Remove the focussed value
|
||||
*/
|
||||
blur() {
|
||||
this.isFocussed = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this item selected?
|
||||
* @param {Object}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isSelected(key) {
|
||||
return key === this.selectedIndex
|
||||
}
|
||||
|
||||
onArrowDown(ev) {
|
||||
ev.preventDefault()
|
||||
if (this.selectedIndex === null) {
|
||||
this.selectedIndex = 0;
|
||||
return;
|
||||
}
|
||||
this.selectedIndex = (this.selectedIndex === this.suggestions.length - 1) ? 0 : this.selectedIndex + 1;
|
||||
this.fixScrolling();
|
||||
}
|
||||
|
||||
fixScrolling() {
|
||||
const currentElement = this.$refs.options[this.selectedIndex];
|
||||
currentElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
|
||||
}
|
||||
|
||||
onArrowUp(ev) {
|
||||
ev.preventDefault()
|
||||
if (this.selectedIndex === null) {
|
||||
this.selectedIndex = this.suggestions.length - 1;
|
||||
return;
|
||||
}
|
||||
this.selectedIndex = (this.selectedIndex === 0) ? this.suggestions.length - 1 : this.selectedIndex - 1;
|
||||
this.fixScrolling();
|
||||
}
|
||||
|
||||
onEnter() {
|
||||
if (this.selectedIndex === null) {
|
||||
this.$emit('nothingSelected', this.display);
|
||||
return;
|
||||
}
|
||||
this.select(this.suggestions[this.selectedIndex]);
|
||||
this.$emit('enter', this.display);
|
||||
}
|
||||
|
||||
select(obj) {
|
||||
if (!obj) {
|
||||
return
|
||||
}
|
||||
this.value = obj; //(obj["title_output"]) ? obj["title_output"] : obj.id
|
||||
this.display = obj;// this.formatDisplay(obj)
|
||||
this.selectedDisplay = this.display
|
||||
// this.$emit('selected', {
|
||||
// value: this.value,
|
||||
// display: this.display,
|
||||
// selectedObject: obj
|
||||
// })
|
||||
this.$emit('input', this.value);
|
||||
this.$emit("search", this.value);
|
||||
// alert(this.value);
|
||||
this.close();
|
||||
}
|
||||
|
||||
formatDisplay(obj) {
|
||||
if (obj.title_output.toLowerCase().indexOf(this.display) !== -1) {
|
||||
return obj.title_output;
|
||||
} else if (this.find(obj.author, this.display.toLowerCase()) !== "") {
|
||||
var author = this.find(obj.author, this.display.toLowerCase());
|
||||
return author;
|
||||
} else if (this.find(obj.subject, this.display.toLowerCase()) != "") {
|
||||
return this.find(obj.subject, this.display.toLowerCase());
|
||||
} else {
|
||||
return obj.id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
find(myarray, searchterm): string {
|
||||
for (var i = 0, len = myarray.length; i < len; i += 1) {
|
||||
if (typeof (myarray[i]) === 'string' && myarray[i].toLowerCase().indexOf(searchterm) !== -1) {
|
||||
// print or whatever
|
||||
return myarray[i];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the results list. If nothing was selected clear the search
|
||||
*/
|
||||
close() {
|
||||
if (!this.value || !this.selectedDisplay) {
|
||||
this.clear();
|
||||
}
|
||||
if (this.selectedDisplay !== this.display && this.value) {
|
||||
this.display = this.selectedDisplay;
|
||||
}
|
||||
this.results = [];
|
||||
this.error = null;
|
||||
//this.removeEventListener()
|
||||
this.$emit('close');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,13 +1,18 @@
|
|||
<template>
|
||||
<div class="sidebar-simplesearch">
|
||||
<!-- <form method="GET" action="//repository.geologie.ac.at/search" accept-charset="UTF-8"> -->
|
||||
<div>
|
||||
<!-- v-on:keyup.enter="search()" -->
|
||||
<div class="autocomplete__box">
|
||||
<input
|
||||
class="search-input"
|
||||
placeholder="Enter your search term..."
|
||||
class="search-input"
|
||||
name="q"
|
||||
type="text"
|
||||
v-model="term" v-on:keyup.enter="search()"
|
||||
v-model="display"
|
||||
@input="searchChanged"
|
||||
v-bind:title="title"
|
||||
v-bind:placeholder="placeholder"
|
||||
v-on:keydown.down="onArrowDown" v-on:keydown.up="onArrowUp" v-on:keydown.enter="onEnter" @keydown.tab="close"
|
||||
v-on:focus="focus"
|
||||
/>
|
||||
|
||||
<!-- <button @click="search()" class="css-1gklxk5 ekqohx90"> -->
|
||||
|
@ -26,6 +31,27 @@
|
|||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- clearButtonIcon -->
|
||||
<!-- <span v-show="!isLoading" class="autocomplete__icon autocomplete--clear" @click="clear">
|
||||
<img src="../assets/close.svg">
|
||||
</span> -->
|
||||
|
||||
<ul class="autocomplete-results pure-u-23-24" v-show="showResults">
|
||||
<li class="loading" v-if="isLoading">Loading results...</li>
|
||||
|
||||
<li
|
||||
v-else
|
||||
v-for="(result, key) in suggestions"
|
||||
:key="key"
|
||||
class="autocomplete-result-item"
|
||||
:class="{'is-active' : isSelected(key) }"
|
||||
@click.prevent="select(result)"
|
||||
ref="options"
|
||||
>
|
||||
<strong> {{ result }}</strong>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -37,11 +63,51 @@
|
|||
|
||||
// @Component({})
|
||||
// export default class VsInput extends Vue {
|
||||
// term = "";
|
||||
// term = "";
|
||||
// search() {
|
||||
// this.$emit("search", this.term);
|
||||
// }
|
||||
// }
|
||||
import VsInput from "./vs-input-class";
|
||||
export default VsInput;
|
||||
</script>
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.sidebar-simplesearch {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.autocomplete-results {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 1px solid #eeeeee;
|
||||
list-style-type: none;
|
||||
z-index: 1000;
|
||||
position: absolute;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
background: white;
|
||||
width: 100%;
|
||||
border: 1px solid #ccc;
|
||||
border-top: 0;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.autocomplete-result-item {
|
||||
list-style: none;
|
||||
text-align: left;
|
||||
padding: 7px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.autocomplete-result-item.is-active {
|
||||
background: rgba(0, 180, 255, 0.15);
|
||||
}
|
||||
|
||||
.autocomplete-result-item:hover {
|
||||
background: rgba(0, 180, 255, 0.075);
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue