Skip to content

Commit 732dbab

Browse files
authored
Merge pull request #33 from lcahlander/master
Merge to master
2 parents 0032f23 + 5927a6f commit 732dbab

File tree

9 files changed

+559
-63
lines changed

9 files changed

+559
-63
lines changed

src/main/js/frontend/package-lock.json

Lines changed: 343 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/js/frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"react-bootstrap": "^2.0.3",
1818
"react-bootstrap-icons": "^1.6.1",
1919
"react-dom": "^17.0.2",
20+
"react-json-view": "^1.21.3",
2021
"react-router": "^6.1.1",
2122
"react-router-dom": "^6.2.1",
2223
"react-scripts": "5.0.0",

src/main/js/frontend/src/App.css

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,21 @@ body {
4848
.NLPContent {
4949
height: 100%;
5050
width: 100%;
51-
background-color: lightgray;
5251
}
5352
.LoadingContent {
5453
height: 100%;
5554
width: 100%;
56-
background-color: lightgoldenrodyellow;
55+
}
56+
57+
.i-misc {
58+
color: green;
59+
}
60+
61+
.i-per {
62+
color: red;
63+
}
64+
65+
.i-loc {
66+
color: blue;
5767
}
5868

src/main/js/frontend/src/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import { HashRouter as Router, Route, Routes } from "react-router-dom";
33
import Layout from "./Layout";
44
import LoadingContent from "./LoadingContent";
5+
import NERContext from "./NERContext";
56

67
function App() {
78
return (
@@ -11,6 +12,9 @@ function App() {
1112
<Route path="/loading" element={<LoadingContent/>}>
1213

1314
</Route>
15+
<Route path="/ner" element={<NERContext/>}>
16+
17+
</Route>
1418

1519
</Route>
1620
</Routes>
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import 'bootstrap/dist/css/bootstrap.min.css';
2+
import React, {useEffect, useState} from "react";
3+
import './App.css';
4+
import {Button, Col, Form, Row} from "react-bootstrap";
5+
import ReactJson from 'react-json-view';
6+
7+
function NERContext() {
8+
9+
const [running, setRunning] = useState({
10+
"arabic": { "start": null, "end": null, "isRunning": false, isLoaded: false },
11+
"english-kbp": { "start": null, "end": null, "isRunning": false, isLoaded: false },
12+
"english": { "start": null, "end": null, "isRunning": false, isLoaded: false },
13+
"chinese": { "start": null, "end": null, "isRunning": false, isLoaded: false },
14+
"french": { "start": null, "end": null, "isRunning": false, isLoaded: false },
15+
"german": { "start": null, "end": null, "isRunning": false, isLoaded: false },
16+
"spanish": { "start": null, "end": null, "isRunning": false, isLoaded: false }
17+
})
18+
19+
const [language, setLanguage] = useState("en");
20+
const [content, setContent] = useState("");
21+
const [namedEntities, setNamedEntities] = useState("");
22+
const [nerError, setNerError] = useState({ code: null, description: null, value: null, properties: {}});
23+
24+
useEffect(() => {
25+
let uri = '/exist/restxq/stanford/nlp/logs';
26+
27+
fetch(uri)
28+
.then((response) => response.json())
29+
.then(
30+
(result) => {
31+
setRunning(result.running);
32+
},
33+
(error) => {
34+
35+
}
36+
)
37+
38+
}, [])
39+
40+
// @ts-ignore
41+
function handleChange(e) {
42+
if (e.target.name === 'language') {
43+
setLanguage(e.target.value);
44+
} else {
45+
setContent(e.target.value);
46+
}
47+
}
48+
49+
function handleSubmit() {
50+
const requestOptions = {
51+
method: 'POST',
52+
headers: { 'Content-Type': 'application/json' },
53+
body: JSON.stringify({
54+
language: language,
55+
text: content
56+
})
57+
};
58+
59+
fetch("/exist/restxq/Stanford/ner", requestOptions)
60+
.then(res => res.json())
61+
.then(
62+
(result) => {
63+
if (result.text) {
64+
setNamedEntities(result.text);
65+
} else {
66+
setNerError(result);
67+
}
68+
},
69+
(error) => {
70+
71+
}
72+
)
73+
74+
}
75+
76+
return (
77+
<div style={{padding: 35}}>
78+
<Form>
79+
<Row className={'mb-3'}>
80+
<Col md={4}>
81+
<Form.Group>
82+
<Form.Label>Select language</Form.Label>
83+
<Form.Select name="language" onChange={handleChange}>
84+
<option value="en" disabled={!running.english.isLoaded}>English</option>
85+
<option value="ar" disabled={!running.arabic.isLoaded}>Arabic</option>
86+
<option value="zh" disabled={!running.chinese.isLoaded}>Chinese</option>
87+
<option value="fr" disabled={!running.french.isLoaded}>French</option>
88+
<option value="de" disabled={!running.german.isLoaded}>German</option>
89+
<option value="es" disabled={!running.spanish.isLoaded}>Spanish</option>
90+
</Form.Select>
91+
</Form.Group>
92+
</Col>
93+
</Row>
94+
<Form.Group as={Row} className={'mb-3'}>
95+
<Form.Label>Text to find named entities</Form.Label>
96+
<Form.Control as="textarea" rows={10} onChange={handleChange} />
97+
</Form.Group>
98+
<Form.Group as={Row} className={'mb-3'}>
99+
<Col sm={2}>
100+
<Button type={'submit'} onClick={handleSubmit}>Submit</Button>
101+
</Col>
102+
</Form.Group>
103+
</Form>
104+
<Row>
105+
<div>Results</div>
106+
<hr/>
107+
<div dangerouslySetInnerHTML={{__html: namedEntities}}></div>
108+
<div>{
109+
nerError.code ?
110+
<>
111+
<div><b>Code</b> <span>{nerError.code}</span></div>
112+
<div><b>Description</b> <span>{nerError.description}</span></div>
113+
<div><b>Value</b> <span>{nerError.value}</span></div>
114+
<ReactJson src={nerError.properties} />
115+
</>
116+
: null
117+
}</div>
118+
<hr/>
119+
</Row>
120+
</div>
121+
)
122+
123+
}
124+
125+
export default NERContext;

src/main/js/frontend/src/SideBarData.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ export const SideBarData = [
77
icon: <HouseDoorFill />,
88
key: "/"
99
},
10+
{
11+
label: "NER",
12+
key: "/ner"
13+
},
1014
{
1115
label: "Loading",
1216
icon: <HouseDoorFill />,

src/main/xar-resources/modules/rest-api.xqm

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
xquery version "3.1";
22

33
module namespace api = "http://exist-db.org/xquery/stanford-nlp/api";
4+
import module namespace ner = "http://exist-db.org/xquery/stanford-nlp/ner";
45
import module namespace scheduler = "http://exist-db.org/xquery/scheduler";
56
import module namespace map = "http://www.w3.org/2005/xpath-functions/map";
67

@@ -131,3 +132,37 @@ function api:logs($timestamp as xs:string*) as map(*)
131132
}
132133
}
133134
};
135+
136+
(:~
137+
: This method runs the ner:clasify($text, $properties) on the text passed in for the language specified.
138+
: @param $content the properties of the source graph in a JSON object
139+
: @see ner:properties-from-language()
140+
: @return A map
141+
: @custom:openapi-tag Natural Language Processing
142+
:)
143+
declare
144+
%rest:POST("{$content}")
145+
%rest:path("/Stanford/ner")
146+
%rest:consumes("application/json")
147+
%rest:produces("application/json")
148+
%output:media-type("application/json")
149+
%output:method("json")
150+
function api:query-text-as-json($content as xs:string) as map(*) {
151+
let $postBody := fn:parse-json(util:base64-decode($content))
152+
let $properties := ner:properties-from-language($postBody?language)
153+
let $classified := ner:classify($postBody?text, $properties)
154+
return
155+
try {
156+
map {
157+
'text' : ner:stringify($classified)
158+
}
159+
} catch * {
160+
map {
161+
'code': $err:code,
162+
'description': $err:description,
163+
'value': $err:value,
164+
'properties': $properties
165+
}
166+
}
167+
};
168+

0 commit comments

Comments
 (0)