- add search components: vs-result.vue, vs-input.vue, facet-category.vue

- add search models
- add opensans font
- add bulma css framework
- add axios, rxjs, vue-property-decorator
- npm updates
This commit is contained in:
Arno Kaimbacher 2021-11-12 10:13:22 +01:00
parent 8e0bc7c18d
commit 156bf0ae26
30 changed files with 4937 additions and 2044 deletions

4
.env Normal file
View File

@ -0,0 +1,4 @@
#NODE_ENV=production
NODE_ENV=development
CONSTANT_VALUE=1234567

View File

@ -1,6 +1,8 @@
module.exports = { module.exports = {
root: true, root: true,
env: { env: {
es6: true,
node: true, node: true,
}, },
extends: [ extends: [
@ -16,5 +18,9 @@ module.exports = {
rules: { rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off", "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
// 'prettier/prettier': ['error', { printWidth: 120 }],
"prettier/prettier": "error",
"@typescript-eslint/indent": ["error", 4],
// "@vue-eslint/printWidth": ["error", 120],
}, },
}; };

9
.prettierrc Normal file
View File

@ -0,0 +1,9 @@
{
"trailingComma": "all",
"tabWidth": 4,
"semi": true,
"singleQuote": false,
"arrowParens": "always",
"proseWrap": "preserve",
"printWidth": 180
}

4365
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,22 @@
{ {
"name": "typescript-vueapp", "name": "tethys.viewer",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve --port 3000",
"build": "vue-cli-service build", "build": "vue-cli-service build",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint",
"format": "prettier --write 'src/**/*.{ts,tsx}'"
}, },
"dependencies": { "dependencies": {
"@openfonts/open-sans_all": "^1.44.2",
"axios": "^0.24.0",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"qs": "^6.10.1",
"rxjs": "^6.6.0",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-class-component": "^8.0.0-0" "vue-class-component": "^8.0.0-0",
"vue-property-decorator": "^9.1.2"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.18.0", "@typescript-eslint/eslint-plugin": "^4.18.0",
@ -22,6 +28,7 @@
"@vue/compiler-sfc": "^3.0.0", "@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-prettier": "^6.0.0", "@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^7.0.0", "@vue/eslint-config-typescript": "^7.0.0",
"bulma": "^0.9.3",
"eslint": "^6.7.2", "eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1", "eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.0.0", "eslint-plugin-vue": "^7.0.0",

View File

@ -1,17 +1,26 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang=""> <html lang="">
<head>
<meta charset="utf-8"> <head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title><%= htmlWebpackPlugin.options.title %></title> <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
</head> <title>
<body> <%= htmlWebpackPlugin.options.title %>
<noscript> </title>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </head>
</noscript>
<div id="app"></div> <body class="Site">
<!-- built files will be auto injected --> <noscript>
</body> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't
</html> work properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,27 +1,176 @@
<template> <template>
<img alt="Vue logo" src="./assets/logo.png" /> <!-- <HelloWorld msg="Welcome to Your Vue.js plus TypeScript App" /> -->
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" /> <div id="page_style" class="site-content page__style page__description" autocomplete="off">
<!-- <div class="content column is-half is-offset-6" style="text-align: right">
<a class="button" href="/default" target="_self"><img class="icon-spacing" src="/static/images/fa/firefox.svg"
style="width: 16px; height: 16px;"><img class="icon-spacing" src="/static/images/fa/chrome.svg"
style="width: 16px; height: 16px;">
<img class="icon-spacing" src="/static/images/fa/opera.svg" style="width: 16px; height: 16px;"> <img
src="/static/images/fa/plus.svg" style="width: 16px; height: 16px;"></a>
<a class="button" href="/account" target="_self"> <img src="/static/images/fa/user.svg"
style="width: 16px; height: 16px;"> </a>
</div>
<div id="home_padding"></div>
<div style="text-align: center;">
<a href="/" id="logo_home" target="_self">
<img id="logo_img_home" src="/static/images/is/logo_text_black.png" width="20%" style="min-width: 140px;">
</a>
</div> -->
<vs-input @search-change="onSearch" title="searching solr datasets" placeholder="Enter your search term..." />
<div class="column is-half is-offset-one-quarter" style="padding-top: 0; margin-top: 0">
<!-- <div class="tabs is-centered">
<ul id="id-results-tabs">
<li class="search_tab is-active">
<a target="_self">Web</a>
</li>
<li class="search_tab">
<a target="_self">Images</a>
</li>
<li class="search_tab">
<a target="_self">Videos</a>
</li>
<li class="search_tab">
<a target="_self">Homepages</a>
</li>
<li class="search_tab">
<a target="_self">Food</a>
</li>
<li class="search_tab">
<a target="_self">Books</a>
</li>
</ul>
</div> -->
<div v-if="results.length > 0" class="result-list-info">
<div class="resultheader">
Your search yielded
<strong>{{ numFound }}</strong> results:
</div>
</div>
<!-- <div id="id-pro-sign-in" class="notification" style="">
<button
class="delete"
onclick="dismissProNotification();"
></button>
It appears that you're not signed in. You'll need to
<a href="/pro" target="_self">signup for Pro</a> or become a
<a
href="https://coil.com/?ref=InfinitySearch2229"
target="_self"
>Coil member</a
>
to access our results.
</div> -->
</div>
<div class="columns">
<div id="id-side-bar" class="column is-4 sidebar_column" style="padding-top: 1.2rem; padding-right: 1.5rem">
<div id="externals" class="">
<div class="card" v-for="(facetItems, key, index) in facets" :key="index" name="external_card" style="margin-bottom: 0px">
<facet-category v-bind:facetItems="facetItems" v-bind:filterName="key" @filter="onFilter"></facet-category>
</div>
<!-- <div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a
id="https://en.wikipedia.org/w/index.php?search="
href="https://en.wikipedia.org/w/index.php?search=test"
name="external_link_0"
style="display: block"
rel="noreferrer noopener"
target="_self"
>
<img src="/static/images/favicons/wikipedia.ico" name="external_icon_0'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_0" style="font-size: 0.95rem; display: inline"> Wikipedia Results </span>
</a>
</p>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a
id="https://duckduckgo.com/?q="
href="https://duckduckgo.com/?q=test"
name="external_link_1"
style="display: block"
rel="noreferrer noopener"
target="_self"
>
<img src="/static/images/favicons/duckduckgo.ico" name="external_icon_1'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_1" style="font-size: 0.95rem; display: inline"> DuckDuckGo Results </span>
</a>
</p>
<span
class="clickableIcon"
onclick="removeExternalClickable(this)"
style="cursor: pointer; display: block; margin: auto; margin-right: 6px; min-width: 0.5em"
>
<img
class="handle fa-ellipsis-v"
src="/static/images/fa/ellipsis-v.svg"
style="cursor: pointer; display: block; margin: auto; margin-right: 12px; min-width: 0.5em; width: 16px; height: 16px"
/>
</span>
</header>
</div> -->
</div>
</div>
<div class="column is-8 results_column" style="padding-top: 1.2rem; padding-right: 0.5rem">
<div class="results">
<!-- Results section -->
<vs-result v-bind:datasets="results"></vs-result>
</div>
</div>
</div>
</div>
<!-- <vs-input
@search="onSearch"
title="searching solr datasets"
placeholder="Enter your search term..."
/>
<div v-if="results.length > 0" class="result-list-info">
<div class="resultheader">
Your search yielded
<strong>{{ numFound }}</strong> results:
</div>
</div> -->
</template> </template>
<script lang="ts"> <script lang="ts">
import { Options, Vue } from "vue-class-component"; import App from "./app";
import HelloWorld from "./components/HelloWorld.vue"; export default App;
@Options({
components: {
HelloWorld,
},
})
export default class App extends Vue {}
</script> </script>
<style lang="scss"> <style lang="scss">
// #app {
// font-family: Avenir, Helvetica, Arial, sans-serif;
// -webkit-font-smoothing: antialiased;
// -moz-osx-font-smoothing: grayscale;
// text-align: center;
// color: #2c3e50;
// margin-top: 60px;
// width: 100%;
// height: 100%;
// }
#app { #app {
font-family: Avenir, Helvetica, Arial, sans-serif; p,
-webkit-font-smoothing: antialiased; ol,
-moz-osx-font-smoothing: grayscale; ul,
text-align: center; li,
color: #2c3e50; dl,
margin-top: 60px; textarea,
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 5px;
}
} }
</style> </style>

51
src/api/api.ts Normal file
View File

@ -0,0 +1,51 @@
import initializeAxios from "./axiosSetup";
import { axiosRequestConfiguration } from "./config";
import { map } from "rxjs/operators";
// import { Observable } from "@reactivex/rxjs/compat";
import { defer, Observable } from "rxjs";
import { AxiosResponse } from "axios";
// https://ichi.pro/de/so-wickeln-sie-axios-mit-typescript-und-react-in-rxjs-ein-118892823169891
const axiosInstance = initializeAxios(axiosRequestConfiguration);
const get = <T>(url: string, queryParams?: any): Observable<T> => {
return defer(() => axiosInstance.get<T>(url, { params: queryParams })).pipe(map((result: AxiosResponse) => result.data));
};
// const post = <T>(
// url: string,
// body: object,
// queryParams?: object
// ): Observable<T | void> => {
// return defer(() =>
// axiosInstance.post<T>(url, body, { params: queryParams })
// ).pipe(map((result) => result.data));
// };
// const put = <T>(
// url: string,
// body: object,
// queryParams?: object
// ): Observable<T | void> => {
// return defer(() =>
// axiosInstance.put<T>(url, body, { params: queryParams })
// ).pipe(map((result) => result.data));
// };
// const patch = <T>(
// url: string,
// body: object,
// queryParams?: object
// ): Observable<T | void> => {
// return defer(() =>
// axiosInstance.patch<T>(url, body, { params: queryParams })
// ).pipe(map((result) => result.data));
// };
// const deleteR = <T>(url: string, id: number): Observable<T | void> => {
// return defer(() => axiosInstance.delete(`${url}/${id}`)).pipe(
// map((result) => result.data)
// );
// };
export default { get };

14
src/api/axiosSetup.ts Normal file
View File

@ -0,0 +1,14 @@
import axios, { AxiosRequestConfig, AxiosInstance, AxiosPromise } from "axios";
const initialization = (config: AxiosRequestConfig): AxiosInstance => {
axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
const axiosInstance = axios.create(config);
/*
Add default headers, interceptors etc..
*/
return axiosInstance;
};
export default initialization;

10
src/api/config.ts Normal file
View File

@ -0,0 +1,10 @@
import { AxiosRequestConfig } from "axios";
import * as qs from "qs";
export const axiosRequestConfiguration: AxiosRequestConfig = {
responseType: "text",
headers: {
"Content-Type": "application/json",
},
paramsSerializer: (params) => qs.stringify(params, { arrayFormat: "repeat" }),
};

175
src/app.ts Normal file
View File

@ -0,0 +1,175 @@
import { Options, Vue } from "vue-class-component";
import HelloWorld from "./components/HelloWorld/HelloWorld.vue";
import VsInput from "./components/vs-input/vs-input.vue";
import VsResult from "./components/vs-result/vs-result.vue";
import FacetCategory from "./components/face-category/facet-category.vue";
import { SolrSettings } from "@/models/solr";
import { DatasetService } from "./services/dataset.service";
import { Dataset, Suggestion } from "./models/dataset";
import { SolrResponse, FacetFields, FacetItem, FacetResults } from "./models/headers";
import { ActiveFilterCategories } from "@/models/solr";
@Options({
components: {
HelloWorld,
VsInput,
VsResult,
FacetCategory,
},
})
export default class App extends Vue {
results: Array<any> = [];
// facets: FacetFields = new FacetFields();
facets: FacetResults = new FacetResults();
searchTerm!: string | Suggestion;
// activeFilterCategories: Object = {};
activeFilterCategories: ActiveFilterCategories = new ActiveFilterCategories(); // = new Array<ActiveFilterCategory>();
pagination: any = {
total: 0,
per_page: 2,
current_page: 0,
// last_page: 0,
data: [],
};
loaded = false;
numFound!: number;
private solr: SolrSettings = {
core: "rdr_data", // SOLR.core;
host: "tethys.at",
};
private rdrAPI!: DatasetService;
private error = "";
mounted() {
this.rdrAPI = new DatasetService();
}
// onSearch(term: string): void {
onSearch(suggestion: Suggestion | string): void {
// let queryOperator;
// if (typeof suggestion === "string") {
// suggestion = suggestion + "*";
// queryOperator = "or";
// } else if (suggestion instanceof Suggestion) {
// // term = suggestion.value;
// queryOperator = "and";
// }
// if (term) {
// term = term.trim();
// } else {
// term = "*%3A*";
// }
this.activeFilterCategories = new ActiveFilterCategories();
// this.facets = {};
this.searchTerm = suggestion;
this.rdrAPI.facetedSearch(suggestion, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe(
(res: SolrResponse) => this.dataHandler(res),
(error: any) => this.errorHandler(error),
);
}
private dataHandler(res: SolrResponse): void {
// this.results = datasets;
this.results = res.response.docs;
this.numFound = res.response.numFound;
// pagination
this.pagination["total"] = res.response.numFound;
this.pagination["per_page"] = res.responseHeader.params.rows;
this.pagination["current_page"] = 1;
this.pagination["data"] = res.response.docs;
// facets
// const facet_fields = res.facet_counts.facet_fields;
// for (const prop in facet_fields) {
// const facetCategory: FacetCategory<any> = facet_fields[prop];
// const facetValues = facetCategory.key.values.map((facet_value: any, i: number) => {
// if (i % 2 === 0 && typeof facet_value == "string") {
// //var rObj = { value: facet, count: facet_fields[prop][i + 1] };
// // FiletrItem with value and count
// const rObj = new FilterItem(facet_value, facetCategory.key.values[i + 1]);
// return rObj;
// }
// });
// .filter(function (el: FilterItem) {
// return el != null && el.count > 0;
// });
// //this.facets.push({ filterName: prop, values: facetValues });
// this.facets[prop] = facetValues;
// }
const facet_fields: FacetFields = res.facets;
let prop: keyof typeof facet_fields;
for (prop in facet_fields) {
const facetCategory = facet_fields[prop];
if (facetCategory.buckets) {
const facetItems: Array<FacetItem> = facetCategory.buckets;
const facetValues = facetItems.filter(function (el) {
return el != null && el.count > 0;
});
// this.facets[prop] = facetCategory;
this.facets[prop] = facetValues;
}
}
}
private errorHandler(err: any): void {
this.error = err;
// this.loading = false;
}
onFilter(facetItem: FacetItem): void {
// console.log(facetItem.val);
// if (!this.activeFilterCategories.hasOwnProperty(facetItem.category)) {
if (!Object.prototype.hasOwnProperty.call(this.activeFilterCategories, facetItem.category)) {
this.activeFilterCategories[facetItem.category] = new Array<string>();
}
// if (!this.activeFilterCategories[facetItem.category].some((e) => e === facetItem.val)) {
if (!this.activeFilterCategories[facetItem.category].some((e) => e === facetItem.val)) {
this.activeFilterCategories[facetItem.category].push(facetItem.val);
this.rdrAPI.facetedSearch(this.searchTerm, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe(
(res: SolrResponse) => this.dataHandler(res),
(error: any) => this.errorHandler(error),
);
// alert(this.activeFilterCategories[filter.Category]);
// var res = await rdrApi.search(this.searchTerm, this.activeFilterCategories, this.solrCore, this.solrHost);
// this.results = res.response.docs;
// this.numFound = res.response.numFound;
// // pagination
// this.pagination['total'] = res.response.numFound;
// this.pagination['per_page'] = res.responseHeader.params.rows;
// this.pagination['current_page'] = 1;
// this.pagination['data'] = res.response.docs;
// var facet_fields = res.facet_counts.facet_fields;
// for (var prop in facet_fields) {
// var facetValues = facet_fields[prop].map((facetValue, i) => {
// if (i % 2 === 0) {
// // var rObj = { value: facetValue, count: facet_fields[prop][i + 1] };
// var rObj;
// if (filter.value == facetValue) {
// rObj = filter;
// } else if (this.facets[prop].some(e => e.value === facetValue)) {
// // console.log(facetValue + " is included")
// var indexOfFacetValue = this.facets[prop].findIndex(i => i.value === facetValue);
// // console.log(indexOfFacetValue);
// rObj = this.facets[prop][indexOfFacetValue];
// rObj.count = facet_fields[prop][i + 1];
// } else {
// rObj = new FilterItem(facetValue, facet_fields[prop][i + 1]);
// }
// return rObj;
// }
// }).filter(function (el) {
// return el != null && el.count > 0;
// });
// // this.facets.push({ filterName: prop, values: facetValues });
// this.facets[prop] = facetValues;
}
}
}

2
src/assets/fa/search.svg Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<svg fill="grey" width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1216 832q0-185-131.5-316.5t-316.5-131.5-316.5 131.5-131.5 316.5 131.5 316.5 316.5 131.5 316.5-131.5 131.5-316.5zm512 832q0 52-38 90t-90 38q-54 0-90-38l-343-342q-179 124-399 124-143 0-273.5-55.5t-225-150-150-225-55.5-273.5 55.5-273.5 150-225 225-150 273.5-55.5 273.5 55.5 225 150 150 225 55.5 273.5q0 220-124 399l343 343q37 37 37 90z"/></svg>

After

Width:  |  Height:  |  Size: 493 B

View File

@ -0,0 +1,201 @@
@charset "utf-8";
@import "~bulma";
// @import "@fontsource/open-sans"; // Defaults to weight 400.
@import "~@openfonts/open-sans_all/index.css";
html, body {
font-family: "Open Sans", sans-serif;
font-size: 0.92rem;
}
/*footer {*/
/* !*position: absolute;*!*/
/* bottom: 0;*/
/* width: 100%;*/
/*}*/
.site {
display: flex;
min-height: 100vh;
flex-direction: column;
}
.site-content {
flex: 1;
}
.search-button-icon {
color: rgb(219, 219, 219);
}
.search-button-icon:hover {
color: rgb(74, 74, 74);
}
.icon-spacing {
margin-right: 3px;
}
svg,
:before,
:after {
box-sizing: border-box;
padding: auto;
margin: auto;
}
.hide {
display: none;
}
.animate_content {
animation: animate 3s ease;
}
@keyframes animate {
10% {
transform: scale(1, 0.004);
}
35% {
transform: scale(0.001, 0.004);
opacity: 1;
}
50% {
transform: scale(0.001, 0.004);
opacity: 0;
}
85% {
transform: scale(1, 0.004);
opacity: 1;
}
100% {
transform: scale(1, 1);
}
}
.page_description {
font-weight: 300;
text-align: center;
}
.page_style {
background: transparent;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 100%;
width: 100%;
margin: auto;
overflow: hidden;
}
.rabbit-grid {
padding-left: 2%;
padding-right: 2%;
}
.rabbit-card {
height: 10vh;
margin: auto;
justify-content: center;
border-radius: 6px;
}
.rabbit-text {
font-size: 1.75vh;
}
/* flip the pane when hovered */
.flip-container:hover .flipper,
.flip-container.hover .flipper {
transform: rotateY(180deg);
}
.flip-container,
.front,
.back {
width: 100%;
height: 100%;
}
/* flip speed goes here */
.flipper {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front,
.back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
/* for firefox 31 */
transform: rotateY(0deg);
border-radius: 6px;
}
/* back, initially hidden pane */
.back {
position: absolute;
transform: rotateY(180deg);
width: 100%;
display: table;
justify-content: center;
border-radius: 6px;
border-style: solid;
border-width: 1px;
}
.back a {
display: table-cell;
vertical-align: middle;
text-align: center;
}
#home_padding {
margin-top: 7%;
}
@media screen and (max-width: 768px) {
#featured_area {
display: none;
}
#home_message {
display: none;
}
#home_padding {
margin-top: 15%;
}
#firefox_button,
#chrome_button,
#opera_button {
display: none;
}
}
@media screen and (min-width: 769px) {
.autocomplete-column.is-offset-one-quarter,
.autocomplete-column.is-offset-one-quarter-tablet {
margin-left: 25%;
}
.autocomplete-column.is-half,
.autocomplete-column.is-half-tablet {
flex: none;
width: 50%;
}
}

