@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,131 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SPARQL_VIEWS,
|
|
3
|
+
type SparqlViewConfig,
|
|
4
|
+
} from "@logilab/sparqlexplorer-views";
|
|
5
|
+
import type { SparqlAuth } from "@logilab/sparqlutils";
|
|
6
|
+
import prefix from "./prefixInverted.json";
|
|
7
|
+
|
|
8
|
+
export interface RDFNode {
|
|
9
|
+
type: "uri" | "bnode" | "literal";
|
|
10
|
+
value: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function stringIncludes(a: string, b: string) {
|
|
14
|
+
return a.toLowerCase().includes(b.toLowerCase());
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function computeRedirect(uri: string, params: string) {
|
|
18
|
+
return `/#/browse/${encodeURIComponent(uri)}?${params}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function prefixedNameFromUri(uri: string) {
|
|
22
|
+
const prefixCandidates = Object.entries(prefix).filter(([baseUri]) =>
|
|
23
|
+
uri.startsWith(baseUri),
|
|
24
|
+
);
|
|
25
|
+
if (prefixCandidates.length > 0) {
|
|
26
|
+
// take the baseUri with the highest length
|
|
27
|
+
const [bestBaseUri, bestPrefix] = prefixCandidates.sort(
|
|
28
|
+
([baseUri1], [baseUri2]) => baseUri2.length - baseUri1.length,
|
|
29
|
+
)[0];
|
|
30
|
+
return uri.replace(bestBaseUri, `${bestPrefix}:`);
|
|
31
|
+
}
|
|
32
|
+
return uri;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const SAVED_ENDPOINT_KEY = "sparqlexplorer.endpoints";
|
|
36
|
+
|
|
37
|
+
function stringToStringArray(rawValue: string | null): Array<string> {
|
|
38
|
+
if (rawValue !== null) {
|
|
39
|
+
try {
|
|
40
|
+
const arrayValue = JSON.parse(rawValue);
|
|
41
|
+
if (
|
|
42
|
+
Array.isArray(arrayValue) &&
|
|
43
|
+
arrayValue.every((v) => typeof v === "string")
|
|
44
|
+
) {
|
|
45
|
+
return arrayValue;
|
|
46
|
+
}
|
|
47
|
+
return [];
|
|
48
|
+
} catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getSavedEndpoints(): Array<string> {
|
|
56
|
+
const rawValue = localStorage.getItem(SAVED_ENDPOINT_KEY);
|
|
57
|
+
return stringToStringArray(rawValue);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function addToSavedEndpoints(value: string) {
|
|
61
|
+
const current = new Set(getSavedEndpoints());
|
|
62
|
+
current.add(value);
|
|
63
|
+
const stringValue = JSON.stringify(Array.from(current));
|
|
64
|
+
localStorage.setItem(SAVED_ENDPOINT_KEY, stringValue);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function getApplicableViews(
|
|
68
|
+
uri: string,
|
|
69
|
+
endpoint: string,
|
|
70
|
+
auth?: SparqlAuth,
|
|
71
|
+
): Promise<Array<SparqlViewConfig>> {
|
|
72
|
+
return Promise.all(
|
|
73
|
+
SPARQL_VIEWS.map((view) => {
|
|
74
|
+
console.log(view.name);
|
|
75
|
+
return view.isApplicable(uri, endpoint, auth);
|
|
76
|
+
}),
|
|
77
|
+
).then((viewsApplicablities) => {
|
|
78
|
+
return SPARQL_VIEWS.filter((_view, idx) => viewsApplicablities[idx]);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const DEFAUT_VIEW_NAME = "Default view";
|
|
83
|
+
|
|
84
|
+
export function isDefaultView(viewName: string | null) {
|
|
85
|
+
return viewName === DEFAUT_VIEW_NAME;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function getLabelSparqlClause(
|
|
89
|
+
uri?: string,
|
|
90
|
+
onlyRdfsLabel: boolean = false,
|
|
91
|
+
) {
|
|
92
|
+
const predicates = onlyRdfsLabel
|
|
93
|
+
? ["<http://www.w3.org/2000/01/rdf-schema#label>"]
|
|
94
|
+
: [
|
|
95
|
+
"<http://www.w3.org/2000/01/rdf-schema#label>",
|
|
96
|
+
"<http://xmlns.com/foaf/0.1/name>",
|
|
97
|
+
"<http://purl.org/dc/terms/identifier>",
|
|
98
|
+
"<http://www.w3.org/2004/02/skos/core#prefLabel>",
|
|
99
|
+
"<http://www.w3.org/2008/05/skos-xl#prefLabel>/<http://www.w3.org/2008/05/skos-xl#literalForm>",
|
|
100
|
+
"<http://purl.org/dc/elements/1.1/title>",
|
|
101
|
+
"<http://purl.org/dc/terms/title>",
|
|
102
|
+
];
|
|
103
|
+
const predicateString = predicates.join("|");
|
|
104
|
+
const uriSelector = uri ? `<${uri}>` : "?uri";
|
|
105
|
+
return `OPTIONAL{
|
|
106
|
+
{
|
|
107
|
+
${uriSelector} ${predicateString} ?label
|
|
108
|
+
}
|
|
109
|
+
}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface Label {
|
|
113
|
+
value: string;
|
|
114
|
+
lang: string | null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface UriAndLabels {
|
|
118
|
+
uri: string;
|
|
119
|
+
labels: Label[];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function getBestLabel(instance: UriAndLabels) {
|
|
123
|
+
const filteredLabels = instance.labels
|
|
124
|
+
.filter((label) => label.lang?.includes("fr"))
|
|
125
|
+
.map((label) => label.value);
|
|
126
|
+
const allLabels = instance.labels.map((label) => label.value);
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
filteredLabels[0] ?? allLabels[0] ?? prefixedNameFromUri(instance.uri)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// FIXME this seems shady
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
3
|
+
const store = require("store");
|
|
4
|
+
|
|
5
|
+
export interface ItemWrapper<V = Record<string, unknown>> {
|
|
6
|
+
exp: number;
|
|
7
|
+
val: V;
|
|
8
|
+
namespace: string;
|
|
9
|
+
time: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface QuotaExceededError extends Error {
|
|
13
|
+
quotaExceeded?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export default class Storage {
|
|
16
|
+
private namespace: string;
|
|
17
|
+
constructor(namespace: string) {
|
|
18
|
+
this.namespace = namespace;
|
|
19
|
+
}
|
|
20
|
+
public set<V = Record<string, unknown>>(
|
|
21
|
+
key: string | undefined,
|
|
22
|
+
// biome-ignore lint/suspicious/noExplicitAny: any is ok
|
|
23
|
+
val: any,
|
|
24
|
+
expInSeconds: number,
|
|
25
|
+
// biome-ignore lint/suspicious/noExplicitAny: any is ok
|
|
26
|
+
onQuotaExceeded: (e: any) => void,
|
|
27
|
+
) {
|
|
28
|
+
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
29
|
+
this.removeExpiredKeys();
|
|
30
|
+
if (key && val !== undefined) {
|
|
31
|
+
//try to store string for dom objects (e.g. XML result). Otherwise, we might get a circular reference error when stringifying this
|
|
32
|
+
if (val.documentElement)
|
|
33
|
+
val = new XMLSerializer().serializeToString(
|
|
34
|
+
val.documentElement,
|
|
35
|
+
);
|
|
36
|
+
try {
|
|
37
|
+
store.set(key, {
|
|
38
|
+
namespace: this.namespace,
|
|
39
|
+
val: val,
|
|
40
|
+
exp: expInSeconds,
|
|
41
|
+
time: Date.now() / 1000,
|
|
42
|
+
} as ItemWrapper<V>);
|
|
43
|
+
} catch (e) {
|
|
44
|
+
if (e instanceof Error) {
|
|
45
|
+
const quotaExceededError = e as QuotaExceededError;
|
|
46
|
+
quotaExceededError.quotaExceeded = isQuotaExceeded(e);
|
|
47
|
+
if (quotaExceededError.quotaExceeded && onQuotaExceeded) {
|
|
48
|
+
onQuotaExceeded(e);
|
|
49
|
+
} else {
|
|
50
|
+
throw quotaExceededError;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
throw e;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
remove(key: string) {
|
|
58
|
+
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
59
|
+
if (key) store.remove(key);
|
|
60
|
+
}
|
|
61
|
+
removeExpiredKeys() {
|
|
62
|
+
if (!store.enabled) return;
|
|
63
|
+
store.each((value: ItemWrapper, key: string) => {
|
|
64
|
+
if (value?.exp && Date.now() / 1000 - value.time > value.exp) {
|
|
65
|
+
this.remove(key);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
removeAll() {
|
|
70
|
+
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
71
|
+
}
|
|
72
|
+
removeNamespace() {
|
|
73
|
+
// biome-ignore lint/suspicious/noExplicitAny: any is ok
|
|
74
|
+
store.each((value: ItemWrapper<any>, key: string) => {
|
|
75
|
+
if (value.namespace && value.namespace === this.namespace)
|
|
76
|
+
this.remove(key);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
get<V>(key?: string): V | undefined {
|
|
80
|
+
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
81
|
+
if (!key) return;
|
|
82
|
+
this.removeExpiredKeys();
|
|
83
|
+
if (key) {
|
|
84
|
+
const info: ItemWrapper<V> = store.get(key);
|
|
85
|
+
if (!info) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
return info.val;
|
|
89
|
+
} else {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// biome-ignore lint/suspicious/noExplicitAny: any is ok
|
|
96
|
+
function isQuotaExceeded(e: any) {
|
|
97
|
+
let quotaExceeded = false;
|
|
98
|
+
if (e) {
|
|
99
|
+
if (e.code) {
|
|
100
|
+
switch (e.code) {
|
|
101
|
+
case 22:
|
|
102
|
+
quotaExceeded = true;
|
|
103
|
+
break;
|
|
104
|
+
case 1014:
|
|
105
|
+
// Firefox
|
|
106
|
+
if (e.name === "NS_ERROR_DOM_QUOTA_REACHED") {
|
|
107
|
+
quotaExceeded = true;
|
|
108
|
+
}
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
} else if (e.number === -2147024882) {
|
|
112
|
+
// Internet Explorer 8
|
|
113
|
+
quotaExceeded = true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return quotaExceeded;
|
|
117
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export function drawSvgStringAsElement(svgString: string) {
|
|
2
|
+
if (svgString && svgString.trim().indexOf("<svg") === 0) {
|
|
3
|
+
//no style passed via config. guess own styles
|
|
4
|
+
const parser = new DOMParser();
|
|
5
|
+
const dom = parser.parseFromString(svgString, "text/xml");
|
|
6
|
+
const svg = dom.documentElement;
|
|
7
|
+
svg.setAttribute("aria-hidden", "true");
|
|
8
|
+
|
|
9
|
+
const svgContainer = document.createElement("div");
|
|
10
|
+
svgContainer.className = "svgImg";
|
|
11
|
+
svgContainer.appendChild(svg);
|
|
12
|
+
return svgContainer;
|
|
13
|
+
}
|
|
14
|
+
throw new Error("No svg string given. Cannot draw");
|
|
15
|
+
}
|
|
16
|
+
export interface FaIcon {
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
svgPathData: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Draws font fontawesome icon as svg. This is a lot more lightweight then the option that is offered by fontawesome
|
|
24
|
+
* @param faIcon
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
export function drawFontAwesomeIconAsSvg(faIcon: FaIcon) {
|
|
28
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${faIcon.width} ${faIcon.height}" aria-hidden="true"><path fill="currentColor" d="${faIcon.svgPathData}"></path></svg>`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function hasClass(el: Element | undefined, className: string) {
|
|
32
|
+
if (!el) return;
|
|
33
|
+
if (el.classList) return el.classList.contains(className);
|
|
34
|
+
else
|
|
35
|
+
return !!el.className.match(
|
|
36
|
+
new RegExp("(\\s|^)" + className + "(\\s|$)"),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function addClass(
|
|
41
|
+
el: Element | undefined | null,
|
|
42
|
+
...classNames: string[]
|
|
43
|
+
) {
|
|
44
|
+
if (!el) return;
|
|
45
|
+
for (const className of classNames) {
|
|
46
|
+
if (el.classList) el.classList.add(className);
|
|
47
|
+
else if (!hasClass(el, className)) el.className += " " + className;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function removeClass(el: Element | undefined | null, className: string) {
|
|
52
|
+
if (!el) return;
|
|
53
|
+
if (el.classList) el.classList.remove(className);
|
|
54
|
+
else if (hasClass(el, className)) {
|
|
55
|
+
const reg = new RegExp("(\\s|^)" + className + "(\\s|$)");
|
|
56
|
+
el.className = el.className.replace(reg, " ");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function getAsValue<E, A>(valueOrFn: E | ((arg: A) => E), arg: A): E {
|
|
61
|
+
if (typeof valueOrFn === "function") {
|
|
62
|
+
// biome-ignore lint/suspicious/noExplicitAny: any is ok
|
|
63
|
+
return (valueOrFn as any)(arg);
|
|
64
|
+
}
|
|
65
|
+
return valueOrFn;
|
|
66
|
+
}
|