@logilab/sparqlexplorer 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +73 -0
- package/build/src/lib/App.d.ts +6 -0
- package/build/src/lib/components/ClassList.d.ts +9 -0
- package/build/src/lib/components/EndpointForm.d.ts +1 -0
- package/build/src/lib/components/GraphSelector.d.ts +1 -0
- package/build/src/lib/components/HomePage.d.ts +1 -0
- package/build/src/lib/components/SearchPage.d.ts +1 -0
- package/build/src/lib/components/UriPage.d.ts +1 -0
- package/build/src/lib/components/UtilsComponents.d.ts +11 -0
- package/build/src/lib/components/ViewSelector.d.ts +2 -0
- package/build/src/lib/components/Yasgui.d.ts +6 -0
- package/build/src/lib/components/YasrTableResults.d.ts +55 -0
- package/build/src/lib/components/layout/DrawerContent.d.ts +4 -0
- package/build/src/lib/components/layout/Footer.d.ts +1 -0
- package/build/src/lib/components/layout/Layout.d.ts +2 -0
- package/build/src/lib/components/layout/Navbar.d.ts +4 -0
- package/build/src/lib/components/uri/URIDefaultView.d.ts +6 -0
- package/build/src/lib/components/uri/URIWithSelectedView.d.ts +7 -0
- package/build/src/lib/context/AuthContext.d.ts +11 -0
- package/build/src/lib/context/ConfigContext.d.ts +15 -0
- package/build/src/lib/context/ViewsContext.d.ts +14 -0
- package/build/src/lib/hooks/useClasses.d.ts +6 -0
- package/build/src/lib/hooks/useGraphs.d.ts +8 -0
- package/build/src/lib/hooks/useNavigateWithParams.d.ts +5 -0
- package/build/src/lib/hooks/useParams.d.ts +1 -0
- package/build/src/lib/hooks/useURIData.d.ts +21 -0
- package/build/src/lib/hooks/useURILink.d.ts +1 -0
- package/build/src/lib/index.d.ts +8 -0
- package/build/src/lib/public-path.d.ts +1 -0
- package/build/src/lib/routes/Home.d.ts +1 -0
- package/build/src/lib/routes/Search.d.ts +1 -0
- package/build/src/lib/routes/Uri.d.ts +1 -0
- package/build/src/lib/routes/Yasgui.d.ts +1 -0
- package/build/src/lib/setupTests.d.ts +1 -0
- package/build/src/lib/utils/getIconFromURI.d.ts +3 -0
- package/build/src/lib/utils/utils.d.ts +24 -0
- package/build/src/lib/yasgui-utils/Storage.d.ts +16 -0
- package/build/src/lib/yasgui-utils/index.d.ts +16 -0
- package/build/static/js/lib.js +285 -0
- package/build/static/js/lib.js.LICENSE.txt +71 -0
- package/build/static/js/lib.js.map +1 -0
- package/package.json +73 -0
- package/src/app/index.css +23 -0
- package/src/app/index.tsx +28 -0
- package/src/app/templates/constants.js +1 -0
- package/src/app/templates/index.hbs +18 -0
- package/src/lib/App.css +83 -0
- package/src/lib/App.tsx +31 -0
- package/src/lib/components/ClassList.tsx +173 -0
- package/src/lib/components/EndpointForm.tsx +126 -0
- package/src/lib/components/GraphSelector.tsx +114 -0
- package/src/lib/components/HomePage.tsx +51 -0
- package/src/lib/components/SearchPage.tsx +211 -0
- package/src/lib/components/UriPage.tsx +158 -0
- package/src/lib/components/UtilsComponents.tsx +54 -0
- package/src/lib/components/ViewSelector.css +22 -0
- package/src/lib/components/ViewSelector.tsx +78 -0
- package/src/lib/components/Yasgui.tsx +127 -0
- package/src/lib/components/YasrTableResults.ts +529 -0
- package/src/lib/components/layout/DrawerContent.tsx +55 -0
- package/src/lib/components/layout/Footer.tsx +32 -0
- package/src/lib/components/layout/Layout.tsx +103 -0
- package/src/lib/components/layout/Navbar.tsx +231 -0
- package/src/lib/components/uri/URIDefaultView.tsx +392 -0
- package/src/lib/components/uri/URIWithSelectedView.tsx +31 -0
- package/src/lib/context/AuthContext.tsx +32 -0
- package/src/lib/context/ConfigContext.tsx +50 -0
- package/src/lib/context/ViewsContext.tsx +53 -0
- package/src/lib/hooks/useClasses.ts +48 -0
- package/src/lib/hooks/useGraphs.ts +67 -0
- package/src/lib/hooks/useNavigateWithParams.tsx +97 -0
- package/src/lib/hooks/useParams.tsx +8 -0
- package/src/lib/hooks/useURIData.ts +180 -0
- package/src/lib/hooks/useURILink.ts +7 -0
- package/src/lib/index.tsx +9 -0
- package/src/lib/public-path.ts +3 -0
- package/src/lib/routes/Home.tsx +13 -0
- package/src/lib/routes/Search.tsx +13 -0
- package/src/lib/routes/Uri.tsx +10 -0
- package/src/lib/routes/Yasgui.tsx +13 -0
- package/src/lib/setupTests.ts +5 -0
- package/src/lib/types.d.ts +6 -0
- package/src/lib/utils/getIconFromURI.ts +32 -0
- package/src/lib/utils/prefixInverted.json +2445 -0
- package/src/lib/utils/utils.ts +131 -0
- package/src/lib/yasgui-utils/Storage.ts +117 -0
- package/src/lib/yasgui-utils/index.ts +66 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { createSearchParams, useLocation, useNavigate } from "react-router-dom";
|
|
3
|
+
import {
|
|
4
|
+
useCanEditEndpoint,
|
|
5
|
+
useEndpoint,
|
|
6
|
+
useSelectedGraphs,
|
|
7
|
+
useView,
|
|
8
|
+
} from "../context/ConfigContext";
|
|
9
|
+
|
|
10
|
+
export function useNavigateWithParams() {
|
|
11
|
+
const navigate = useNavigate();
|
|
12
|
+
const getSearchParamsString = useSearchParamsString();
|
|
13
|
+
|
|
14
|
+
return useCallback(
|
|
15
|
+
(
|
|
16
|
+
pathname: string,
|
|
17
|
+
newParams?: Record<string, string | null>,
|
|
18
|
+
replace?: boolean,
|
|
19
|
+
) => {
|
|
20
|
+
console.log(getSearchParamsString());
|
|
21
|
+
navigate(
|
|
22
|
+
{
|
|
23
|
+
pathname: pathname,
|
|
24
|
+
search: getSearchParamsString(newParams),
|
|
25
|
+
},
|
|
26
|
+
{ replace },
|
|
27
|
+
);
|
|
28
|
+
},
|
|
29
|
+
[navigate, getSearchParamsString],
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function useSearchParamsString() {
|
|
34
|
+
const endpoint = useEndpoint();
|
|
35
|
+
const viewUrl = useView();
|
|
36
|
+
const selectedGraphs = useSelectedGraphs();
|
|
37
|
+
const canEditEndpoint = useCanEditEndpoint();
|
|
38
|
+
|
|
39
|
+
return useCallback(
|
|
40
|
+
(newParams?: Record<string, string | null>) => {
|
|
41
|
+
const params: Record<string, string | null> = newParams ?? {};
|
|
42
|
+
if (canEditEndpoint && endpoint && !("endpoint" in params)) {
|
|
43
|
+
params.endpoint = endpoint;
|
|
44
|
+
}
|
|
45
|
+
if (viewUrl && !("view" in params)) {
|
|
46
|
+
params.view = viewUrl;
|
|
47
|
+
}
|
|
48
|
+
if (!("graphs" in params)) {
|
|
49
|
+
params.graphs = JSON.stringify(selectedGraphs);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const cleanedParams: Record<string, string> = {};
|
|
53
|
+
Object.entries(params).forEach(([k, v]) => {
|
|
54
|
+
if (v) {
|
|
55
|
+
cleanedParams[k] = v;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return createSearchParams(cleanedParams).toString();
|
|
59
|
+
},
|
|
60
|
+
[endpoint, viewUrl, canEditEndpoint, selectedGraphs],
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function useChangeView() {
|
|
65
|
+
const navigate = useNavigateWithParams();
|
|
66
|
+
const location = useLocation();
|
|
67
|
+
return (view: string | null) => navigate(location.pathname, { view }, true);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function useAddGraph() {
|
|
71
|
+
const navigate = useNavigateWithParams();
|
|
72
|
+
const location = useLocation();
|
|
73
|
+
const selectedGraphs = useSelectedGraphs();
|
|
74
|
+
return (graph: string) => {
|
|
75
|
+
const newGraphs = [...selectedGraphs];
|
|
76
|
+
newGraphs.push(graph);
|
|
77
|
+
navigate(
|
|
78
|
+
location.pathname,
|
|
79
|
+
{ graphs: JSON.stringify(newGraphs) },
|
|
80
|
+
true,
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function useRemoveGraph() {
|
|
86
|
+
const navigate = useNavigateWithParams();
|
|
87
|
+
const location = useLocation();
|
|
88
|
+
const selectedGraphs = useSelectedGraphs();
|
|
89
|
+
return (graph: string) => {
|
|
90
|
+
const newGraphs = selectedGraphs.filter((g) => g !== graph);
|
|
91
|
+
navigate(
|
|
92
|
+
location.pathname,
|
|
93
|
+
{ graphs: JSON.stringify(newGraphs) },
|
|
94
|
+
true,
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import {
|
|
2
|
+
querySparql,
|
|
3
|
+
type SparqlAuth,
|
|
4
|
+
sparqlResultToArray,
|
|
5
|
+
} from "@logilab/sparqlutils";
|
|
6
|
+
import { useEffect, useState } from "react";
|
|
7
|
+
import { useAuth } from "../context/AuthContext";
|
|
8
|
+
import { getLabelSparqlClause, type Label, type RDFNode } from "../utils/utils";
|
|
9
|
+
|
|
10
|
+
export interface ITriples {
|
|
11
|
+
// use objects from rdfjs instead ?
|
|
12
|
+
subject: RDFNode;
|
|
13
|
+
predicate: RDFNode;
|
|
14
|
+
object: RDFNode;
|
|
15
|
+
graph: RDFNode;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function fetchUriData(
|
|
19
|
+
endpoint: string,
|
|
20
|
+
uri: string,
|
|
21
|
+
graphs: string[],
|
|
22
|
+
search: string,
|
|
23
|
+
page: number,
|
|
24
|
+
perPage: number,
|
|
25
|
+
auth?: SparqlAuth,
|
|
26
|
+
): Promise<{ triples: ITriples[]; total: number; labels: Label[] }> {
|
|
27
|
+
const triples: ITriples[] = [];
|
|
28
|
+
const escapedSearch = search.replace('"', '\\"');
|
|
29
|
+
const searchFilter =
|
|
30
|
+
search !== ""
|
|
31
|
+
? ` FILTER (
|
|
32
|
+
regex(str(?s), "${escapedSearch}", "i") OR
|
|
33
|
+
regex(str(?p), "${escapedSearch}", "i") OR
|
|
34
|
+
regex(str(?o), "${escapedSearch}", "i") OR
|
|
35
|
+
regex(str(?g), "${escapedSearch}", "i")
|
|
36
|
+
)`
|
|
37
|
+
: "";
|
|
38
|
+
|
|
39
|
+
const defaultGraphSelect = `
|
|
40
|
+
{
|
|
41
|
+
{
|
|
42
|
+
<${uri}> ?p ?o.
|
|
43
|
+
BIND (<${uri}> AS ?s)
|
|
44
|
+
} UNION {
|
|
45
|
+
?s ?p <${uri}>
|
|
46
|
+
BIND (<${uri}> AS ?o)
|
|
47
|
+
}
|
|
48
|
+
}`;
|
|
49
|
+
|
|
50
|
+
function getSpecificGraphSelect(g: string) {
|
|
51
|
+
return `
|
|
52
|
+
{
|
|
53
|
+
{
|
|
54
|
+
GRAPH <${g}> {
|
|
55
|
+
<${uri}> ?p ?o.
|
|
56
|
+
}
|
|
57
|
+
BIND (<${uri}> AS ?s)
|
|
58
|
+
} UNION {
|
|
59
|
+
GRAPH <${g}> {
|
|
60
|
+
?s ?p <${uri}>
|
|
61
|
+
}
|
|
62
|
+
BIND (<${uri}> AS ?o)
|
|
63
|
+
}
|
|
64
|
+
BIND (<${g}> AS ?g)
|
|
65
|
+
}`;
|
|
66
|
+
}
|
|
67
|
+
const graphList = graphs
|
|
68
|
+
.filter((g) => g !== "default")
|
|
69
|
+
.map((g) => getSpecificGraphSelect(g))
|
|
70
|
+
.join(" UNION ");
|
|
71
|
+
|
|
72
|
+
let graphSelect = "";
|
|
73
|
+
if (graphs.includes("default")) {
|
|
74
|
+
graphSelect += defaultGraphSelect;
|
|
75
|
+
if (graphs.length > 1) {
|
|
76
|
+
graphSelect += ` UNION ${graphList}`;
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
graphSelect = graphList;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const fetchTriplesWhereQuery = `${graphSelect}${searchFilter}`;
|
|
83
|
+
const [triplesResult, countResult, labelResult] = await Promise.all([
|
|
84
|
+
querySparql(
|
|
85
|
+
endpoint,
|
|
86
|
+
`SELECT DISTINCT ?g ?s ?p ?o WHERE {${fetchTriplesWhereQuery} } ORDER BY ?p LIMIT ${perPage} OFFSET ${page * perPage}`,
|
|
87
|
+
auth,
|
|
88
|
+
),
|
|
89
|
+
querySparql(
|
|
90
|
+
endpoint,
|
|
91
|
+
`SELECT (COUNT(*) as ?count) WHERE { ${fetchTriplesWhereQuery} }`,
|
|
92
|
+
auth,
|
|
93
|
+
),
|
|
94
|
+
querySparql(
|
|
95
|
+
endpoint,
|
|
96
|
+
`SELECT DISTINCT ?label WHERE {
|
|
97
|
+
${getLabelSparqlClause(uri)}
|
|
98
|
+
}`,
|
|
99
|
+
auth,
|
|
100
|
+
),
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
sparqlResultToArray(triplesResult).forEach((elem) => {
|
|
104
|
+
triples.push({
|
|
105
|
+
subject: elem.s,
|
|
106
|
+
predicate: elem.p,
|
|
107
|
+
object: elem.o,
|
|
108
|
+
graph: elem.g ?? { type: "uri", value: "default" },
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const total = parseInt(countResult.results.bindings[0].count.value, 10);
|
|
113
|
+
|
|
114
|
+
const labels: Label[] = [];
|
|
115
|
+
|
|
116
|
+
sparqlResultToArray(labelResult).forEach((elem) => {
|
|
117
|
+
labels.push({
|
|
118
|
+
value: elem.label?.value,
|
|
119
|
+
lang: null,
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
triples,
|
|
125
|
+
total,
|
|
126
|
+
labels,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function useURIData({
|
|
131
|
+
endpoint,
|
|
132
|
+
uri,
|
|
133
|
+
graphs,
|
|
134
|
+
search,
|
|
135
|
+
page,
|
|
136
|
+
perPage,
|
|
137
|
+
}: {
|
|
138
|
+
endpoint: string;
|
|
139
|
+
uri: string;
|
|
140
|
+
graphs: string[];
|
|
141
|
+
search: string;
|
|
142
|
+
page: number;
|
|
143
|
+
perPage: number;
|
|
144
|
+
}) {
|
|
145
|
+
const [triples, setTriples] = useState<ITriples[]>([]);
|
|
146
|
+
const [error, setError] = useState<string | null>(null);
|
|
147
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
148
|
+
const [total, setTotal] = useState(0);
|
|
149
|
+
const [labels, setLabels] = useState<Label[]>([]);
|
|
150
|
+
const { auth } = useAuth();
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
async function fetchResults() {
|
|
153
|
+
try {
|
|
154
|
+
setIsLoaded(false);
|
|
155
|
+
const {
|
|
156
|
+
triples: tempTriples,
|
|
157
|
+
total: tempTotals,
|
|
158
|
+
labels: tempLabels,
|
|
159
|
+
} = await fetchUriData(
|
|
160
|
+
endpoint,
|
|
161
|
+
uri,
|
|
162
|
+
graphs,
|
|
163
|
+
search,
|
|
164
|
+
page,
|
|
165
|
+
perPage,
|
|
166
|
+
auth,
|
|
167
|
+
);
|
|
168
|
+
setTriples(tempTriples);
|
|
169
|
+
setTotal(tempTotals);
|
|
170
|
+
setLabels(tempLabels);
|
|
171
|
+
setIsLoaded(true);
|
|
172
|
+
} catch (e) {
|
|
173
|
+
setError(e.message);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
fetchResults();
|
|
177
|
+
}, [endpoint, uri, graphs, search, page, perPage, auth]);
|
|
178
|
+
|
|
179
|
+
return { triples, total, labels, error, isLoaded };
|
|
180
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { useSearchParamsString } from "./useNavigateWithParams";
|
|
2
|
+
|
|
3
|
+
export function useURILink(uri: string) {
|
|
4
|
+
const getSearchParamsString = useSearchParamsString();
|
|
5
|
+
const encodedUri = encodeURIComponent(uri);
|
|
6
|
+
return `/browse/${encodedUri}?${getSearchParamsString()}`;
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./App";
|
|
2
|
+
export * from "./utils/utils"
|
|
3
|
+
export * from "./context/ViewsContext";
|
|
4
|
+
export * from "./context/AuthContext";
|
|
5
|
+
export * from "./context/ConfigContext";
|
|
6
|
+
export * from "./utils/getIconFromURI";
|
|
7
|
+
|
|
8
|
+
import App from "./App";
|
|
9
|
+
export default App
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Container from "@mui/material/Container";
|
|
2
|
+
import { HomePage } from "../components/HomePage";
|
|
3
|
+
import { Layout } from "../components/layout/Layout";
|
|
4
|
+
|
|
5
|
+
export function Home() {
|
|
6
|
+
return (
|
|
7
|
+
<Layout>
|
|
8
|
+
<Container>
|
|
9
|
+
<HomePage />
|
|
10
|
+
</Container>
|
|
11
|
+
</Layout>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Container from "@mui/material/Container";
|
|
2
|
+
import { Layout } from "../components/layout/Layout";
|
|
3
|
+
import { SearchPage } from "../components/SearchPage";
|
|
4
|
+
|
|
5
|
+
export function Search() {
|
|
6
|
+
return (
|
|
7
|
+
<Layout>
|
|
8
|
+
<Container>
|
|
9
|
+
<SearchPage />
|
|
10
|
+
</Container>
|
|
11
|
+
</Layout>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Container from "@mui/material/Container";
|
|
2
|
+
import { Layout } from "../components/layout/Layout";
|
|
3
|
+
import { YasguiPage } from "../components/Yasgui";
|
|
4
|
+
|
|
5
|
+
export function Yasgui() {
|
|
6
|
+
return (
|
|
7
|
+
<Layout>
|
|
8
|
+
<Container>
|
|
9
|
+
<YasguiPage />
|
|
10
|
+
</Container>
|
|
11
|
+
</Layout>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import ChevronRight from "@mui/icons-material/ChevronRight";
|
|
2
|
+
import Face from "@mui/icons-material/Face";
|
|
3
|
+
import Inventory2 from "@mui/icons-material/Inventory2";
|
|
4
|
+
import LibraryBooks from "@mui/icons-material/LibraryBooks";
|
|
5
|
+
import ListAlt from "@mui/icons-material/ListAlt";
|
|
6
|
+
import LocationOn from "@mui/icons-material/LocationOn";
|
|
7
|
+
import TextFields from "@mui/icons-material/TextFields";
|
|
8
|
+
import Widgets from "@mui/icons-material/Widgets";
|
|
9
|
+
|
|
10
|
+
export function getIconFromURI(uri: string) {
|
|
11
|
+
switch (uri) {
|
|
12
|
+
case "http://purl.org/dc/dcmitype/PhysicalObject":
|
|
13
|
+
return Inventory2;
|
|
14
|
+
case "http://purl.org/dc/terms/Location":
|
|
15
|
+
return LocationOn;
|
|
16
|
+
case "http://xmlns.com/foaf/0.1/Agent":
|
|
17
|
+
return Face;
|
|
18
|
+
case "http://www.w3.org/2000/01/rdf-schema#Class":
|
|
19
|
+
case "http://www.w3.org/2002/07/owl#Class":
|
|
20
|
+
return Widgets;
|
|
21
|
+
case "http://www.w3.org/2002/07/owl#Ontology":
|
|
22
|
+
return LibraryBooks;
|
|
23
|
+
case "http://www.w3.org/2002/07/owl#AnnotationProperty":
|
|
24
|
+
case "http://www.w3.org/2002/07/owl#OntologyProperty":
|
|
25
|
+
case "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property":
|
|
26
|
+
return TextFields;
|
|
27
|
+
case "http://www.w3.org/2004/02/skos/core#Concept":
|
|
28
|
+
return ListAlt;
|
|
29
|
+
default:
|
|
30
|
+
return ChevronRight;
|
|
31
|
+
}
|
|
32
|
+
}
|