first commit
This commit is contained in:
commit
790940581e
|
@ -0,0 +1,3 @@
|
||||||
|
.DS_Store
|
||||||
|
__pycache__
|
||||||
|
static/bower_components
|
|
@ -0,0 +1,49 @@
|
||||||
|
from elasticsearch import Elasticsearch
|
||||||
|
from elasticsearch_dsl import *
|
||||||
|
import logging
|
||||||
|
|
||||||
|
log = logging.getLogger("ES connector")
|
||||||
|
log.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
ES_HOST = "ip-90-147-167-25.ct1.garrservices.it"
|
||||||
|
|
||||||
|
class ESObject(object):
|
||||||
|
def __init__(self, id, pid, type, title, abstract, propagated_abstract):
|
||||||
|
self.id = id
|
||||||
|
self.pid = pid
|
||||||
|
self.type = type
|
||||||
|
self.title = title
|
||||||
|
self.abstract = abstract
|
||||||
|
self.propagated_abstract = propagated_abstract
|
||||||
|
|
||||||
|
|
||||||
|
class ESResponse(object):
|
||||||
|
def __init__(self, count=0, hits=[]):
|
||||||
|
self.count = count
|
||||||
|
self.hits = hits
|
||||||
|
|
||||||
|
|
||||||
|
class ESConnector(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.index_host = ES_HOST
|
||||||
|
self.client = Elasticsearch(hosts=self.index_host, timeout=600000)
|
||||||
|
|
||||||
|
|
||||||
|
def query_after(self, query_string=None, start=0, i='propagation-after'):
|
||||||
|
s = Search(using=self.client, index=i)
|
||||||
|
if query_string is not None:
|
||||||
|
q = Q('query_string', query=query_string)
|
||||||
|
s = s.query(q)
|
||||||
|
s = s[start:start+10]
|
||||||
|
response = s.execute()
|
||||||
|
|
||||||
|
hits = []
|
||||||
|
for hit in response.hits:
|
||||||
|
hits.append(ESObject(hit.id,
|
||||||
|
hit.pid,
|
||||||
|
hit.type,
|
||||||
|
hit.title,
|
||||||
|
hit.abstract if 'abstract' in hit else '',
|
||||||
|
hit.propagated_abstract if 'propagated_abstract' in hit else ''))
|
||||||
|
|
||||||
|
return ESResponse(hits=hits, count=response.hits.total)
|
|
@ -0,0 +1,39 @@
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from starlette.staticfiles import StaticFiles
|
||||||
|
from starlette.responses import FileResponse
|
||||||
|
from fastapi import FastAPI, Form
|
||||||
|
from es_connector import ESConnector
|
||||||
|
|
||||||
|
log = logging.getLogger("TPDL2020 webapp")
|
||||||
|
log.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
log.info("TPDL2020 Webapp (re)started")
|
||||||
|
|
||||||
|
_CURDIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
app.mount('/static', StaticFiles(directory=os.path.join(_CURDIR, 'static' )))
|
||||||
|
|
||||||
|
es_connector = ESConnector()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get('/')
|
||||||
|
def root():
|
||||||
|
return FileResponse(os.path.join(os.path.join(_CURDIR, 'static'),'index.html'))
|
||||||
|
|
||||||
|
|
||||||
|
# @app.get("/favicon.ico")
|
||||||
|
# def favicon():
|
||||||
|
# return FileResponse(os.path.join(os.path.join(_CURDIR, 'static' ),'favicon.ico'))
|
||||||
|
|
||||||
|
|
||||||
|
@app.get('/api/query/')
|
||||||
|
def query_get(q='*', s:int=0, i=None):
|
||||||
|
try:
|
||||||
|
log.info("Executing query={q} start={s}".format(q=q, s=s))
|
||||||
|
result = es_connector.query_after(q, s, i)
|
||||||
|
return result
|
||||||
|
except Exception as e:
|
||||||
|
log.error(e)
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "static",
|
||||||
|
"authors": [
|
||||||
|
"Andrea Mannocci <andrea.mannocci@isti.cnr.it>"
|
||||||
|
],
|
||||||
|
"description": "",
|
||||||
|
"main": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://andremann.github.io",
|
||||||
|
"private": true,
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"jquery": "^3.5.1",
|
||||||
|
"vue": "^2.6.11",
|
||||||
|
"bootstrap": "^4.5.0",
|
||||||
|
"axios": "^0.19.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Globals
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
a,
|
||||||
|
a:focus,
|
||||||
|
a:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom default button */
|
||||||
|
.btn-secondary,
|
||||||
|
.btn-secondary:hover,
|
||||||
|
.btn-secondary:focus {
|
||||||
|
color: #333;
|
||||||
|
text-shadow: none; /* Prevent inheritance from `body` */
|
||||||
|
background-color: #fff;
|
||||||
|
border: .05rem solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Base structure
|
||||||
|
*/
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 .05rem .1rem rgba(0, 0, 0, .5);
|
||||||
|
box-shadow: inset 0 0 5rem rgba(0, 0, 0, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-container {
|
||||||
|
max-width: 42em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header
|
||||||
|
*/
|
||||||
|
.masthead {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.masthead-brand {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-masthead .nav-link {
|
||||||
|
padding: .25rem 0;
|
||||||
|
font-weight: 700;
|
||||||
|
color: rgba(255, 255, 255, .5);
|
||||||
|
background-color: transparent;
|
||||||
|
border-bottom: .25rem solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-masthead .nav-link:hover,
|
||||||
|
.nav-masthead .nav-link:focus {
|
||||||
|
border-bottom-color: rgba(255, 255, 255, .25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-masthead .nav-link + .nav-link {
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-masthead .active {
|
||||||
|
color: #fff;
|
||||||
|
border-bottom-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 48em) {
|
||||||
|
.masthead-brand {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.nav-masthead {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cover
|
||||||
|
*/
|
||||||
|
.cover {
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
|
.cover .btn-lg {
|
||||||
|
padding: .75rem 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Footer
|
||||||
|
*/
|
||||||
|
.mastfoot {
|
||||||
|
color: rgba(255, 255, 255, .5);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
body {
|
||||||
|
padding-top: 5rem;
|
||||||
|
}
|
||||||
|
.starter-template {
|
||||||
|
padding: 3rem 1.5rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<!-- Required meta tags -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
|
||||||
|
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bd-placeholder-img {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-anchor: middle;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bd-placeholder-img-lg {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="static/css/starter.css" rel="stylesheet">
|
||||||
|
<!-- <link href="static/css/cover.css" rel="stylesheet"> -->
|
||||||
|
|
||||||
|
<title>TPDL 2020 Companion WebApp</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
|
||||||
|
<a class="navbar-brand" href="#">TPDL 2020 Paper #55 WebApp</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault"
|
||||||
|
aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
|
||||||
|
<ul class="navbar-nav mr-auto">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">The paper</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="container" id="app">
|
||||||
|
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-10">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control" v-model="query" placeholder="Your query terms..."
|
||||||
|
aria-label="Your query terms..." aria-describedby="button-addon2">
|
||||||
|
<select class="form-control col-md-3" aria-describedby="button-addon2" v-model="index" v-on:change="switch_index">
|
||||||
|
<option v-bind:value="'propagation-after'">After propagation</option>
|
||||||
|
<option v-bind:value="'propagation-before'">Before propagation</option>
|
||||||
|
</select>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button class="btn btn-outline-secondary" type="button" id="button-addon2"
|
||||||
|
v-on:click="first_query">Search!</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="#" v-on:click="run_example(1)">Example 1</a>
|
||||||
|
<a href="#" v-on:click="run_example(2)">Example 2</a>
|
||||||
|
<a href="#" v-on:click="run_example(3)">Example 3</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center" v-if="hits">
|
||||||
|
<div>
|
||||||
|
<strong>Query:</strong> {{query}} - Viewing records {{start}} to {{start+10}} - <strong>Hits:</strong> {{total}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center" v-if="hits">
|
||||||
|
<div>
|
||||||
|
<nav aria-label="Page navigation example">
|
||||||
|
<ul class="pagination justify-content-center">
|
||||||
|
<li class="page-item" v-bind:class="{disabled: start < 10}" v-on:click="start >= 10 && previous_page()">
|
||||||
|
<a class="page-link" href="#" tabindex="-1" aria-disabled="true">Previous</a>
|
||||||
|
</li>
|
||||||
|
<li class="page-item" v-bind:class="{disabled: start+10 > total}"
|
||||||
|
v-on:click="start+10 <= total && next_page()">
|
||||||
|
<a class="page-link" href="#">Next</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<table class="table table-responsive">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><span class="badge badge-primary">ID</span> & <span
|
||||||
|
class="badge badge-warning">PIDs</span></th>
|
||||||
|
<th scope="col">Type</th>
|
||||||
|
<th scope="col">Metadata</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="hit in hits">
|
||||||
|
<td>
|
||||||
|
<div><span class="badge badge-primary">{{hit.id}}</span></div>
|
||||||
|
<div v-for="pid in hit.pid['_l_']"><span class="badge badge-warning">{{pid}}</span></div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>
|
||||||
|
<span v-if="hit.type == 'publication'" class="badge badge-success">publication</span>
|
||||||
|
<span v-if="hit.type == 'dataset'" class="badge badge-danger">dataset</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><strong>Titles</strong></div>
|
||||||
|
<div v-for="title in hit.title['_l_']">→ {{title}}</div>
|
||||||
|
<div><strong>Abstracts</strong></div>
|
||||||
|
<div v-for="abstract in hit.abstract['_l_']">→ {{abstract}}</div>
|
||||||
|
<div v-if="index != 'propagation-before'"><strong>Propagated abstracts</strong></div>
|
||||||
|
<div v-for="propagated in hit.propagated_abstract['_l_']">→ {{propagated}}<br />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Optional JavaScript -->
|
||||||
|
<script src="static/bower_components/vue/dist/vue.min.js"></script>
|
||||||
|
<script src="static/bower_components/axios/dist/axios.min.js"></script>
|
||||||
|
<script src="static/js/app.js"></script>
|
||||||
|
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||||
|
<script src="static/bower_components/jquery/dist/jquery.slim.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
|
||||||
|
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="static/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
var app = new Vue({
|
||||||
|
el: '#app',
|
||||||
|
data: {
|
||||||
|
query: null,
|
||||||
|
hits: null,
|
||||||
|
start: 0,
|
||||||
|
total: null,
|
||||||
|
index: 'propagation-after'
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
switch_index: function () {
|
||||||
|
this.first_query()
|
||||||
|
},
|
||||||
|
run_query: function () {
|
||||||
|
if (this.query == null)
|
||||||
|
this.query = '*';
|
||||||
|
axios
|
||||||
|
.get('/api/query?q=' + this.query + '&s=' + this.start + '&i=' + this.index)
|
||||||
|
.then(response => { this.hits = response.data.hits, this.total = response.data.count });
|
||||||
|
},
|
||||||
|
first_query: function () {
|
||||||
|
this.start = 0;
|
||||||
|
this.run_query();
|
||||||
|
},
|
||||||
|
run_example: function (n) {
|
||||||
|
switch (n) {
|
||||||
|
case 1:
|
||||||
|
this.query = "\"60|725e95aad103035a194402a606c5826d\"";
|
||||||
|
this.run_query();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
this.query = "\"PRIMAP-hist Socio-Eco dataset\"";
|
||||||
|
this.run_query();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
this.query = "shc014";
|
||||||
|
this.run_query();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
previous_page: function () {
|
||||||
|
this.start = this.start - 10;
|
||||||
|
this.run_query();
|
||||||
|
},
|
||||||
|
next_page: function () {
|
||||||
|
this.start = this.start + 10;
|
||||||
|
this.run_query();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
Loading…
Reference in New Issue