View File

@ -1,126 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
>vue-cli documentation</a
>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
target="_blank"
rel="noopener"
>babel</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript"
target="_blank"
rel="noopener"
>typescript</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
target="_blank"
rel="noopener"
>eslint</a
>
</li>
</ul>
<h3>Essential Links</h3>
<ul>
<li>
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
>Forum</a
>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
>Community Chat</a
>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
>Twitter</a
>
</li>
<li>
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
</li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li>
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
>vue-router</a
>
</li>
<li>
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
</li>
<li>
<a
href="https://github.com/vuejs/vue-devtools#vue-devtools"
target="_blank"
rel="noopener"
>vue-devtools</a
>
</li>
<li>
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
>vue-loader</a
>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
rel="noopener"
>awesome-vue</a
>
</li>
</ul>
</div>
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
@Options({
props: {
msg: String,
},
})
export default class HelloWorld extends Vue {
msg!: string;
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,14 @@
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}

View File

@ -0,0 +1,10 @@
import { Options, Vue } from "vue-class-component";
import { Prop } from "vue-property-decorator";
@Options({
name: "HelloWorld",
})
export default class HelloWorld extends Vue {
@Prop({ type: String })
private msg!: string;
}

View File

@ -0,0 +1,32 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a>
</li>
<li>
<a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a>
</li>
<li>
<a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a>
</li>
</ul>
</div>
</template>
<script lang="ts">
import HelloWorld from "./HelloWorld";
export default HelloWorld;
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
@import "./HelloWorld.scss"; // $text-primary would be defined in that file
</style>

