- 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:
parent
8e0bc7c18d
commit
156bf0ae26
4
.env
Normal file
4
.env
Normal file
|
@ -0,0 +1,4 @@
|
|||
#NODE_ENV=production
|
||||
NODE_ENV=development
|
||||
|
||||
CONSTANT_VALUE=1234567
|
|
@ -1,6 +1,8 @@
|
|||
module.exports = {
|
||||
|
||||
root: true,
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
|
@ -16,5 +18,9 @@ module.exports = {
|
|||
rules: {
|
||||
"no-console": 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
9
.prettierrc
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"trailingComma": "all",
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"arrowParens": "always",
|
||||
"proseWrap": "preserve",
|
||||
"printWidth": 180
|
||||
}
|
4355
package-lock.json
generated
4355
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
|
@ -1,16 +1,22 @@
|
|||
{
|
||||
"name": "typescript-vueapp",
|
||||
"name": "tethys.viewer",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"serve": "vue-cli-service serve --port 3000",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
"lint": "vue-cli-service lint",
|
||||
"format": "prettier --write 'src/**/*.{ts,tsx}'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@openfonts/open-sans_all": "^1.44.2",
|
||||
"axios": "^0.24.0",
|
||||
"core-js": "^3.6.5",
|
||||
"qs": "^6.10.1",
|
||||
"rxjs": "^6.6.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": {
|
||||
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
||||
|
@ -22,6 +28,7 @@
|
|||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"@vue/eslint-config-typescript": "^7.0.0",
|
||||
"bulma": "^0.9.3",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eslint-plugin-vue": "^7.0.0",
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
||||
<title>
|
||||
<%= htmlWebpackPlugin.options.title %>
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body class="Site">
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't
|
||||
work properly without JavaScript enabled. Please enable it to
|
||||
continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
183
src/App.vue
183
src/App.vue
|
@ -1,27 +1,176 @@
|
|||
<template>
|
||||
<img alt="Vue logo" src="./assets/logo.png" />
|
||||
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
|
||||
<!-- <HelloWorld msg="Welcome to Your Vue.js plus 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>
|
||||
|
||||
<script lang="ts">
|
||||
import { Options, Vue } from "vue-class-component";
|
||||
import HelloWorld from "./components/HelloWorld.vue";
|
||||
|
||||
@Options({
|
||||
components: {
|
||||
HelloWorld,
|
||||
},
|
||||
})
|
||||
export default class App extends Vue {}
|
||||
import App from "./app";
|
||||
export default App;
|
||||
</script>
|
||||
|
||||
<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 {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
p,
|
||||
ol,
|
||||
ul,
|
||||
li,
|
||||
dl,
|
||||
textarea,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
51
src/api/api.ts
Normal file
51
src/api/api.ts
Normal 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
14
src/api/axiosSetup.ts
Normal 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
10
src/api/config.ts
Normal 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
175
src/app.ts
Normal 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
2
src/assets/fa/search.svg
Normal 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 |
201
src/assets/scss/main-styles.scss
Normal file
201
src/assets/scss/main-styles.scss
Normal 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%;
|
||||
}
|
||||
}
|
|
@ -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>
|
14
src/components/HelloWorld/HelloWorld.scss
Normal file
14
src/components/HelloWorld/HelloWorld.scss
Normal 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;
|
||||
}
|
10
src/components/HelloWorld/HelloWorld.ts
Normal file
10
src/components/HelloWorld/HelloWorld.ts
Normal 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;
|
||||
}
|
32
src/components/HelloWorld/HelloWorld.vue
Normal file
32
src/components/HelloWorld/HelloWorld.vue
Normal 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>
|
60
src/components/face-category/FacetCategory.ts
Normal file
60
src/components/face-category/FacetCategory.ts
Normal 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;
|
||||
}
|
||||
}
|
62
src/components/face-category/facet-category.vue
Normal file
62
src/components/face-category/facet-category.vue
Normal 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>
|
250
src/components/vs-input/vs-input.ts
Normal file
250
src/components/vs-input/vs-input.ts
Normal 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");
|
||||
}
|
||||
}
|
98
src/components/vs-input/vs-input.vue
Normal file
98
src/components/vs-input/vs-input.vue
Normal 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>
|
51
src/components/vs-result/vs-result.ts
Normal file
51
src/components/vs-result/vs-result.ts
Normal 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;
|
||||
}
|
||||
}
|
165
src/components/vs-result/vs-result.vue
Normal file
165
src/components/vs-result/vs-result.vue
Normal 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>
|
|
@ -1,4 +1,5 @@
|
|||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import "./assets/scss/main-styles.scss";
|
||||
|
||||
createApp(App).mount("#app");
|
||||
|
|
32
src/models/dataset.ts
Normal file
32
src/models/dataset.ts
Normal 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
75
src/models/headers.ts
Normal 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
50
src/models/solr.ts
Normal 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
43
src/notes.txt
Normal 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
698
src/search_page.html
Normal 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>
|
140
src/services/dataset.service.ts
Normal file
140
src/services/dataset.service.ts
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user