e && e.length) ? 'inherit' : 'none'\n }} />\n )\n\n}\n\nGraph.propTypes = {\n nodes: PropTypes.arrayOf(PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n label: PropTypes.string.isRequired,\n })).isRequired,\n edges: PropTypes.arrayOf(PropTypes.shape({\n from: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n to: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n })).isRequired\n}\n\nGraph.defaultProps = {\n nodes: [],\n edges: []\n}\n\nexport default Graph\n","import axios from 'axios';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport SiteWrapper from '../../SiteWrapper';\nimport { Page, Card } from 'tabler-react';\nimport Graph from '../../components/Sparql/Graph'\nimport { Collapse, Button } from 'reactstrap';\n\nconst TiddlyMapExport = ({ match: { params: { id: tiddlyMapExportId } } }) => {\n const [mapExport, setMapExport] = useState()\n const [tiddlyMapView, setTiddlyMapView] = useState()\n const [visibleExportGraphIds, setVisibleExportGraphIds] = useState([])\n const [visibleErrorType, setVisibleErrorType] = useState()\n\n useEffect(() => {\n mapExport && mapExport.attributes.tiddly_map_view_id && axios.get(`/api/tiddly_map_views/${mapExport.attributes.tiddly_map_view_id}`)\n .then(({ data: { data } }) => setTiddlyMapView(data))\n }, [mapExport])\n\n useEffect(() => {\n axios.get(`/api/tiddly_map_exports/${tiddlyMapExportId}`)\n .then(({ data: { data } }) => setMapExport(data))\n }, [tiddlyMapExportId])\n\n const displayEdge = (edge) => {\n const fromLabel = mapExport.attributes.conversion_log.nodes[edge.from].label\n const toLabel = mapExport.attributes.conversion_log.nodes[edge.to].label\n return
\n {fromLabel} \n {edge.type} \n {toLabel} \n \n }\n\n const REGEXP_ID = useMemo(() => /\"*([\\d]{4}-[\\d]{2}-[\\d]{2}T[\\d]{2}:[\\d]{2}:[\\d]{2})*\"*.*\\/([^/>]+)>?\\.?$/, [])\n\n\n const generateNodeID = useCallback((node) => {\n const res = REGEXP_ID.exec(node);\n if (!res || res.length < 3) { return new Date().getTime() }\n return res[2];\n }, [REGEXP_ID])\n\n const getNodeData = useCallback((node) => {\n const nodeId = generateNodeID(node)\n return nodeId\n ? mapExport.attributes.conversion_log.nodes[nodeId]\n : null\n }, [mapExport, generateNodeID])\n\n const displayNode = (node) => {\n const titles = []\n const nodeData = getNodeData(node);\n let hasErrors = false;\n titles.push(nodeData && nodeData.label)\n hasErrors = !(nodeData)\n const hasTitle = titles.filter(n => n).length\n return
)}\n className={hasErrors ? 'text-error' : undefined}\n >\n {hasTitle\n ? titles.join(
)\n : node\n }
\n {hasTitle ?
{node} : null}\n \n }\n\n const displayNtuple = (ntuple) => {\n const { 0: subject, 1: predicate, 2: object } = ntuple.replace(/\\.$/, '').split(' ')\n\n return
\n {displayNode(subject)}\n {predicate} \n {displayNode(object)}\n \n }\n\n const getNodesFromEdge = (edge) => {\n return [edge.from, edge.to].map(nodeId => mapExport.attributes.conversion_log.nodes[nodeId])\n }\n\n const ntuplesToEdges = (tuples) => {\n return tuples.map(ntuple => {\n const { 0: from, 1: label, 2: to } = ntuple.replace(/\\.$/, '').split(' ')\n const fromId = generateNodeID(from) || []\n const toId = generateNodeID(to) || []\n return { from: fromId || from, label, to: toId || to }\n })\n }\n\n const ntuplesToNodes = (tuples) => {\n const nodes = []\n tuples.forEach(ntuple => {\n const n = [];\n const { 0: from, 2: to } = ntuple.replace(/\\.$/, '').split(/[\\s]/)\n n.push(from)\n n.push(to)\n n.forEach(node => {\n let nodeData = getNodeData(node)\n if (nodeData) {\n\n if (!nodes.find(n => n.id === nodeData.id)) {\n nodes.push(nodeData)\n }\n } else {\n const nodeId = generateNodeID(node) || []\n const rawData = { id: nodeId || node, label: node }\n if (!nodes.find(n => n.id === rawData.id)) {\n nodes.push(rawData)\n }\n }\n })\n })\n return nodes;\n }\n\n const errorMap = useMemo(() => mapExport && mapExport.attributes && mapExport.attributes.missing_log.reduce((prev, cur) => {\n switch (cur.error) {\n case 'Edge label not found in matrix':\n case 'Node label not found in matrix':\n prev.matrix.push(cur);\n break;\n case 'Node type not found in Ontology':\n case 'Edge type not found in Ontology':\n prev.ontology.push(cur);\n break;\n case 'Node attribute type unknown':\n case 'Edge attribute type unknown':\n prev.attributes.push(cur);\n break;\n default:\n console.error('Unknown error type: ', cur)\n }\n return prev;\n }, { matrix: [], ontology: [], attributes: [] }),\n [mapExport]);\n console.log(errorMap)\n return (\n
\n \n \n \n Erreurs: \n {errorMap && Object.keys(errorMap).map(errorType => (\n setVisibleErrorType(errorType)} style={{ marginBottom: '1rem' }}>{errorType} ({errorMap[errorType].length}) \n ))}\n \n {mapExport && mapExport.attributes.missing_log.length && Object.keys(errorMap).map(errorType =>\n
\n\n \n \n \n Éléments manquant \n Erreur \n Type recherché (OWL) \n \n \n \n {errorMap[errorType].map(data => (\n \n {data.label} \n {data.error} \n {data.nodeType} \n \n ))}\n \n
\n \n )\n }\n
\n \n \n\n Conversions: \n\n {mapExport && mapExport.attributes.conversion_log.conversions && mapExport.attributes.conversion_log.conversions.map(log => (\n \n
{displayEdge(log.edge)}
\n { console.log({ visibleExportGraphIds, id: log.edge.id }) ||\n visibleExportGraphIds.includes(log.edge.id)\n ?\n
\n :
\n }\n\n
\n \n \n Subject \n Predicate \n Object \n \n \n \n {log.ntuples.map(ntuple => displayNtuple(ntuple))}\n \n
\n
\n ))}\n \n \n \n )\n}\n\nexport default TiddlyMapExport","import Graph from \"../components/Sparql/Graph\"\nimport SiteWrapper from '../SiteWrapper';\nimport { Page, Card } from 'tabler-react';\nimport React, { useEffect, useState } from 'react'\nimport axios from 'axios'\nimport { resultsToGraphData, resultsToDataTable } from \"../utils/queryResultExtractor\"\nimport CodeMirror from '@uiw/react-codemirror';\nimport 'codemirror/keymap/sublime';\nimport 'codemirror/theme/monokai.css';\nimport ReactDatatable from '@ashvin27/react-datatable';\nimport { toast } from 'react-toastify';\nimport Scroll from 'react-scroll';\nconst Element = Scroll.Element;\nconst scroller = Scroll.scroller;\n\nconst SparqlRequest = () => {\n\n const [query, setQuery] = useState(localStorage.getItem(\"last_request\"))\n\n const [queriesSnippets, setQueriesSnippets] = useState([])\n const [selectedQuerrySnippet, setSelectedQuerySnippet] = useState(\"\")\n\n const [isRequestConstruct, setisRequestConstruct] = useState(false)\n\n const [queryResultGraph, setQueryResultGraph] = useState([])\n const [queryResultData, setQueryResultData] = useState([])\n\n const [queryName, setQueryName] = useState(\"\")\n\n useEffect(() => {\n fetchQueries()\n }, [])\n\n /**\n * Obtient les 25 dernières requêtes enregistrées\n */\n const fetchQueries = () => {\n axios.get(`/api/queries/25/recent`)\n .then(({ data: { data } }) => setQueriesSnippets(data))\n }\n\n /**\n * Exécute la requête écrite\n */\n const execRequest = () => {\n const params = new URLSearchParams();\n params.append('query', query);\n axios.post('/fuseki/ds/sparql', params, {\n headers: { \n Accept: isRequestConstruct ? 'application/ld+json' : 'application/json' \n } \n }).then(({ data }) => {\n if(isRequestConstruct){\n // Draw graph\n setQueryResultGraph(\n resultsToGraphData(data)\n )\n setQueryResultData([])\n } else {\n // Fill data table\n setQueryResultData(resultsToDataTable(data))\n setQueryResultGraph([])\n }\n // Somewhere else, even another file\n scroller.scrollTo('result', {\n duration: 500,\n delay: 100,\n smooth: true,\n offset: 50, // Scrolls to element + 50 pixels down the page\n })\n })\n .catch(err => {\n console.error(err)\n switch(err.response?.status) {\n case 400:\n toast.error(\"Erreur dans la synthaxe sparql.\")\n break;\n default:\n toast.error(err.statusText)\n }\n\n })\n }\n\n useEffect(() => {\n localStorage.setItem(\"last_request\", query)\n setisRequestConstruct(query.includes('CONSTRUCT '))\n }, [query])\n\n const saveQuery = () => {\n const formData = new FormData();\n\n formData.append('query_name', queryName);\n formData.append('query_string', query);\n \n axios.post(`/api/queries/`, formData)\n .then(() => fetchQueries())\n }\n\n const loadQuerySnippet = () => {\n if(selectedQuerrySnippet.attributes){\n setQuery(selectedQuerrySnippet.attributes.query_string)\n }\n }\n\n const adaptQuery = (queryString) => {\n if (queryString.slice(-1) !== '\\n') {\n return queryString + '\\n'\n }\n\n return queryString\n }\n\n const updateQuery = (editor) => {\n setQuery(adaptQuery(editor.getValue()))\n }\n\n return (\n
\n \n\n \n
\n\n
\n
\n\n \n Requete Sparql \n \n\n \n\n \n\n Enregistrer la requete \n setQueryName(e.target.value)} />\n { saveQuery() }}>\n Confirmer\n \n
\n\n \n Charger une requête \n { setSelectedQuerySnippet(queriesSnippets[e.target.value]) }}\n >\n {\n (queriesSnippets || []).map((query, index) => {\n return (\n \n {query.attributes.query_name}\n \n )\n })\n }\n \n loadQuerySnippet()}>\n Charger\n \n
\n\n\n updateQuery(editor)}\n\n />\n\n \n \n Executer\n \n
\n \n \n
\n\n {/*
*/}\n
\n
\n \n\n \n Résultat \n \n\n \n \n \n
\n \n ({\n key: columnName,\n text: columnName,\n align: \"left\",\n sortable: true,\n }))\n : []}\n />\n
\n \n\n \n \n
\n\n
\n
\n\n \n \n )\n}\n\nexport default SparqlRequest;\n","const DEFAULT_LANGUAGE = 'fr';\n\nconst resultsToGraphData = (queryResult) => {\n let edges = []\n let nodes = []\n console.log(\"Converting query results into graph data : \")\n console.log(queryResult)\n\n if(queryResult['@graph']){\n console.log(\"result is in json ld format ! \")\n\n queryResult['@graph'].forEach(node => {\n if(node['@id']){\n\n // Get the label of the node\n let label = node.label;\n if(Array.isArray(label)){\n const _label = node.label.find(l => l['@language'] === DEFAULT_LANGUAGE)\n label = _label['@value']\n }\n\n // Keep the found node\n nodes.push({\n id: node['@id'], label, \n shape: label ? undefined : 'diamond' // If no label, this is an intermediate node\n })\n console.log(\"Found node\", {id: node['@id'], label})\n\n // Create the node's edges\n Object.keys(node).forEach(edgeName => {\n const edge = queryResult['@context'][edgeName]\n console.log(label, \" - Checking edge\", edgeName, { edge })\n if(['label'].indexOf(edgeName) < 0 && edge){\n console.log('Attribute to keep found:', edgeName)\n console.log(edgeName, node[edgeName])\n\n const from = node['@id']\n const tos = [node[edgeName]].flat()\n tos.forEach(to => {\n if(typeof to === 'string'){\n edges.push({\n from,\n to,\n label: edgeName,\n })\n }\n })\n }\n })\n }\n })\n }\n\n // Create missing nodes\n edges.forEach(({ to }) => {\n if(to && nodes.map(({ id }) => id).indexOf(to) < 0){\n console.warn('Creating missing node:', {id: to, label: to })\n nodes.push({id: to, label: to })\n }\n })\n\n return {edges, nodes: nodes}\n}\n\n\n/**\n * Formatte les données reçues de Fuseki en un format interprétable pour construire un tableau HTML\n * @param {object} queryResult \n * @returns {Array[Object]} Retourne le résultat formatté\n */\nconst resultsToDataTable = (queryResult) => {\n\n /* Named variable in query\n * @example:\n * SELECT ?subject ?a ?object\n * FROM
\n * WHERE {\n * ?s ?a ?o.\n * ?s rdfs:label ?subject.\n * ?o rdfs:label ?object\n * }\n * LIMIT 25\n */\n\n if(!queryResult){ return [] }\n const result = []\n if(queryResult && queryResult.results){\n queryResult.results.bindings.forEach((value) => {\n const row = {}\n Object.keys(value).forEach(k => {\n row[k] = value[k].value\n })\n result.push(row)\n })}\n console.log({ result })\n return result\n}\nexport { resultsToDataTable, resultsToGraphData }","import axios from 'axios';\nimport React, { useState } from 'react'\nimport { Page, Card } from 'tabler-react';\nimport SiteWrapper from '../SiteWrapper';\nimport { toast } from 'react-toastify';\n\nconst OntologyLoading = () => {\n const [excelClassesFile, setExcelClassesFile] = useState('')\n const [owlClassesFile, setOwlClassesFile] = useState('')\n\n const uploadExcelFile = () => {\n if (excelClassesFile !== '') {\n var data = new FormData()\n data.append('file', excelClassesFile)\n axios.post('/api/excel_classes', data)\n .then((result) => {\n toast.success('Fichier mis a jour avec succès !')\n })\n .catch((error) => {\n toast.error(\"Une erreur s'est produite.\")\n console.log(error)\n })\n } else {\n toast.error(\"Aucun fichier selectionné.\")\n }\n\n }\n\n const loadExcelFile = (file) => {\n setExcelClassesFile(file)\n }\n\n const uploadOwlFile = () => {\n if (owlClassesFile !== '') {\n var data = new FormData()\n data.append('file', owlClassesFile)\n axios.post('/api/owl_classes', data)\n .then((result) => {\n toast.success('Fichier mis a jour avec succès !')\n })\n .catch((error) => {\n toast.error(\"Une erreur s'est produite.\")\n console.log(error)\n })\n } else {\n toast.error(\"Aucun fichier selectionné.\")\n\n }\n\n\n }\n\n const loadOwlFile = (file) => {\n setOwlClassesFile(file)\n }\n\n\n\n return (\n \n \n \n\n \n \n )\n}\n\nexport default OntologyLoading;","import { Page, Card } from 'tabler-react';\nimport SiteWrapper from '../SiteWrapper';\n\nconst OntologyLoading = () => {\n\treturn (\n \n \n\n \n
\n\n
\n
\n\n \n Tiddlers lists \n \n\n \n\n \n\n tiddlers 1 \n\t\t\t\t\ttiddlers 2 \n\t\t\t\t\ttiddlers 3 \n\t\t\t\t\ttiddlers 4 \n\t\t\t\t\ttiddlers 5 \t\t\t\t\t\n\n\n
\n \n \n
\n\n {/*
*/}\n
\n \n\n \n Tiddlers alignement \n \n\n \n here goes alignment \n \n\n \n
\n\n
\n
\n\n \n \n )\n}\nexport default OntologyLoading;","import * as React from \"react\";\nimport { BrowserRouter as Router, Route, Switch } from \"react-router-dom\";\nimport \"tabler-react/dist/Tabler.css\";\nimport './App.css'\nimport TiddlyWiki from './pages/TiddlyWiki'\nimport TiddlyMapView from './pages/TiddlyMapView'\nimport TiddlyMapExportList from './pages/TiddlyMapExport/index'\nimport TiddlyMapExportShow from './pages/TiddlyMapExport/show'\nimport SparqlRequest from './pages/SparqlRequest'\nimport OntologyLoading from './pages/OntologyLoading'\nimport TiddlersMapping from './pages/TiddlersMapping'\n\nconst Error404 = () => 404 PAGE \n\nconst App = () => {\n return (\n \n \n \n \n \n \n \n \n \n \n\t\t \n {/* */}\n {/* \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n */}\n \n \n \n \n );\n}\n\nexport default App;","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport 'bootstrap/dist/css/bootstrap.min.css'; // add this\nimport './index.css';\nimport '@neos21/bootstrap3-glyphicons/dist/css/bootstrap3-glyphicons.min.css'\nimport reportWebVitals from './reportWebVitals';\nimport App from './App';\n\nReactDOM.render( , document.getElementById('root'));\nreportWebVitals(console.log);\n"],"sourceRoot":""}