View File

@ -0,0 +1,60 @@
import { FacetItem } from "@/models/headers";
import { FilterItem } from "@/models/solr";
import { Options, Vue } from "vue-class-component";
import { Prop, Emit } from "vue-property-decorator";
// import FilterItem from '../models/filter-item';
@Options({
name: "FacetCategory",
})
export default class FacetCategory extends Vue {
ITEMS_PER_FILTER = 2;
bar = "";
collapsed = true;
@Prop()
facetItems!: Array<FacetItem>;
@Prop([String])
filterName!: string;
get alias(): string {
return this.filterName == "datatype" ? "doctype" : this.filterName;
}
// get filterItems(): Array<FilterItem> {
// return this.data;
// }
get overflowing(): boolean {
//ko.observable(self.filterItems().length - self.activeFilterItems().length > ITEMS_PER_FILTER);
return this.facetItems.length > this.ITEMS_PER_FILTER;
}
get uncollapseLabelText(): string {
if (this.collapsed == true) {
// return myLabels.viewer.sidePanel.more; //"More results";
return "More results";
} else {
// return myLabels.viewer.sidePanel.collapse; //"Collapse";
return "Collapse";
}
}
toggle(): void {
if (this.collapsed == true) {
this.collapsed = false;
} else if (this.collapsed == false) {
this.collapsed = true;
//list.children("li:gt(4)").hide();
}
}
@Emit("filter")
activateItem(filterItem: FacetItem): FacetItem {
filterItem.category = this.alias;
filterItem.active = true;
// this.$emit("filter", filterItem);
return filterItem;
}
}

