Skip to content

Commit 30d9237

Browse files
authored
Merge pull request #12 from LD4P/v11-update-pyscript
Updates pyscript to 2024.11.1
2 parents 5dfb4c1 + ad94f42 commit 30d9237

File tree

7 files changed

+114
-73
lines changed

7 files changed

+114
-73
lines changed

index.html

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,17 @@
22
<html>
33
<head>
44
<title>Sinopia Linked Data - Graph Explorer</title>
5-
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
5+
<link rel="stylesheet" href="https://pyscript.net/releases/2024.11.1/core.css" />
66
<link href="static/css/main.css" rel="stylesheet" />
77
<link href="static/css/header.css" rel="stylesheet" />
88
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.3/font/bootstrap-icons.css">
99
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
10-
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
10+
<script type="module" src="https://pyscript.net/releases/2024.11.1/core.js"></script>
1111
<style>
1212
strong {
1313
font-weight: 800;
1414
}
1515
</style>
16-
<py-config type="toml">
17-
packages = ["pandas", "markdown", "Jinja2", "./static/wheels/rdflib-7.1.1-py3-none-any.whl"]
18-
19-
[[fetch]]
20-
from = "src"
21-
files = ["helpers.py", "load_rdf.py", "query_rdf.py", "sinopia_api.py", "state.py"]
22-
23-
</py-config>
24-
<py-script>
25-
__version__ = "1.0.5"
26-
import asyncio
27-
import sys
28-
import js
29-
# Hack to load rdflib
30-
# setattr(sys.stderr, 'isatty', lambda : True)
31-
32-
from pyodide.ffi import create_proxy
33-
34-
import helpers
35-
36-
import rdflib
37-
38-
39-
BIBFRAME = rdflib.Namespace("http://id.loc.gov/ontologies/bibframe/")
40-
SINOPIA = rdflib.Namespace("http://sinopia.io/vocabulary/")
41-
42-
from sinopia_api import show_groups
43-
from load_rdf import bibframe_sparql as bf_sparql_widget, build_graph, download_graph
44-
from query_rdf import download_query_results, run_query
45-
46-
47-
48-
async def load_content():
49-
for element_id in ['intro',
50-
'retrieve-rdf',
51-
'bf-work-instance-item-rdf',
52-
'sparql-summary'
53-
]:
54-
await helpers.render_markdown(element_id)
55-
56-
57-
asyncio.ensure_future(load_content())
58-
59-
bf_sparql_widget("bf-sparql-query")
60-
61-
helpers.set_versions(__version__)
62-
63-
</py-script>
6416
</head>
6517
<body>
6618
<div class="editor-navbar">
@@ -116,21 +68,21 @@ <h4>Version <span id="version" ></span></h4>
11668
<div class="row">
11769
<div class="col">
11870
<div class="form-check">
119-
<input type="radio" py-click="asyncio.ensure_future(show_groups('Development'))" name="sinopia_env" value="Development" class="form-check-input">
71+
<input type="radio" py-click="show_groups" name="sinopia_env" value="Development" class="form-check-input">
12072
<label for="https://api.development.sinopia.io/" class="form-check-label">Development</label>
12173
</input>
12274
</div>
12375
<div class="form-check">
124-
<input type="radio" py-click="asyncio.ensure_future(show_groups('Stage'))" value="Stage" name="sinopia_env" class="form-check-input">
76+
<input type="radio" py-click="show_groups" value="Stage" name="sinopia_env" class="form-check-input">
12577
<label for="https://api.stage.sinopia.io/" class="form-check-label">Stage</label>
12678
</input>
12779
</div>
12880
<div class="form-check">
129-
<input type="radio" py-click="asyncio.ensure_future(show_groups('Production'))" value="Production" name="sinopia_env" class="form-check-input">
81+
<input type="radio" py-click="show_groups" value="Production" name="sinopia_env" class="form-check-input">
13082
<label for="https://api.sinopia.io/" class="form-check-label">Production</label>
13183
</input>
13284
</div>
133-
<button class="btn btn-primary btn-lg" py-click="asyncio.ensure_future(build_graph())">
85+
<button class="btn btn-primary btn-lg" py-click="build_graph">
13486
<i class="spinner-border d-none" id="graph-loading-status"></i>
13587
Build Graph
13688
</button>
@@ -220,5 +172,30 @@ <h5 class="modal-title" id="graph-repl-modal-title">Graph Explorer - Python REPL
220172
</div>
221173
</div>
222174

