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