View File

@ -0,0 +1,62 @@
<template>
<div class="panel panel-default">
<!-- <h3 class="panel-title filterViewModelName">{{ filterName }}</h3> -->
<div class="panel-heading">
<h3 class="panel-title titlecase filterViewModelName">{{ filterName }}</h3>
</div>
<div class="panel-body">
<!-- e.g.language -->
<ul class="filter-items list-unstyled" v-bind:class="{ limited: facetItems.length > 1 && collapsed }">
<li v-for="(item, index) in facetItems" :key="index" class="list-group-item titlecase">
<!-- <span :class="item.Active ? 'disabled' : ''" @click.prevent="activateItem(item)">{{ item.val }} ({{ item.count }}) </span> -->
<span @click.prevent="activateItem(item)">{{ item.val }} ({{ item.count }}) </span>
</li>
</ul>
<ul class="overflowing" v-if="overflowing == true">
<li>
<span @click="toggle()">{{ uncollapseLabelText }}</span>
</li>
</ul>
</div>
</div>
</template>
<script lang="ts">
import FacetCategory from "./FacetCategory";
export default FacetCategory;
</script>
<style scoped>
/* local styles */
.disabled {
/* color: #EBEBE4; */
color: lightgray;
pointer-events: none;
text-decoration: line-through;
}
.overflowing {
color: #444444;
list-style: none;
z-index: 999;
}
.overflowing span {
color: #444444;
font-style: italic;
text-decoration: underline;
cursor: pointer;
}
.filter-items.limited li:nth-of-type(1n + 3) {
display: none;
}
ul.filter-items li span {
cursor: pointer;
/* color:#ffffff;
text-decoration: none;
font-weight: bold;
font-size: 16px; */
}
</style>

View File

