forked from kristjan/cjvt-valency
working on api + frontend; todo: switch corpus
This commit is contained in:
parent
8c6d6ab8ab
commit
bc4e8e2cf1
32
README.md
32
README.md
|
@ -12,7 +12,7 @@ $ git submodule update
|
||||||
|
|
||||||
|
|
||||||
### Database (2 containers)
|
### Database (2 containers)
|
||||||
Set db admin, user, pass, etc in Makefile.
|
Set db admin, user, pass, etc in 'Makefile'.
|
||||||
Spin up the database service and create users:
|
Spin up the database service and create users:
|
||||||
```bash
|
```bash
|
||||||
# $ make database-clean # opt
|
# $ make database-clean # opt
|
||||||
|
@ -38,11 +38,15 @@ $ make python-env-install
|
||||||
$ make fill-database
|
$ make fill-database
|
||||||
```
|
```
|
||||||
|
|
||||||
If all goes well, we should be able to inspect the database on `0.0.0.0:8087`.
|
If all goes well, we should be able to inspect the database, filled with corpora, on `0.0.0.0:8087`.
|
||||||
|
|
||||||
|
|
||||||
### Flask backend (1 container)
|
### Flask backend (1 container)
|
||||||
Input: see Database
|
Relies heavily on the database. Set that up first.
|
||||||
|
```bash
|
||||||
|
# $ make backend=dev # development
|
||||||
|
$ make backend-prod
|
||||||
|
```
|
||||||
|
|
||||||
API endpoints:
|
API endpoints:
|
||||||
|
|
||||||
|
@ -53,17 +57,13 @@ API endpoints:
|
||||||
|
|
||||||
|
|
||||||
### Vue frontend (1 container)
|
### Vue frontend (1 container)
|
||||||
|
Relies on Flask backend.
|
||||||
|
Before running `make`, you might need to set the correct api address.
|
||||||
|
Check `./src/frontend_vue/config/config_prod.json`.
|
||||||
|
bash
|
||||||
|
```
|
||||||
|
# $ make frontend-dev # development
|
||||||
|
$ make frontend-prod
|
||||||
|
```
|
||||||
|
|
||||||
* ngnix server
|
App available on: `http://0.0.0.0:8080`.
|
||||||
|
|
||||||
|
|
||||||
## Deployment
|
|
||||||
|
|
||||||
Preflight:
|
|
||||||
* get up DB
|
|
||||||
* prepare DB
|
|
||||||
|
|
||||||
Flight:
|
|
||||||
* start backend
|
|
||||||
* start frontend
|
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,13 @@ from pathlib import Path
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
CORPORA = ["ssj", "kres"]
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
app_index = {c: {} for c in CORPORA}
|
||||||
|
|
||||||
# when running vuejs via webpack
|
# when running vuejs via webpack
|
||||||
# CORS(app)
|
# CORS(app)
|
||||||
CORS(app, resources={r"/api/*": {
|
CORS(app, resources={r"/api/*": {
|
||||||
|
@ -54,20 +58,18 @@ def home(pathname):
|
||||||
return redirect(url_for("index"), code=302)
|
return redirect(url_for("index"), code=302)
|
||||||
|
|
||||||
|
|
||||||
|
# @app.route("/api/words/<corpus>")
|
||||||
|
# def api_words(corpus):
|
||||||
@app.route("/api/words")
|
@app.route("/api/words")
|
||||||
def api_words():
|
def api_words():
|
||||||
return json.dumps({
|
return json.dumps({
|
||||||
"sorted_words": vallex.sorted_words,
|
"sorted_words": app_index["ssj"]["words"], # todo - make corpus as arg
|
||||||
"has_se": vallex.has_se
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/functors")
|
@app.route("/api/functors")
|
||||||
def api_functors():
|
def api_functors():
|
||||||
res = []
|
# return array ([functor, len])
|
||||||
for key in sorted(vallex.functors_index.keys()):
|
return json.dumps(app_index["ssj"]["functors"])
|
||||||
res.append((key, len(vallex.functors_index[key])))
|
|
||||||
return json.dumps(res)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/register", methods=["POST"])
|
@app.route("/api/register", methods=["POST"])
|
||||||
|
@ -376,6 +378,60 @@ def api_senses_update():
|
||||||
vallex.db["v2_sense_map"].insert(data)
|
vallex.db["v2_sense_map"].insert(data)
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|
||||||
|
def prepare_db():
|
||||||
|
def helper_tid_to_token(tid, tokens):
|
||||||
|
for t in tokens:
|
||||||
|
if t["tid"] == tid:
|
||||||
|
return t
|
||||||
|
return None
|
||||||
|
|
||||||
|
# update entries (add headwords and fuctors for indexing)
|
||||||
|
for corpus in ["ssj", "kres"]:
|
||||||
|
for e in valdb[corpus].find({}):
|
||||||
|
#! hw_tids are not array ids
|
||||||
|
hw_tids = list(set([x["from"] for x in e["srl_links"]]))
|
||||||
|
hw_tokens = [helper_tid_to_token(tid, e["tokens"]) for tid in hw_tids]
|
||||||
|
headwords = [(t["lemma"] if t["msd"][0] == "G" else t["lemma"] + "_") for t in hw_tokens]
|
||||||
|
e["headwords"] = headwords
|
||||||
|
|
||||||
|
functors = list(set([x["afun"] for x in e["srl_links"]]))
|
||||||
|
e["headwords"] = headwords
|
||||||
|
e["functors"] = functors
|
||||||
|
|
||||||
|
valdb[corpus].save(e)
|
||||||
|
|
||||||
|
# create app_index (used in frontend, left side word index)
|
||||||
|
for corpus in CORPORA:
|
||||||
|
res_hws = {}
|
||||||
|
res_fns = {}
|
||||||
|
for e in valdb[corpus].find({}):
|
||||||
|
for hw in e["headwords"]:
|
||||||
|
if hw in res_hws:
|
||||||
|
res_hws[hw] += 1
|
||||||
|
else:
|
||||||
|
res_hws[hw] = 1
|
||||||
|
for fn in e["functors"]:
|
||||||
|
if fn in res_fns:
|
||||||
|
res_fns[fn] += 1
|
||||||
|
else:
|
||||||
|
res_fns[fn] = 1
|
||||||
|
|
||||||
|
alphabetical = {}
|
||||||
|
for k, e in res_hws.items():
|
||||||
|
fst = k[0].lower()
|
||||||
|
if fst in alphabetical:
|
||||||
|
alphabetical[fst].append((k, e))
|
||||||
|
else:
|
||||||
|
alphabetical[fst] = [(k, e)]
|
||||||
|
|
||||||
|
for k, e in alphabetical.items():
|
||||||
|
alphabetical[k] = sorted(e, key=lambda x: x[0])
|
||||||
|
app_index[corpus]["words"] = alphabetical
|
||||||
|
|
||||||
|
functors = [(k, e) for (k, e) in res_fns.items()]
|
||||||
|
functors = sorted(functors, key=lambda x: x[0])
|
||||||
|
app_index[corpus]["functors"] = functors
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("Starting app.py main()")
|
print("Starting app.py main()")
|
||||||
|
@ -407,8 +463,10 @@ if __name__ == "__main__":
|
||||||
)
|
)
|
||||||
valdb = client.valdb
|
valdb = client.valdb
|
||||||
|
|
||||||
|
if config["prepare_db"]:
|
||||||
|
prepare_db()
|
||||||
|
|
||||||
# log.info("[*] Starting app.py with config:\n%s".format(config))
|
# log.info("[*] Starting app.py with config:\n%s".format(config))
|
||||||
log.info("[*] Starting app.py with config:\n{}".format(config))
|
log.info("[*] Starting app.py with config:\n{}".format(config))
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
app.run(host=str(config["host"]), port=int(config["port"]))
|
app.run(host=str(config["host"]), port=int(config["port"]))
|
||||||
|
|
|
@ -3,4 +3,5 @@ debug: True
|
||||||
port: 5004
|
port: 5004
|
||||||
host: localhost
|
host: localhost
|
||||||
logfile: "/var/log/valency_backend.log"
|
logfile: "/var/log/valency_backend.log"
|
||||||
|
prepare_db: True
|
||||||
---
|
---
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"api_addr": "http://193.2.76.103:5004"
|
"api_addr": "http://0.0.0.0:5004"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"api_addr": "http://localhost:5004"
|
"api_addr": "http://0.0.0.0:5004"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"api_addr": "http://193.2.76.103:5004"
|
"api_addr": "0.0.0.0:5004"
|
||||||
}
|
}
|
||||||
|
|
40
src/frontend_vue/package-lock.json
generated
40
src/frontend_vue/package-lock.json
generated
|
@ -116,7 +116,7 @@
|
||||||
"argparse": {
|
"argparse": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
"integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"sprintf-js": "~1.0.2"
|
"sprintf-js": "~1.0.2"
|
||||||
|
@ -2979,9 +2979,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"esprima": {
|
"esprima": {
|
||||||
"version": "2.7.3",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
"integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"esrecurse": {
|
"esrecurse": {
|
||||||
|
@ -5128,13 +5128,13 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "3.7.0",
|
"version": "3.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz",
|
||||||
"integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=",
|
"integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^2.6.0"
|
"esprima": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jsesc": {
|
"jsesc": {
|
||||||
|
@ -5255,9 +5255,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.10",
|
"version": "4.17.11",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||||
},
|
},
|
||||||
"lodash.camelcase": {
|
"lodash.camelcase": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
|
@ -9679,6 +9679,24 @@
|
||||||
"mkdirp": "~0.5.1",
|
"mkdirp": "~0.5.1",
|
||||||
"sax": "~1.2.1",
|
"sax": "~1.2.1",
|
||||||
"whet.extend": "~0.9.9"
|
"whet.extend": "~0.9.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"esprima": {
|
||||||
|
"version": "2.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
|
||||||
|
"integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"js-yaml": {
|
||||||
|
"version": "3.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz",
|
||||||
|
"integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"argparse": "^1.0.7",
|
||||||
|
"esprima": "^2.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tapable": {
|
"tapable": {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<div class="my-home container-fluid">
|
<div class="my-home container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="serach" class="col-sm-2 border-right fill">
|
<div id="serach" class="col-sm-2 border-right fill">
|
||||||
<LWords v-if="navSS()"></LWords>
|
<LWords v-if="this.$root.store.selIndex === 'words'"></LWords>
|
||||||
<LFunctors v-else></LFunctors>
|
<LFunctors v-else></LFunctors>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
|
@ -35,11 +35,6 @@ export default {
|
||||||
LFunctors: LFunctors,
|
LFunctors: LFunctors,
|
||||||
MainDispl: MainDispl,
|
MainDispl: MainDispl,
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
navSS: function () {
|
|
||||||
return this.$root.storeGet("navSS") === "words"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ export default {
|
||||||
this.$http.get(this.$root.storeGet("api_addr") + "/api/words")
|
this.$http.get(this.$root.storeGet("api_addr") + "/api/words")
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
component.$root.store.api_error = null
|
component.$root.store.api_error = null
|
||||||
component.$root.store.has_se = response.data["has_se"]
|
// component.$root.store.has_se = response.data["has_se"]
|
||||||
component.letters = response.data["sorted_words"]
|
component.letters = response.data["sorted_words"]
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<label class="radio-inline"><input value="one" v-model="$root.store.radio" v-on:change="reload()" checked="" type="radio" name="optradio">posamezne povedi</label>
|
<label class="radio-inline"><input value="one" v-model="$root.store.radio" v-on:change="reload()" checked="" type="radio" name="optradio">posamezne povedi</label>
|
||||||
<label class="radio-inline"><input value="two" v-model="$root.store.radio" v-on:change="reload()" type="radio" name="optradio">skupne udeleženske vloge</label>
|
<label class="radio-inline"><input value="two" v-model="$root.store.radio" v-on:change="reload()" type="radio" name="optradio">skupne udeleženske vloge</label>
|
||||||
<label v-if="this.$root.store.navSS === 'words'" class="radio-inline"><input value="three" v-model="$root.store.radio" v-on:change="reload()" type="radio" name="optradio">po meri</label>
|
<label v-if="this.$root.store.selIndex === 'words'" class="radio-inline"><input value="three" v-model="$root.store.radio" v-on:change="reload()" type="radio" name="optradio">po meri</label>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -206,7 +206,7 @@ export default {
|
||||||
reload: function () {
|
reload: function () {
|
||||||
this.state = "loading"
|
this.state = "loading"
|
||||||
this.sentences = {}
|
this.sentences = {}
|
||||||
if (this.$root.store.navSS === "functors") this.getFFrames(this.hw)
|
if (this.$root.store.selIndex === "functors") this.getFFrames(this.hw)
|
||||||
else {
|
else {
|
||||||
this.getFrames(this.hw)
|
this.getFrames(this.hw)
|
||||||
if (this.$root.store.radio === "three") {
|
if (this.$root.store.radio === "three") {
|
||||||
|
|
|
@ -6,17 +6,30 @@
|
||||||
<b-collapse is-nav id="nav_collapse">
|
<b-collapse is-nav id="nav_collapse">
|
||||||
|
|
||||||
<b-navbar-nav>
|
<b-navbar-nav>
|
||||||
<b-nav-item-dropdown text="Prikaz" right>
|
<b-nav-item-dropdown text="korpus" right>
|
||||||
<b-dropdown-item v-for="option in search_options"
|
<b-dropdown-item v-for="option in optCorpora"
|
||||||
|
:value="option"
|
||||||
|
:key="option"
|
||||||
|
v-on:click="updateCorpus(option)"
|
||||||
|
>
|
||||||
|
{{ option }}
|
||||||
|
</b-dropdown-item>
|
||||||
|
</b-nav-item-dropdown>
|
||||||
|
</b-navbar-nav>
|
||||||
|
|
||||||
|
<b-navbar-nav>
|
||||||
|
<b-nav-item-dropdown text="prikaz" right>
|
||||||
|
<b-dropdown-item v-for="option in optIndexes"
|
||||||
:value="option.val"
|
:value="option.val"
|
||||||
:key="option.val"
|
:key="option.val"
|
||||||
v-on:click="setNavSS(option.val)">
|
v-on:click="updateIndex(option.val)"
|
||||||
|
>
|
||||||
{{ option.key }}
|
{{ option.key }}
|
||||||
</b-dropdown-item>
|
</b-dropdown-item>
|
||||||
</b-nav-item-dropdown>
|
</b-nav-item-dropdown>
|
||||||
</b-navbar-nav>
|
</b-navbar-nav>
|
||||||
|
|
||||||
<!-- Right aligned nav items -->
|
<!-- Right aligned nav items -->
|
||||||
<b-navbar-nav class="ml-auto" right v-if="this.loggedIn()">
|
<b-navbar-nav class="ml-auto" right v-if="this.loggedIn()">
|
||||||
<b-nav-item>
|
<b-nav-item>
|
||||||
Uporabnik: {{ this.$root.store.username }}
|
Uporabnik: {{ this.$root.store.username }}
|
||||||
|
@ -46,19 +59,27 @@ export default {
|
||||||
name: "Nav",
|
name: "Nav",
|
||||||
props: ["appState"],
|
props: ["appState"],
|
||||||
data() {return {
|
data() {return {
|
||||||
search_options: [
|
optIndexes: [
|
||||||
{key: "besede", val: "words"},
|
{key: "besede", val: "words"},
|
||||||
{key: "udeleženske vloge", val: "functors"},
|
{key: "udeleženske vloge", val: "functors"},
|
||||||
],
|
],
|
||||||
|
optCorpora: ["kres", "ssj"],
|
||||||
}},
|
}},
|
||||||
methods: {
|
methods: {
|
||||||
setNavSS(val) {
|
updateAll() {
|
||||||
this.$root.store.radio = "one"
|
this.$root.store.radio = "one"
|
||||||
this.$root.store.navSS = val
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: "Home"
|
name: "Home"
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
updateCorpus(val) {
|
||||||
|
this.$root.store.selCorpus = val
|
||||||
|
this.updateAll()
|
||||||
|
},
|
||||||
|
updateIndex(val) {
|
||||||
|
this.$root.store.selIndex = val
|
||||||
|
this.updateAll()
|
||||||
|
},
|
||||||
loggedIn() {
|
loggedIn() {
|
||||||
return (this.$root.store.token !== null)
|
return (this.$root.store.token !== null)
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,7 +38,8 @@ const store = {
|
||||||
// api_addr: "http://193.2.76.103:5004", // production
|
// api_addr: "http://193.2.76.103:5004", // production
|
||||||
token: null,
|
token: null,
|
||||||
username: null,
|
username: null,
|
||||||
navSS: "words",
|
selIndex: "words",
|
||||||
|
selCorpus: "kres",
|
||||||
radio: "one",
|
radio: "one",
|
||||||
has_se: [], // used for appending (se) to certain verbs
|
has_se: [], // used for appending (se) to certain verbs
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user