175+
<!-- Load modal -->
176+
<div class="modal fade" tabindex="-1" id="splashModal">
177+
<div class="modal-dialog modal-fullscreen-sm-down">
178+
<div class="modal-content">
179+
<div class="modal-header">
180+
<h5 class="modal-title">Graph Explorer Initialization</h5>
181+
<button type="button" id="splashModalCloseBtn" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
182+
</div>
183+
<div class="modal-body">
184+
Loading...
185+
<div class="spinner-border text-secondary" role="status">
186+
<span class="visually-hidden">Loading...</span>
187+
</div>
188+
</div>
189+
</div>
190+
</div>
191+
</div>
192+
193+
<script>
194+
document.addEventListener('DOMContentLoaded', function () {
195+
var myModal = new bootstrap.Modal('#splashModal', {});
196+
myModal.show();
197+
});
198+
</script>
199+
<script type="py" src="./main.py" config="./pyconfig.json"></script>
223200
</body>
224201
</html>

main.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
__version__ = "1.1.0"
2+
import asyncio
3+
import sys
4+
import js
5+
6+
7+
from pyodide.ffi import create_proxy
8+
9+
import helpers
10+
11+
import rdflib
12+
13+
BIBFRAME = rdflib.Namespace("http://id.loc.gov/ontologies/bibframe/")
14+
SINOPIA = rdflib.Namespace("http://sinopia.io/vocabulary/")
15+
16+
from sinopia_api import show_groups
17+
from load_rdf import bibframe_sparql as bf_sparql_widget, build_graph, download_graph
18+
from query_rdf import download_query_results, run_query
19+
20+
21+
async def load_content():
22+
for element_id in [
23+
"intro",
24+
"retrieve-rdf",
25+
"bf-work-instance-item-rdf",
26+
"sparql-summary",
27+
]:
28+
await helpers.render_markdown(element_id)
29+
30+
31+
asyncio.ensure_future(load_content())
32+
33+
bf_sparql_widget("bf-sparql-query")
34+
35+
helpers.set_versions(__version__)
36+
37+
splash_modal_close_btn = js.document.getElementById("splashModalCloseBtn")
38+
splash_modal_close_btn.click()

pyconfig.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"packages": [
3+
"pandas",
4+
"markdown",
5+
"Jinja2",
6+
"pyparsing",
7+
"./static/wheels/isodate-0.6.1-py2.py3-none-any.whl",
8+
"./static/wheels/rdflib-7.1.1-py3-none-any.whl"
9+
],
10+
"files": {
11+
"./src/helpers.py": "./helpers.py",
12+
"./src/load_rdf.py": "./load_rdf.py",
13+
"./src/query_rdf.py": "./query_rdf.py",
14+
"./src/sinopia_api.py": "./sinopia_api.py",
15+
"./src/state.py": "./state.py"
16+
}
17+
}

src/load_rdf.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ async def _get_all_graph(api_url: str, limit: int = 250) -> None:
2424
while loading_resources:
2525
result = await pyfetch(next_url)
2626
payload = await result.json()
27-
for i,row in enumerate(payload["data"]):
27+
for i, row in enumerate(payload["data"]):
2828
if not "data" in row:
2929
js.console.log(f"No data for {i}")
3030
continue
@@ -49,7 +49,7 @@ async def _get_group_graph(group: str, api_url: str, limit: int = 2_500) -> None
4949
initial_url = f"{api_url}resource?limit={limit}&group={group}&start={start}"
5050
initial_result = await pyfetch(initial_url)
5151
group_payload = await initial_result.json()
52-
for i,row in enumerate(group_payload["data"]):
52+
for i, row in enumerate(group_payload["data"]):
5353
if not "data" in row:
5454
js.console.log(f"No RDF found for {row.get('uri', 'bad url')}")
5555
continue
@@ -65,7 +65,7 @@ async def _get_group_graph(group: str, api_url: str, limit: int = 2_500) -> None
6565
return SINOPIA_GRAPH
6666

6767