@ -0,0 +1,250 @@
// import Vue from "vue";
// import { Component, Prop } from 'vue-property-decorator';
// import debounce from 'lodash/debounce';
import { DatasetService } from "../../services/dataset.service";
import { SolrSettings } from "@/models/solr";
// import { ref } from "vue";
import { Options, Vue } from "vue-class-component";
import { Prop, Emit } from "vue-property-decorator";
import { Dataset, Suggestion, SearchType } from "@/models/dataset";
@Options({
name: "VsInput",
})
export default class VsInput extends Vue {
@Prop()
private title!: string;
@Prop({ default: "Search" })
private placeholder!: string;
private display = "";
private value!: Suggestion;
private error = "";
private results: Array<Dataset> = [];
private loading = false;
private selectedIndex = 0;
private selectedDisplay = "";
private solr: SolrSettings = {
core: "rdr_data", // SOLR.core;
host: "tethys.at",
};
private rdrAPI!: DatasetService;
itemRefs!: Array<any>;
setItemRef(el: any) {
this.itemRefs.push(el);
}
beforeUpdate() {
this.itemRefs = [];
}
mounted() {
this.rdrAPI = new DatasetService();
}
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(): Suggestion[] {
// const suggestion = {
// titles: new Array<string>(),
// authors: new Array<string>(),
// subjects: new Array<string>(),
// };
const suggestions = new Array<Suggestion>();
this.results.forEach((dataset) => {
const del = dataset.title_output?.toLowerCase();
if (dataset.title_output.toLowerCase().includes(this.display.toLowerCase())) {
const title = dataset.title_output;
// if (!suggestion["titles"].find((value) => value === title)) {
// suggestion.titles.push(title);
// }
const hasTitleSuggestion = suggestions.some((suggestion) => suggestion.value === title && suggestion.type == SearchType.Title);
if (!hasTitleSuggestion) {
const suggestion = new Suggestion(title, SearchType.Title);
suggestions.push(suggestion);
}
}
if (this.find(dataset.author, this.display.toLowerCase()) !== "") {
const author = this.find(dataset.author, this.display.toLowerCase());
const hasAuthorSuggestion = suggestions.some((suggestion) => suggestion.value === author && suggestion.type == SearchType.Author);
if (!hasAuthorSuggestion) {
const suggestion = new Suggestion(author, SearchType.Author);
suggestions.push(suggestion);
}
}
if (this.find(dataset.subject, this.display.toLowerCase()) != "") {
const subject = this.find(dataset.subject, this.display.toLowerCase());
const hasSubjectSuggestion = suggestions.some((suggestion) => suggestion.value === subject && suggestion.type == SearchType.Subject);
if (!hasSubjectSuggestion) {
const suggestion = new Suggestion(subject, SearchType.Subject);
suggestions.push(suggestion);
}
}
});
return suggestions;
}
/**
* Clear all values, results and errors
**/
clear(): void {
this.display = "";
// this.value = null;
this.results = [];
this.error = "";
this.$emit("clear");
}
@Emit("search-change")
search(): string {
this.results = [];
// this.$emit("search", this.display)
return this.display;
}
searchChanged(): void {
this.selectedIndex = 0;
// 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 = [];
}
}
private resourceSearch() {
if (!this.display) {
this.results = [];
return;
}
this.loading = true;
// this.setEventListener();
this.request();
}
private request(): void {
this.rdrAPI.searchTerm(this.display, this.solr.core, this.solr.host).subscribe(
(res: Dataset[]) => this.dataHandler(res),
(error: any) => this.errorHandler(error),
() => (this.loading = false),
);
}
private dataHandler(datasets: Dataset[]): void {
this.results = datasets;
// this.$emit("search", this.display);
// this.loading = false;
}
private errorHandler(err: any): void {
this.error = err;
// this.loading = false;
}
/**
* Is this item selected?
* @param {Object}
* @return {Boolean}
*/
isSelected(key: number): boolean {
return key === this.selectedIndex;
}
onArrowDown(ev: any): void {
ev.preventDefault();
if (this.selectedIndex === null) {
this.selectedIndex = 0;
return;
}
this.selectedIndex = this.selectedIndex === this.suggestions.length - 1 ? 0 : this.selectedIndex + 1;
this.fixScrolling();
}
private fixScrolling() {
const currentElement = this.itemRefs[this.selectedIndex];
currentElement.scrollIntoView({
behavior: "smooth",
block: "nearest",
inline: "start",
});
}
onArrowUp(ev: any): void {
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(): void {
if (this.selectedIndex === null) {
this.$emit("nothingSelected", this.display);
return;
}
this.select(this.suggestions[this.selectedIndex]);
// this.$emit("enter", this.display);
}
@Emit("search-change")
select(obj: Suggestion): Suggestion {
// 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("search", this.value);
this.close();
return this.value;
}
private find(myarray: Array<string>, searchterm: string): string {
for (let 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(): void {
if (!this.value || !this.selectedDisplay) {
this.clear();
}
if (this.selectedDisplay !== this.display && this.value) {
this.display = this.selectedDisplay;
}
this.results = [];
this.error = "";
//this.removeEventListener()
this.$emit("close");
}
}

View File

@ -0,0 +1,98 @@
<template>
<div class="content column is-half is-offset-one-quarter" style="margin-top: 30px; padding-bottom: 0; margin-bottom: 0px">
<div class="field has-addons">
<div class="control is-expanded">
<input
id="search_query"
class="input is-medium"
type="text"
name="q"
autocomplete="off"
v-model="display"
v-on: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"
/>
<!-- <p>Message is: {{ display }}</p> -->
</div>
<div class="control">
<button class="button input is-medium search-button-icon" @click="search()">
<img src="../../assets/fa/search.svg" style="height: 22px; width: 22px" />
</button>
</div>
</div>
</div>
<div class="autocomplete-column is-half is-offset-one-quarter">
<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, i) in suggestions"
:key="i"
class="autocomplete-result-item"
:class="{ 'is-active': isSelected(i) }"
@click.prevent="select(result)"
:ref="setItemRef"
>
<div class="small-label">
<label>{{ result.value }} ({{ result.type }})</label>
</div>
</li>
</ul>
</div>
</template>
<script lang="ts">
import VsInput from "./vs-input";
export default VsInput;
</script>
<style>
.autocomplete-column {
display: block;
flex-basis: 0;
flex-grow: 1;
flex-shrink: 1;
padding: 0 0.75rem 0.75rem 0.75rem;
position: relative;
}
.autocomplete-results {
padding: 0;
margin: 0;
margin-left: 0em;
border: 1px solid #eeeeee;
list-style-type: none;
z-index: 1000;
position: absolute;
max-height: 200px;
overflow-y: auto;
overflow: hidden;
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>

View File

@ -0,0 +1,51 @@
import { Dataset } from "@/models/dataset";
import { Options, Vue } from "vue-class-component";
import { Prop } from "vue-property-decorator";
@Options({
name: "VsResult",
})
export default class VsResult extends Vue {
public openAccessLicences: Array<string> = ["CC-BY-4.0", "CC-BY-SA-4.0"];
@Prop()
private datasets!: Array<Dataset>;
public get results(): Array<Dataset> {
return this.datasets;
}
public getDomainWithoutSubdomain() {
const urlParts = new URL(window.location.href).hostname.split(".");
return urlParts
.slice(0)
.slice(-(urlParts.length === 4 ? 3 : 2))
.join(".");
}
private convert(unixtimestamp: number) {
// Unixtimestamp
// var unixtimestamp = document.getElementById('timestamp').value;
// Months array
const months_arr = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// Convert timestamp to milliseconds
const date = new Date(unixtimestamp * 1000);
// Year
const year = date.getFullYear();
// Month
const month = months_arr[date.getMonth()];
// Day
const day = date.getDate();
// Hours
const hours = date.getHours();
// Minutes
const minutes = "0" + date.getMinutes();
// Seconds
const seconds = "0" + date.getSeconds();
// Display date time in MM-dd-yyyy h:m:s format
const convdataTime = month + "-" + day + "-" + year + " " + hours + ":" + minutes.substr(-2) + ":" + seconds.substr(-2);
// document.getElementById('datetime').innerHTML = convdataTime;
return convdataTime;
}
}

View File

@ -0,0 +1,165 @@
<template>
<div class="column" v-for="document in results" :key="document.id">
<div class="card result-list-container">
<div class="card-content row record-elem">
<span class="label label-info" data-container="div" data-title="Publication date">
{{ convert(document.server_date_published) }}
</span>
<span class="label label-default ng-binding">{{ document.doctype }}</span>
<span v-if="openAccessLicences.includes(document.licence)" class="label label-success titlecase">Open Access</span>
<p v-if="document.identifier && document.identifier.length > 0">
<!-- <span>Author: {{ document.identifier.join(', ') }}</span> -->
<!-- <span v-for="(author,index) in document.author" :key="index">{{ author }}; </span> -->
<!-- <span>'https://doi.org/' + {{ document.identifier[0] }}</span> -->
<a target="_blank" v-bind:href="'https://doi.org/' + document.identifier[0]">
{{ "https://doi.org/" + document.identifier[0] }}
</a>
</p>
<h4>
<a
v-if="document.identifier && document.identifier.length > 0"
target="_self"
v-bind:href="'https://doi.' + getDomainWithoutSubdomain() + '/' + document.identifier[0]"
class="ng-binding"
>
{{ document.title_output }}
</a>
<a v-else target="_self" v-bind:href="'dataset/' + document.id" class="ng-binding">
{{ document.title_output }}
</a>
</h4>
<p v-if="document.author && document.author.length > 0">
<!-- <span>Author: {{ document.author.join(', ') }}</span> -->
<span v-for="(author, index) in document.author" :key="index">{{ author }}; </span>
</p>
<p class="clamped clamped-2">
<span class="text">
Abstract: {{ document.abstract_output }}
<span class="ellipsis">...</span>
<span class="fill"></span>
</span>
</p>
<p>
<span>Licence: {{ document.licence }}</span>
</p>
<span class="label label-keyword titlecase" v-for="(item, index) in document.subject" :key="index"> #{{ item }} </span>
</div>
</div>
</div>
</template>
<script lang="ts">
import VsResults from "./vs-result";
export default VsResults;
</script>
<style scoped>
/* overflow for abstracts */
.clamped {
line-height: 1.5;
overflow: hidden;
position: relative;
}
.clamped-2 {
/* Clamp to 2 lines, ie line-height x 2: */
max-height: 4.5em;
}
.ellipsis {
background: #fff;
bottom: 0;
position: absolute;
right: 0;
}
.fill {
background: #fff;
height: 100%;
position: absolute;
width: 100%;
}
/* zenodo */
.label-success {
background-color: #5cb85c;
}
.label-default {
background-color: #777;
}
.label-info {
background-color: #6aa3d5;
}
.label-keyword {
background-color: #7e7e7e;
}
.label {
display: inline-block;
padding: 0.2em 0.12em 0.3em;
font-size: 75%;
color: #fff;
border-radius: 0.25em;
margin-right: 1.25em;
/* margin-left: 10px; */
}
/* .record-elem .h4, record-elem h4 {
font-size: 18px;
} */
.record-elem p a {
color: #3ad29f;
font-size: 14px;
}
/* .record-elem h4 a {
color: #000;
} */
.record-elem h4 a {
cursor: pointer;
color: #000;
text-decoration: none;
font-weight: bold;
/* margin-left: 10px; */
font-size: 16px;
}
.record-elem h4 a:hover {
color: #777;
text-decoration: none;
}
/* .search-detail a:hover {
color: rgb(0, 128, 0);
} */
.record-elem .h4,
.record-elem h4 {
font-size: 16px;
letter-spacing: 0.05em;
margin-top: 8px;
}
.record-detail h1,
.record-detail p,
.record-elem h4,
.record-elem p,
.well {
word-wrap: break-word;
}
.record-elem p span {
color: #000;
font-size: 14px;
}
.post {
position: relative;
min-height: 1px;
padding-left: 15px;
padding-right: 15px;
box-sizing: border-box;
margin-bottom: 10px;
margin-top: 15px;
}
/* .record-elem {
border-top: 1px solid rgb(238, 238, 238);
} */
</style>

View File

@ -1,4 +1,5 @@
import { createApp } from "vue"; import { createApp } from "vue";
import App from "./App.vue"; import App from "./App.vue";
import "./assets/scss/main-styles.scss";
createApp(App).mount("#app"); createApp(App).mount("#app");

32
src/models/dataset.ts Normal file
View File

@ -0,0 +1,32 @@
export interface Dataset {
abstract_additional: Array<string>;
abstract_output: string;
author: Array<string>;
author_sort: Array<string>;
belongs_to_bibliography: boolean;
creating_corporation: string;
doctype: string;
geo_location: string;
id: number;
identifier: Array<string>;
language: string;
licence: string;
publisher_name: string;
server_date_published: Array<number>;
subject: Array<string>;
title_output: string;
year: number;
year_inverted: number;
}
export class Suggestion {
constructor(public value: string, public type: SearchType) {}
// value!: string;
// type!: SearchType;
}
export enum SearchType {
Title = "title",
Author = "author",
Subject = "subject",
}

75
src/models/headers.ts Normal file
View File

@ -0,0 +1,75 @@
import { Dataset } from "./dataset";
export interface SolrResponse {
responseHeader: ResponseHeader;
response: ResponseContent;
facets: FacetFields;
// facet_counts: FacetCount;
}
export interface ResponseHeader {
status: boolean;
QTime: number;
params: ResponseHeaderParams;
}
export interface ResponseHeaderParams {
defType: string;
rows?: number;
start?: number;
wt?: string;
// 0:'fl=id,licence,server_date_published,abstract_output,identifier,title_output,title_additional,author,subject,doctype'
// df:'title'
// facet:'on'
// indent:'on'
// json.facet.language:'{ type: "terms", field: "language" }'
// json.facet.subject:'{ type: "terms", field: "subject" }'
// q:'title:Geodaten - Blatt 49 Wels (1:50.000)'
// q.op:'and'
// rows:'10'
// start:'0'
// wt:'json'
}
export interface ResponseContent {
numFound: number;
start: number;
docs: Array<Dataset>;
}
// export interface FacetCount {
// facet_fields: FacetCategory<any>;
// }
// export class FacetCategory<T> {
// [key: string]: {
// values: T[];
// };
// }
export class FacetResults {
language!: Array<FacetItem>;
subject!: Array<FacetItem>;
}
export class FacetFields {
// count: number;
language!: FacetInstance;
subject!: FacetInstance;
// [key: string]: FacetInstance;
}
export interface FacetInstance {
[key: string]: Array<FacetItem>;
// buckets: Array<FacetItem>;
}
export interface FacetItem {
val: string;
count: number;
category: string;
active: boolean;
}

50
src/models/solr.ts Normal file
View File

@ -0,0 +1,50 @@
export interface SolrSettings {
core: string;
host: string;
}
export class ActiveFilterCategories {
// count: number;
language!: Array<string>;
subject!: Array<string>;
[key: string]: Array<string>;
}
// export class ActiveFilterCategory {
// key!: string;
// values!: Array<string>;
// // [key: string]: Array<string>;
// }
export class FilterItem {
private category: string;
val: string;
count: number;
private active: boolean;
constructor(value: string, count: number) {
this.val = value;
this.count = count;
this.active = false;
this.category = "";
}
//#region properties
get Category(): string {
return this.category;
}
set Category(theCategory: string) {
this.category = theCategory;
}
get Active(): boolean {
return this.active;
}
set Active(isActive: boolean) {
this.active = isActive;
}
//#endregion
}

43
src/notes.txt Normal file
View File

@ -0,0 +1,43 @@
// <script lang="ts">
// import { Options, Vue } from "vue-class-component";
// import HelloWorld from "./components/HelloWorld/HelloWorld.vue";
// import VsInput from "./components/vs-input/vs-input.vue";
// @Options({
// components: {
// HelloWorld,
// VsInput,
// },
// })
// export default class App extends Vue {
// async onSearch(term: string): Promise<void> {
// if (term) {
// term = term.trim();
// } else {
// term = "*%3A*";
// }
// }
// }
// </script>
npm install -g @vue/cli
vue --version
@vue/cli 4.5.15
npm install --save rxjs
npm install bulma --save-dev
npm install --save @openfonts/open-sans_all
vue inspect > out.js
npm install --save qs

698
src/search_page.html Normal file
View File

@ -0,0 +1,698 @@
<div class="columns">
<div class="column is-9 results_column" style="padding-top: 1.2rem; padding-right: 0.5rem">
<div class="column" id="loading_bar" style="padding-top: 0px; display: none">
<div class="column" style="padding-top: 0; padding-bottom: 0; margin-bottom: 0"></div>
<div class="card" style="margin-bottom: 0px">
<div class="card-content">
<div class="content">
<noscript>It appears that your Javascript is disabled. To view results on
this page, you will need to enable it. You might want to visit our
<a href="/lite/results">lite results</a>.
</noscript>
<progress class="progress is-large" max="100">60%</progress>
</div>
</div>
</div>
</div>
<div id="results">
<div class="column" style="padding-top: 0">
<div class="card" style="margin-bottom: 0px">
<div class="card-content">
<div class="content">
It looks like you're not logged in right now. you will need to
<a href="/login" target="_self">login to Pro</a> or become a
<a href="https://coil.com/?ref=InfinitySearch2229" target="_self">Coil Member</a>
to access the results.
<div class="block"></div>
<div class="columns" style="text-align: center">
<div class="column is-one-third">
<a class="button" style="width: 100%" href="/login" target="_self">Login</a>
</div>
<div class="column is-one-third">
<a class="button" style="width: 100%" href="/pro" target="_self">Learn more about
Infinity Pro</a>
</div>
<div class="column is-one-third">
<a class="button" style="width: 100%"
href="https://coil.com/?ref=InfinitySearch2229" target="_self">Learn more about
Coil</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div hidden="" id="id-custom-tab-page">
<div class="columns" style="margin-top: 1rem">
<div class="column is-one-quarter is-offset-2">
<p class="heading">Current Tabs</p>
<div id="id-current-tab-list">
<nav class="level is-mobile" id="id-web-tab">
<div class="level-item has-text-centered is-capitalized">web</div>
<div class="level-item has-text-centered is-one-quarter">
<div style="order: 2; margin-left: auto; margin-right: 0.5rem">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
<img class="handle trash" src="/static/images/fa/trash-alt.svg"
id="id-remove-tab-icon-web" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
margin-left: 0.5rem;
" onclick="removeTab(this);" />
</div>
</div>
</nav>
<nav class="level is-mobile" id="id-images-tab">
<div class="level-item has-text-centered is-capitalized">
images
</div>
<div class="level-item has-text-centered is-one-quarter">
<div style="order: 2; margin-left: auto; margin-right: 0.5rem">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
<img class="handle trash" src="/static/images/fa/trash-alt.svg"
id="id-remove-tab-icon-images" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
margin-left: 0.5rem;
" onclick="removeTab(this);" />
</div>
</div>
</nav>
<nav class="level is-mobile" id="id-videos-tab">
<div class="level-item has-text-centered is-capitalized">
videos
</div>
<div class="level-item has-text-centered is-one-quarter">
<div style="order: 2; margin-left: auto; margin-right: 0.5rem">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
<img class="handle trash" src="/static/images/fa/trash-alt.svg"
id="id-remove-tab-icon-videos" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
margin-left: 0.5rem;
" onclick="removeTab(this);" />
</div>
</div>
</nav>
<nav class="level is-mobile" id="id-homepages-tab">
<div class="level-item has-text-centered is-capitalized">
homepages
</div>
<div class="level-item has-text-centered is-one-quarter">
<div style="order: 2; margin-left: auto; margin-right: 0.5rem">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
<img class="handle trash" src="/static/images/fa/trash-alt.svg"
id="id-remove-tab-icon-homepages" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
margin-left: 0.5rem;
" onclick="removeTab(this);" />
</div>
</div>
</nav>
<nav class="level is-mobile" id="id-food-tab">
<div class="level-item has-text-centered is-capitalized">
food
</div>
<div class="level-item has-text-centered is-one-quarter">
<div style="order: 2; margin-left: auto; margin-right: 0.5rem">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
<img class="handle trash" src="/static/images/fa/trash-alt.svg"
id="id-remove-tab-icon-food" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
margin-left: 0.5rem;
" onclick="removeTab(this);" />
</div>
</div>
</nav>
<nav class="level is-mobile" id="id-books-tab">
<div class="level-item has-text-centered is-capitalized">
books
</div>
<div class="level-item has-text-centered is-one-quarter">
<div style="order: 2; margin-left: auto; margin-right: 0.5rem">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
<img class="handle trash" src="/static/images/fa/trash-alt.svg"
id="id-remove-tab-icon-books" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
margin-left: 0.5rem;
" onclick="removeTab(this);" />
</div>
</div>
</nav>
<nav class="level is-mobile" id="id-movies-tab">
<div class="level-item has-text-centered is-capitalized">
movies
</div>
<div class="level-item has-text-centered is-one-quarter">
<div style="order: 2; margin-left: auto; margin-right: 0.5rem">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
<img class="handle trash" src="/static/images/fa/trash-alt.svg"
id="id-remove-tab-icon-movies" style="
cursor: pointer;
min-width: 0.5em;
width: 16px;
height: 16px;
margin-left: 0.5rem;
" onclick="removeTab(this);" />
</div>
</div>
</nav>
</div>
</div>
<div class="column is-one-quarter is-offset-1">
<p class="heading">Add New Tabs</p>
<nav class="level">
<div class="level-item">
<div class="select">
<select id="id-add-tab-selector" style="
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans',
'Droid Sans', 'Helvetica Neue', Helvetica, Arial,
sans-serif;
">
<option id="id-tab-selector-web" value="web" style="display: none">
Web
</option>
<option id="id-tab-selector-images" value="images" style="display: none">
Images
</option>
<option id="id-tab-selector-videos" value="videos" style="display: none">
Videos
</option>
<option id="id-tab-selector-homepages" value="homepages" style="display: none">
Homepages
</option>
<option id="id-tab-selector-general" value="general">
General
</option>
<option id="id-tab-selector-food" value="food" style="display: none">
Food
</option>
<option id="id-tab-selector-books" value="books" style="display: none">
Books
</option>
<option id="id-tab-selector-movies" value="movies" style="display: none">
Movies
</option>
<option id="id-tab-selector-music" value="music">
Music
</option>
<option id="id-tab-selector-infinity" value="infinity">
Infinity
</option>
<option id="id-tab-selector-edu" value="edu">Edu</option>
<option id="id-tab-selector-pdf" value="pdf">Pdf</option>
<option id="id-tab-selector-qa" value="qa">Qa</option>
<option id="id-tab-selector-reddit" value="reddit">
Reddit
</option>
<option id="id-tab-selector-fandom" value="fandom">
Fandom
</option>
<option id="id-tab-selector-coil" value="coil">Coil</option>
<option id="id-tab-selector-no_js" value="no_js">
No Javascript
</option>
<option id="id-tab-selector-decentralized" value="decentralized">
Decentralized
</option>
</select>
</div>
</div>
<div class="level-item">
<button class="button" id="id-add-tab-button" onclick="addTab();" style="
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
">
Add
</button>
</div>
</nav>
<br />
<nav class="level">
<div class="level-item">
<button class="button" id="id-update-tabs-button" style="
order: 2;
margin-left: auto;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
" onclick="resetTabsToOriginal();">
Reset
</button>
</div>
</nav>
<div id="id-custom-tabs-error"></div>
</div>
</div>
</div>
</div>
<div id="id-side-bar" class="column is-3 sidebar_column" style="padding-top: 1.2rem; padding-right: 1.5rem">
<div id="externals" class="">
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://en.wikipedia.org/w/index.php?search="
href="https://en.wikipedia.org/w/index.php?search=test" name="external_link_0"
style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/wikipedia.ico"
name="external_icon_0'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_0"
style="font-size: 0.95rem; display: inline">
Wikipedia Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://duckduckgo.com/?q=" href="https://duckduckgo.com/?q=test" name="external_link_1"
style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/duckduckgo.ico"
name="external_icon_1'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_1"
style="font-size: 0.95rem; display: inline">
DuckDuckGo Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://www.google.com/search?q=" href="https://www.google.com/search?q=test"
name="external_link_2" style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/google.ico"
name="external_icon_2'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_2"
style="font-size: 0.95rem; display: inline">
Google Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://www.youtube.com/results?search_query="
href="https://www.youtube.com/results?search_query=test" name="external_link_3"
style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/youtube.svg"
name="external_icon_3'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_3"
style="font-size: 0.95rem; display: inline">
Youtube Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://www.amazon.com/s?k=" href="https://www.amazon.com/s?k=test"
name="external_link_4" style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/amazon.ico"
name="external_icon_4'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_4"
style="font-size: 0.95rem; display: inline">
Amazon Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://twitter.com/search?q=" href="https://twitter.com/search?q=test"
name="external_link_5" style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/twitter.png"
name="external_icon_5'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_5"
style="font-size: 0.95rem; display: inline">
Twitter Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://www.reddit.com/search/?q=" href="https://www.reddit.com/search/?q=test"
name="external_link_6" style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/reddit.ico"
name="external_icon_6'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_6"
style="font-size: 0.95rem; display: inline">
Reddit Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://github.com/search?q=" href="https://github.com/search?q=test"
name="external_link_7" style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/github.ico"
name="external_icon_7'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_7"
style="font-size: 0.95rem; display: inline">
GitHub Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
<div class="card" name="external_card" style="margin-bottom: 0px">
<header class="card-header">
<p class="card-header-title" style="font-weight: normal; padding-right: 5px">
<a id="https://www.reuters.com/search/news?blob="
href="https://www.reuters.com/search/news?blob=test" name="external_link_8"
style="display: block" rel="noreferrer noopener" target="_self">
<img onerror="imgError(this)" src="/static/images/favicons/reuters.ico"
name="external_icon_8'" class="external-icon" />
<span hidden="" class="external-text" name="external_text_8"
style="font-size: 0.95rem; display: inline">
Reuters Results
</span>
</a>
</p>
<span class="clickableIcon" onclick="removeExternalClickable(this)" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 6px;
min-width: 0.5em;
">
<img class="handle fa-ellipsis-v" src="/static/images/fa/ellipsis-v.svg" style="
cursor: pointer;
display: block;
margin: auto;
margin-right: 12px;
min-width: 0.5em;
width: 16px;
height: 16px;
" />
</span>
</header>
</div>
</div>
<div id="externals_menu">
<div class="card is-fullwidth" id="plus-minus-info" style="
margin-top: 0.5rem;
margin-bottom: 0px;
height: 2.5rem;
padding: 0.7rem;
">
<div class="columns is-vcentered is-mobile">
<div class="column" style="text-align: center">
<button class="button is-small" id="external_add" style="
border-color: transparent;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
">
<img src="/static/images/fa/plus.svg" class="cl-external-link-img" />
</button>
</div>
<div class="column is-narrow" style="text-align: center">|</div>
<div class="column" style="text-align: center">
<button class="button is-small" id="external_minus" style="
border-color: transparent;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
">
<img src="/static/images/fa/minus.svg" class="cl-external-link-img" />
</button>
</div>
<div class="column is-narrow" style="text-align: center">|</div>
<div class="column" style="text-align: center">
<div id="external-info-button" style="text-align: center">
<div style="cursor: pointer" id="externals_layout_button"
onclick="toggleExternalsLayout();">
<img id="id-externals-layout-img" class="cl-external-link-img"
src="/static/images/fa/list.svg" />
</div>
</div>
</div>
</div>
</div>
<div id="external_link_add_box" style="margin: 0.5rem" hidden="">
<div class="box is-fullwidth is" style="margin: 0; padding: 0.5rem">
<input class="input is-small" id="new_external_label" placeholder="Search Label" style="
margin: 0.25rem;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
" />
<input class="input is-small" id="new_external_link"
placeholder="Search Link (https://is.com/results?q=)" style="
margin: 0.25rem;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
" />
<input class="input is-small" id="new_external_icon"
placeholder="Icon Link (https://is.com/img.png)" style="
margin: 0.25rem;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
" />
</div>
<button class="button is-small is-outlined" id="external_input_add" style="
float: right;
margin: 0.5rem;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
">
Add
</button>
<button class="button is-small is-outlined is-danger" id="external_input_cancel" style="
float: right;
margin-top: 0.5rem;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
">
Cancel
</button>
</div>
<div id="external_input_defaults" hidden="">
<button class="button is-small is-outlined is-danger" id="external_input_defaults_button" style="
float: right;
margin-top: 0.5rem;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', Helvetica, Arial, sans-serif;
">
Reset
</button>
</div>
</div>
<br />
</div>
</div>

View File

@ -0,0 +1,140 @@
// import http from "@/http-common";
import api from "../api/api";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
import { Dataset, Suggestion } from "@/models/dataset";
import { SolrResponse } from "@/models/headers";
import { ActiveFilterCategories } from "@/models/solr";
export class DatasetService {
// for the autocomplete search
public searchTerm(term: string, solrCore: string, solrHost: string): Observable<Dataset[]> {
// solr endpoint
// const host = 'http://voyagerdemo.com/';
// const host = 'https://www.tethys.at/';''
const host = "https://" + solrHost;
const path = "/solr/" + solrCore + "/select?";
const base = host + path;
//const fields = 'id,server_date_published,abstract_output,title_output,title_additional,author,subject'; // fields we want returned
const fields = ["id", "licence", "server_date_published", "abstract_output", "title_output", "title_additional", "author", "subject", "doctype"].toString();
//var dismaxFields = "title^3 abstract^2 subject^1";
const qfFields = "title^3 author^2 subject^1";
let 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
// }
const query = "&q=" + term + "*";
// const apiU = base + params + query;
const q_params = {
"0": "fl=" + fields,
q: term + "*",
defType: "edismax",
qf: qfFields,
indent: "on",
wt: "json",
};
const stations = api.get<SolrResponse>(base, q_params).pipe(map((res: SolrResponse) => res.response.docs));
return stations;
}
public facetedSearch(
suggestion: Suggestion | string,
activeFilterCategories: ActiveFilterCategories,
solrCore: string,
solrHost: string,
start?: string,
): Observable<SolrResponse> {
// solr endpoint
// const host = 'http://voyagerdemo.com/';
//const host = 'https://www.tethys.at/';
//const host = 'https://' + solrHost;
const host = "https://" + solrHost;
const path = "/solr/" + solrCore + "/select?";
const base = host + path;
//const fields = 'id,server_date_published,abstract_output,title_output,title_additional,author,subject'; // fields we want returned
const fields = ["id", "licence", "server_date_published", "abstract_output", "identifier", "title_output", "title_additional", "author", "subject", "doctype"].toString();
// const qfFields = "title^3 author^2 subject^1";
// let params = "fl=" + fields;
// if (term == "*%3A*") {
// params += "&defType=edismax&wt=json&indent=on"; //edismax
// } else {
// params += "&defType=dismax&qf=" + qfFields + "&wt=json&indent=on"; //dismax
// }
let term, queryOperator, qfFields;
if (typeof suggestion === "string") {
term = suggestion + "*";
queryOperator = "or";
qfFields = "title^3 author^2 subject^1";
} else if (suggestion instanceof Suggestion) {
term = suggestion.type + ':"' + suggestion.value + '"';
queryOperator = "and";
qfFields = undefined;
}
if (start === undefined) start = "0";
// start = "&start=" + start;
// const facetFields =
// "&facet=on&facet.field=language&facet.field={!key=datatype}doctype&facet.field=subject"; //&fq=year:(2019)";//&facet.query=year:2018";
const filterFields = new Array<string>();
if (Object.keys(activeFilterCategories).length > 0) {
// filterFields = '["';
// const filterFields: string[] = [];
// const facet_fields: FacetFields = res.facets;
let prop: keyof typeof activeFilterCategories;
for (prop in activeFilterCategories) {
const filterItems = activeFilterCategories[prop];
// const filterItems = facetCategory.values;
// filterItems.forEach((filterItem) => {
// console.log(`${key} ${valueArray}`);
filterItems.forEach(function (value: string) {
// filterFields += "&fq=" + key + ':("' + value + '")';
filterFields.push(prop + ':("' + value + '")');
// filterFields += prop + ":" + value;
});
}
// filterFields += '"]';
}
const query = "&sort=server_date_published desc" + "&q=" + term;
// const api =
// base + params + limit + start + query + filterFields + facetFields;
// https://solr.apache.org/guide/8_4/json-request-api.html
const q_params = {
"0": "fl=" + fields,
q: term,
"q.op": queryOperator,
defType: "edismax",
qf: qfFields,
// df: "title",
indent: "on",
wt: "json",
rows: 10,
// fq: ["subject:Steiermark", "language:de"],
fq: filterFields,
start: start,
facet: "on",
// "facet.field": "language",
"json.facet.language": '{ type: "terms", field: "language" }',
"json.facet.subject": '{ type: "terms", field: "subject" }',
};
const stations = api.get<SolrResponse>(base, q_params);
// .pipe(map((res) => res.response.docs));
return stations;
}
}