@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.
Files changed (88) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +73 -0
  3. package/build/src/lib/App.d.ts +6 -0
  4. package/build/src/lib/components/ClassList.d.ts +9 -0
  5. package/build/src/lib/components/EndpointForm.d.ts +1 -0
  6. package/build/src/lib/components/GraphSelector.d.ts +1 -0
  7. package/build/src/lib/components/HomePage.d.ts +1 -0
  8. package/build/src/lib/components/SearchPage.d.ts +1 -0
  9. package/build/src/lib/components/UriPage.d.ts +1 -0
  10. package/build/src/lib/components/UtilsComponents.d.ts +11 -0
  11. package/build/src/lib/components/ViewSelector.d.ts +2 -0
  12. package/build/src/lib/components/Yasgui.d.ts +6 -0
  13. package/build/src/lib/components/YasrTableResults.d.ts +55 -0
  14. package/build/src/lib/components/layout/DrawerContent.d.ts +4 -0
  15. package/build/src/lib/components/layout/Footer.d.ts +1 -0
  16. package/build/src/lib/components/layout/Layout.d.ts +2 -0
  17. package/build/src/lib/components/layout/Navbar.d.ts +4 -0
  18. package/build/src/lib/components/uri/URIDefaultView.d.ts +6 -0
  19. package/build/src/lib/components/uri/URIWithSelectedView.d.ts +7 -0
  20. package/build/src/lib/context/AuthContext.d.ts +11 -0
  21. package/build/src/lib/context/ConfigContext.d.ts +15 -0
  22. package/build/src/lib/context/ViewsContext.d.ts +14 -0
  23. package/build/src/lib/hooks/useClasses.d.ts +6 -0
  24. package/build/src/lib/hooks/useGraphs.d.ts +8 -0
  25. package/build/src/lib/hooks/useNavigateWithParams.d.ts +5 -0
  26. package/build/src/lib/hooks/useParams.d.ts +1 -0
  27. package/build/src/lib/hooks/useURIData.d.ts +21 -0
  28. package/build/src/lib/hooks/useURILink.d.ts +1 -0
  29. package/build/src/lib/index.d.ts +8 -0
  30. package/build/src/lib/public-path.d.ts +1 -0
  31. package/build/src/lib/routes/Home.d.ts +1 -0
  32. package/build/src/lib/routes/Search.d.ts +1 -0
  33. package/build/src/lib/routes/Uri.d.ts +1 -0
  34. package/build/src/lib/routes/Yasgui.d.ts +1 -0
  35. package/build/src/lib/setupTests.d.ts +1 -0
  36. package/build/src/lib/utils/getIconFromURI.d.ts +3 -0
  37. package/build/src/lib/utils/utils.d.ts +24 -0
  38. package/build/src/lib/yasgui-utils/Storage.d.ts +16 -0
  39. package/build/src/lib/yasgui-utils/index.d.ts +16 -0
  40. package/build/static/js/lib.js +285 -0
  41. package/build/static/js/lib.js.LICENSE.txt +71 -0
  42. package/build/static/js/lib.js.map +1 -0
  43. package/package.json +73 -0
  44. package/src/app/index.css +23 -0
  45. package/src/app/index.tsx +28 -0
  46. package/src/app/templates/constants.js +1 -0
  47. package/src/app/templates/index.hbs +18 -0
  48. package/src/lib/App.css +83 -0
  49. package/src/lib/App.tsx +31 -0
  50. package/src/lib/components/ClassList.tsx +173 -0
  51. package/src/lib/components/EndpointForm.tsx +126 -0
  52. package/src/lib/components/GraphSelector.tsx +114 -0
  53. package/src/lib/components/HomePage.tsx +51 -0
  54. package/src/lib/components/SearchPage.tsx +211 -0
  55. package/src/lib/components/UriPage.tsx +158 -0
  56. package/src/lib/components/UtilsComponents.tsx +54 -0
  57. package/src/lib/components/ViewSelector.css +22 -0
  58. package/src/lib/components/ViewSelector.tsx +78 -0
  59. package/src/lib/components/Yasgui.tsx +127 -0
  60. package/src/lib/components/YasrTableResults.ts +529 -0
  61. package/src/lib/components/layout/DrawerContent.tsx +55 -0
  62. package/src/lib/components/layout/Footer.tsx +32 -0
  63. package/src/lib/components/layout/Layout.tsx +103 -0
  64. package/src/lib/components/layout/Navbar.tsx +231 -0
  65. package/src/lib/components/uri/URIDefaultView.tsx +392 -0
  66. package/src/lib/components/uri/URIWithSelectedView.tsx +31 -0
  67. package/src/lib/context/AuthContext.tsx +32 -0
  68. package/src/lib/context/ConfigContext.tsx +50 -0
  69. package/src/lib/context/ViewsContext.tsx +53 -0
  70. package/src/lib/hooks/useClasses.ts +48 -0
  71. package/src/lib/hooks/useGraphs.ts +67 -0
  72. package/src/lib/hooks/useNavigateWithParams.tsx +97 -0
  73. package/src/lib/hooks/useParams.tsx +8 -0
  74. package/src/lib/hooks/useURIData.ts +180 -0
  75. package/src/lib/hooks/useURILink.ts +7 -0
  76. package/src/lib/index.tsx +9 -0
  77. package/src/lib/public-path.ts +3 -0
  78. package/src/lib/routes/Home.tsx +13 -0
  79. package/src/lib/routes/Search.tsx +13 -0
  80. package/src/lib/routes/Uri.tsx +10 -0
  81. package/src/lib/routes/Yasgui.tsx +13 -0
  82. package/src/lib/setupTests.ts +5 -0
  83. package/src/lib/types.d.ts +6 -0
  84. package/src/lib/utils/getIconFromURI.ts +32 -0
  85. package/src/lib/utils/prefixInverted.json +2445 -0
  86. package/src/lib/utils/utils.ts +131 -0
  87. package/src/lib/yasgui-utils/Storage.ts +117 -0
  88. 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,8 @@
1
+ import { useSearchParams } from "react-router-dom";
2
+
3
+ export function useParam(param: string) {
4
+ const [searchParams] = useSearchParams();
5
+
6
+ const paramValue = searchParams.get(param);
7
+ return paramValue;
8
+ }
@@ -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,3 @@
1
+ /* eslint-disable no-var */
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */
3
+ declare var SPARQL_ENDPOINT: string;
@@ -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,10 @@
1
+ import { Layout } from "../components/layout/Layout";
2
+ import { UriPage } from "../components/UriPage";
3
+
4
+ export function Uri() {
5
+ return (
6
+ <Layout>
7
+ <UriPage />
8
+ </Layout>
9
+ );
10
+ }
@@ -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,5 @@
1
+ // jest-dom adds custom jest matchers for asserting on DOM nodes.
2
+ // allows you to do things like:
3
+ // expect(element).toHaveTextContent(/react/i)
4
+ // learn more: https://github.com/testing-library/jest-dom
5
+ import "@testing-library/jest-dom/extend-expect";
@@ -0,0 +1,6 @@
1
+ declare module "*.svg";
2
+ declare module "*.png";
3
+ declare module "*.gif";
4
+ declare module "*.jpg";
5
+
6
+ declare const BASENAME: string | undefined;
@@ -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
+ }