68-
async def build_graph() -> rdflib.Graph:
68+
async def build_graph(*args) -> rdflib.Graph:
6969
groups_selected = js.document.getElementById("env-groups")
7070
individual_resources = js.document.getElementById("resource-urls")
7171
sinopia_env_radio = js.document.getElementsByName("sinopia_env")
@@ -134,18 +134,22 @@ async def build_graph() -> rdflib.Graph:
134134
Download Graph
135135
</button>
136136
<ul class="dropdown-menu" aria-labelledby="rdf-download-file">
137-
<li><a py-click="asyncio.ensure_future(download_graph('ttl'))" class="dropdown-item" href="#">Turtle (.ttl)</a></li>
138-
<li><a class="dropdown-item" py-click="asyncio.ensure_future(download_graph('xml'))" href="#">XML (.rdf)</a></li>
139-
<li><a class="dropdown-item" py-click="asyncio.ensure_future(download_graph('json-ld'))" href="#">JSON-LD (.json)</a></li>
140-
<li><a class="dropdown-item" py-click="asyncio.ensure_future(download_graph('nt'))" href="#">N3 (.nt)</a></li>
137+
<li><a py-click="download_graph" data-serialization="ttl" class="dropdown-item" href="#">Turtle (.ttl)</a></li>
138+
<li><a class="dropdown-item" py-click="download_graph" data-serialization="xml" href="#">XML (.rdf)</a></li>
139+
<li><a class="dropdown-item" py-click="download_graph" data-serialization="json-ld" href="#">JSON-LD (.json)</a></li>
140+
<li><a class="dropdown-item" py-click="download_graph" data-serialization="nt" href="#">N3 (.nt)</a></li>
141141
</ul>
142142
</div>
143143
</div>
144144
"""
145145
)
146146

147147

148-
async def download_graph(serialization: str):
148+
async def download_graph(event):
149+
anchor = event.target
150+
serialization = anchor.getAttribute("data-serialization")
151+
152+
js.console.log(f"In graph, {serialization}")
149153
if len(SINOPIA_GRAPH) < 1:
150154
js.alert("Empty graph cannot be download")
151155
return
@@ -223,7 +227,7 @@ def bibframe(element_id: str, urls: list):
223227
</textarea>
224228
</div>
225229
<div class="mb-3">
226-
<button class="btn btn-primary" py-click="asyncio.ensure_future(run_query())">Run query</button>
230+
<button class="btn btn-primary" py-click="run_query">Run query</button>
227231
</div>
228232
</div>"""
229233
)
@@ -232,5 +236,4 @@ def bibframe(element_id: str, urls: list):
232236
def bibframe_sparql(element_id: str):
233237
wrapper_div = js.document.getElementById(element_id)
234238
all_namespaces = NAMESPACES + [("rdf", rdflib.RDF), ("rdfs", rdflib.RDFS)]
235-
js.console.log(f"All namespaces {all_namespaces}")
236239
wrapper_div.innerHTML = sparql_template.render(namespaces=all_namespaces)

src/query_rdf.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
Download Results
2424
</button>
2525
<ul class="dropdown-menu" aria-labelledby="rdf-download-file">
26-
<li><a py-click="asyncio.ensure_future(download_query_results('csv'))" class="dropdown-item" href="#">CSV (.csv)</a></li>
27-
<li><a class="dropdown-item" py-click="asyncio.ensure_future(download_query_results('json'))" href="#">JSON (.json)</a></li>
26+
<li><a py-click="download_query_results" data-serialization='csv' class="dropdown-item" href="#">CSV (.csv)</a></li>
27+
<li><a class="dropdown-item" py-click="download_query_results" data-serialization='json' href="#">JSON (.json)</a></li>
2828
</ul>
2929
</div>
3030
</div>
@@ -50,13 +50,14 @@
5050
)
5151

5252

53-
async def download_query_results(serialization: str):
53+
async def download_query_results(event):
54+
serialization = event.target.getAttribute("data-serialization")
5455
js.console.log(f"Download query results {serialization} {len(RESULTS_DF)}")
5556
mime_type, content = None, None
5657
match serialization:
5758
case "csv":
5859
mime_type = "text/csv"
59-
contents = RESULTS_DF.to_csv()
60+
contents = RESULTS_DF.to_csv(index=False)
6061

6162
case "json":
6263
mime_type = "application/json"
@@ -74,17 +75,17 @@ async def download_query_results(serialization: str):
7475
js.document.body.removeChild(anchor)
7576

7677

77-
async def run_query():
78+
async def run_query(*args):
7879
global RESULTS_DF
7980
query_element = js.document.getElementById("bf-sparql-queries")
8081
sparql_query = query_element.value
8182
output_element = js.document.getElementById("bf-sparql-results")
82-
output_element.innerHTML = ""
83+
output_element.content = ""
8384
try:
8485
query = SINOPIA_GRAPH.query(sparql_query)
8586
RESULTS_DF = pd.DataFrame(query.bindings)
8687
output_element.innerHTML = query_results_template.render(
8788
count=f"{len(query.bindings):,}", vars=query.vars, results=query.bindings
8889
)
8990
except Exception as e:
90-
output_element.innerHTML = f"""<h2>Query Error</h2><p>{e}</p>"""
91+
output_element.content = f"""<h2>Query Error</h2><p>{e}</p>"""

src/sinopia_api.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ async def _on_load_groups(event):
5353

5454

5555
def _environment_checkbox(env):
56+
5657
div = js.document.createElement("div")
5758
div.classList.add("form-check")
5859
ident = env[1]
@@ -83,7 +84,11 @@ def _group_select(options: list = []):
8384
return wrapper_div
8485

8586

86-
async def show_groups(env):
87+
async def show_groups(*args):
88+
current_radio_btn = args[0].target
89+
env = current_radio_btn.value
90+
91+
js.console.log(f"Env is {current_radio_btn.value}")
8792
api_url = environments.get(env)
8893
if api_url is None:
8994
return
@@ -93,7 +98,7 @@ async def show_groups(env):
9398
groups_url = f"{api_url}groups/"
9499
get_result = await pyfetch(groups_url)
95100
result = await get_result.json()
96-
#data = json.loads(result.getvalue())["data"]
101+
# data = json.loads(result.getvalue())["data"]
97102
data = result["data"]
98103
groups = [("All", "all")]
99104
for row in data:
40.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)