Initial commit
This commit is contained in:
commit
d38f28bd07
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.idea
|
||||||
|
dataset/kb/data/*
|
||||||
|
!dataset/kb/data/.gitkeep
|
16
CHANGELOG.md
Normal file
16
CHANGELOG.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Changelog
|
||||||
|
Tous les changements notables apportés à ce projet seront documentés dans ce fichier.
|
||||||
|
|
||||||
|
Le format est basé sur [Keep a Changelog](http://keepachangelog.com/fr/1.0.0/)
|
||||||
|
et ce projet adhère à [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.0.0] - 2018-04-24
|
||||||
|
|
||||||
|
### Ajouts
|
||||||
|
- Code source initial
|
||||||
|
- Documentation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 DATAtourisme
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
106
README.md
Normal file
106
README.md
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://www.datatourisme.gouv.fr" target="_blank">
|
||||||
|
<img alt="DATAtourisme" src="https://framagit.org/datatourisme/api/raw/master/docs/_media/logo.png">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
La plateforme <strong>OPEN DATA</strong> de l'information touristique
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center"><a href="https://www.datatourisme.gouv.fr/">https://www.datatourisme.gouv.fr</a></p>
|
||||||
|
|
||||||
|
|
||||||
|
# Environnement full-stack Docker
|
||||||
|
|
||||||
|
Ce projet contient un environnement [docker-compose](https://docs.docker.com/compose/) contenant les
|
||||||
|
services suivants :
|
||||||
|
|
||||||
|
* La base de données [Blazegraph](http://www.blazegraph.com)
|
||||||
|
* L'[API DATAtourisme](https://framagit.org/datatourisme/api) associée à :
|
||||||
|
* Un point d'accès HTTP GraphQL
|
||||||
|
* [GraphiQL](https://github.com/graphql/graphiql), une interface visuelle de conception de requête
|
||||||
|
* [Voyager](https://github.com/APIs-guru/graphql-voyager), un visualisateur de schéma sous forme de graphe.
|
||||||
|
|
||||||
|
Ce stack vous permet de mettre rapidement en place un environnement de restitution des données touristiques
|
||||||
|
téléchargées à partir de la [plateforme diffuseur](https://diffuseur.datatourisme.gouv.fr).
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
### Pré-requis
|
||||||
|
|
||||||
|
Pour utiliser l'environnement, doivent être installés et configurés :
|
||||||
|
|
||||||
|
* [Docker-ce](https://docs.docker.com/engine/installation/)
|
||||||
|
* [docker-compose](https://docs.docker.com/compose/install/)
|
||||||
|
|
||||||
|
Par défaut, vous devrez rendre disponible les ports 8080 et 9999.
|
||||||
|
|
||||||
|
### Récupération d'un fichier de données
|
||||||
|
|
||||||
|
Pour vous servir de l'environnement, vous devez d'abord récupérer des données touristiques :
|
||||||
|
|
||||||
|
1. Connectez-vous à la [plateforme diffuseur](https://diffuseur.datatourisme.gouv.fr). Il sera nécessaire de
|
||||||
|
créer un compte s'il s'agit de votre première connexion.
|
||||||
|
2. Créez et configurez un flux de données à l'aide de l'éditeur visuel de requête.
|
||||||
|
3. Configurez le flux pour utiliser un format **compatible avec l'API** :
|
||||||
|
* RDF-XML
|
||||||
|
* Turtle
|
||||||
|
* NT
|
||||||
|
4. Téléchargez le fichier du flux une fois celui-ci disponible.
|
||||||
|
|
||||||
|
Le fichier ainsi obtenu doit être copié dans le répertoire `dataset/kb/data` pour être chargé dans la base de
|
||||||
|
données lors de la création du conteneur Docker.
|
||||||
|
|
||||||
|
À titre d'information, voici comment se décompose le dossier `dataset` :
|
||||||
|
|
||||||
|
| Répertoire | description |
|
||||||
|
| -------------------------------- |-------------------------------------------------|
|
||||||
|
| dataset/ | Répertoire décrivant la configuration et les données à charger dans le namespace |
|
||||||
|
| /kb/ | Namespace pour les données (kb étant le namespace par défaut) |
|
||||||
|
| /data/ | Répertoire où copier les données sémantiques (ttl, nt, n3, xml, gz...) |
|
||||||
|
| /RWSTore.properties | Configuration de la base de données pour ce namespace namespace |
|
||||||
|
|
||||||
|
### Lancement de l'environnement
|
||||||
|
|
||||||
|
Vous pouvez maintenant lancer l'environnement :
|
||||||
|
|
||||||
|
```
|
||||||
|
$ docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
Ces commandes lanceront deux serveurs :
|
||||||
|
- un serveur [Blazegraph](https://www.blazegraph.com/) sur le port 9999 chargé de vos données.
|
||||||
|
- un serveur incluant l'[API DATAtourisme](https://framagit.org/datatourisme/api) sur le port 8080.
|
||||||
|
|
||||||
|
Vous pouvez accèder aux interfaces suivantes :
|
||||||
|
|
||||||
|
* Interface d'administration Blazegraph : http://localhost:9999
|
||||||
|
* Point d'accès HTTP GraphQL : http://localhost:8080
|
||||||
|
* GraphiQL : http://localhost:8080/graphiql
|
||||||
|
* Voyager : http://localhost:8080/voyager
|
||||||
|
|
||||||
|
### Utilisation de l'API
|
||||||
|
|
||||||
|
Pour utiliser l'API, reportez vous à la [documentation officielle](https://datatourisme.frama.io/api/#/).
|
||||||
|
|
||||||
|
### Mise à jour des données
|
||||||
|
|
||||||
|
Lorsque vous souhaitez mettre à jour les données de votre environnement, vous devez procéder ainsi :
|
||||||
|
|
||||||
|
1. Stoppez l'environnement s'il est actif : `docker-compose stop`
|
||||||
|
1. Téléchargez le nouveau fichier de donnée et remplacez le dans **dataset/kb/data**
|
||||||
|
2. Supprimez le conteneur Blazegraph : `docker-compose rm blazegraph`
|
||||||
|
3. Relancez l'environnement : `docker-compose up`
|
||||||
|
|
||||||
|
## Liens
|
||||||
|
|
||||||
|
* [API DATAtourisme](https://framagit.org/datatourisme/api)
|
||||||
|
* [Documentation de l'API](https://datatourisme.frama.io/api)
|
||||||
|
* [Plateforme diffuseur](https://diffuseur.datatourisme.gouv.fr)
|
||||||
|
* Centre de support
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License
|
53
dataset/kb/RWStore.properties
Normal file
53
dataset/kb/RWStore.properties
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#
|
||||||
|
# Note: These options are applied when the journal and the triple store are
|
||||||
|
# first created.
|
||||||
|
|
||||||
|
##
|
||||||
|
## Journal options.
|
||||||
|
##
|
||||||
|
|
||||||
|
# The backing file. This contains all your data. You want to put this someplace
|
||||||
|
# safe. The default locator will wind up in the directory from which you start
|
||||||
|
# your servlet container.
|
||||||
|
com.bigdata.journal.AbstractJournal.file=/var/lib/blazegraph/blazegraph.jnl
|
||||||
|
|
||||||
|
# The persistence engine. Use 'Disk' for the WORM or 'DiskRW' for the RWStore.
|
||||||
|
com.bigdata.journal.AbstractJournal.bufferMode=DiskRW
|
||||||
|
|
||||||
|
# Setup for the RWStore recycler rather than session protection.
|
||||||
|
com.bigdata.service.AbstractTransactionService.minReleaseAge=1
|
||||||
|
|
||||||
|
# Enable group commit. See http://wiki.blazegraph.com/wiki/index.php/GroupCommit
|
||||||
|
# Note: Group commit is a beta feature in BlazeGraph release 1.5.1.
|
||||||
|
#com.bigdata.journal.Journal.groupCommit=true
|
||||||
|
|
||||||
|
com.bigdata.btree.writeRetentionQueue.capacity=4000
|
||||||
|
com.bigdata.btree.BTree.branchingFactor=128
|
||||||
|
|
||||||
|
# 200M initial extent
|
||||||
|
com.bigdata.journal.AbstractJournal.initialExtent=209715200
|
||||||
|
com.bigdata.journal.AbstractJournal.maximumExtent=209715200
|
||||||
|
|
||||||
|
##
|
||||||
|
## Setup for QUADS mode without the full text index.
|
||||||
|
##
|
||||||
|
com.bigdata.rdf.sail.truthMaintenance=false
|
||||||
|
com.bigdata.rdf.store.AbstractTripleStore.quads=false
|
||||||
|
com.bigdata.rdf.store.AbstractTripleStore.statementIdentifiers=false
|
||||||
|
com.bigdata.rdf.store.AbstractTripleStore.textIndex=true
|
||||||
|
com.bigdata.rdf.store.AbstractTripleStore.axiomsClass=com.bigdata.rdf.axioms.NoAxioms
|
||||||
|
|
||||||
|
# Bump up the branching factor for the lexicon indices on the default kb.
|
||||||
|
com.bigdata.namespace.kb.lex.com.bigdata.btree.BTree.branchingFactor=400
|
||||||
|
|
||||||
|
# Bump up the branching factor for the statement indices on the default kb.
|
||||||
|
com.bigdata.namespace.kb.spo.com.bigdata.btree.BTree.branchingFactor=1024
|
||||||
|
|
||||||
|
# Uncomment to enable collection of OS level performance counters. When
|
||||||
|
# collected they will be self-reported through the /counters servlet and
|
||||||
|
# the workbench "Performance" tab.
|
||||||
|
#
|
||||||
|
# com.bigdata.journal.Journal.collectPlatformStatistics=true
|
||||||
|
|
||||||
|
# geospatial
|
||||||
|
com.bigdata.rdf.store.AbstractTripleStore.geoSpatial=true
|
0
dataset/kb/data/.gitkeep
Normal file
0
dataset/kb/data/.gitkeep
Normal file
23
docker-compose.yml
Normal file
23
docker-compose.yml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
blazegraph:
|
||||||
|
image: conjecto/blazegraph
|
||||||
|
ports:
|
||||||
|
- 9999:9999
|
||||||
|
environment:
|
||||||
|
JAVA_XMS: 512m
|
||||||
|
JAVA_XMX: 1g
|
||||||
|
volumes:
|
||||||
|
- ./dataset:/docker-entrypoint-initdb.d
|
||||||
|
ports:
|
||||||
|
- "9999:9999"
|
||||||
|
|
||||||
|
datatourisme:
|
||||||
|
build: docker
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
- blazegraph
|
22
docker/Dockerfile
Normal file
22
docker/Dockerfile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
FROM php
|
||||||
|
MAINTAINER Conjecto <contact@conjecto.com>
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
--no-install-recommends git zip zlib1g-dev
|
||||||
|
|
||||||
|
RUN docker-php-ext-install -j$(nproc) zip
|
||||||
|
|
||||||
|
COPY app/ /var/app/
|
||||||
|
WORKDIR /var/app/
|
||||||
|
|
||||||
|
# install composer
|
||||||
|
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
||||||
|
RUN php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
|
||||||
|
RUN php composer-setup.php
|
||||||
|
RUN php -r "unlink('composer-setup.php');"
|
||||||
|
|
||||||
|
# install vendors
|
||||||
|
RUN php composer.phar install
|
||||||
|
|
||||||
|
# run server
|
||||||
|
CMD ["php", "-S", "0.0.0.0:80", "-t", "/var/app/www"]
|
13
docker/app/composer.json
Normal file
13
docker/app/composer.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"type": "project",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Conjecto",
|
||||||
|
"email": "contact@conjecto.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": "^7.0",
|
||||||
|
"datatourisme/api": "^1.0"
|
||||||
|
}
|
||||||
|
}
|
1
docker/app/www/graphiql/es6-promise.auto.min.js
vendored
Normal file
1
docker/app/www/graphiql/es6-promise.auto.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
docker/app/www/graphiql/fetch.min.js
vendored
Normal file
1
docker/app/www/graphiql/fetch.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
!function(){"use strict";function t(t){if("string"!=typeof t&&(t=t.toString()),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(t))throw new TypeError("Invalid character in header field name");return t.toLowerCase()}function e(t){return"string"!=typeof t&&(t=t.toString()),t}function r(t){this.map={},t instanceof r?t.forEach(function(t,e){this.append(e,t)},this):t&&Object.getOwnPropertyNames(t).forEach(function(e){this.append(e,t[e])},this)}function o(t){return t.bodyUsed?Promise.reject(new TypeError("Already read")):void(t.bodyUsed=!0)}function n(t){return new Promise(function(e,r){t.onload=function(){e(t.result)},t.onerror=function(){r(t.error)}})}function s(t){var e=new FileReader;return e.readAsArrayBuffer(t),n(e)}function i(t){var e=new FileReader;return e.readAsText(t),n(e)}function a(){return this.bodyUsed=!1,this._initBody=function(t){if(this._bodyInit=t,"string"==typeof t)this._bodyText=t;else if(p.blob&&Blob.prototype.isPrototypeOf(t))this._bodyBlob=t;else if(p.formData&&FormData.prototype.isPrototypeOf(t))this._bodyFormData=t;else{if(t)throw new Error("unsupported BodyInit type");this._bodyText=""}},p.blob?(this.blob=function(){var t=o(this);if(t)return t;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this.blob().then(s)},this.text=function(){var t=o(this);if(t)return t;if(this._bodyBlob)return i(this._bodyBlob);if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)}):this.text=function(){var t=o(this);return t?t:Promise.resolve(this._bodyText)},p.formData&&(this.formData=function(){return this.text().then(h)}),this.json=function(){return this.text().then(JSON.parse)},this}function u(t){var e=t.toUpperCase();return c.indexOf(e)>-1?e:t}function f(t,e){if(e=e||{},this.url=t,this.credentials=e.credentials||"omit",this.headers=new r(e.headers),this.method=u(e.method||"GET"),this.mode=e.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&e.body)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(e.body)}function h(t){var e=new FormData;return t.trim().split("&").forEach(function(t){if(t){var r=t.split("="),o=r.shift().replace(/\+/g," "),n=r.join("=").replace(/\+/g," ");e.append(decodeURIComponent(o),decodeURIComponent(n))}}),e}function d(t){var e=new r,o=t.getAllResponseHeaders().trim().split("\n");return o.forEach(function(t){var r=t.trim().split(":"),o=r.shift().trim(),n=r.join(":").trim();e.append(o,n)}),e}function l(t,e){e||(e={}),this._initBody(t),this.type="default",this.url=null,this.status=e.status,this.ok=this.status>=200&&this.status<300,this.statusText=e.statusText,this.headers=e.headers instanceof r?e.headers:new r(e.headers),this.url=e.url||""}if(!self.fetch){r.prototype.append=function(r,o){r=t(r),o=e(o);var n=this.map[r];n||(n=[],this.map[r]=n),n.push(o)},r.prototype["delete"]=function(e){delete this.map[t(e)]},r.prototype.get=function(e){var r=this.map[t(e)];return r?r[0]:null},r.prototype.getAll=function(e){return this.map[t(e)]||[]},r.prototype.has=function(e){return this.map.hasOwnProperty(t(e))},r.prototype.set=function(r,o){this.map[t(r)]=[e(o)]},r.prototype.forEach=function(t,e){Object.getOwnPropertyNames(this.map).forEach(function(r){this.map[r].forEach(function(o){t.call(e,o,r,this)},this)},this)};var p={blob:"FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(t){return!1}}(),formData:"FormData"in self},c=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];a.call(f.prototype),a.call(l.prototype),self.Headers=r,self.Request=f,self.Response=l,self.fetch=function(t,e){var r;return r=f.prototype.isPrototypeOf(t)&&!e?t:new f(t,e),new Promise(function(t,e){function o(){return"responseURL"in n?n.responseURL:/^X-Request-URL:/m.test(n.getAllResponseHeaders())?n.getResponseHeader("X-Request-URL"):void 0}var n=new XMLHttpRequest;n.onload=function(){var r=1223===n.status?204:n.status;if(100>r||r>599)return void e(new TypeError("Network request failed"));var s={status:r,statusText:n.statusText,headers:d(n),url:o()},i="response"in n?n.response:n.responseText;t(new l(i,s))},n.onerror=function(){e(new TypeError("Network request failed"))},n.open(r.method,r.url,!0),"include"===r.credentials&&(n.withCredentials=!0),"responseType"in n&&p.blob&&(n.responseType="blob"),r.headers.forEach(function(t,e){n.setRequestHeader(e,t)}),n.send("undefined"==typeof r._bodyInit?null:r._bodyInit)})},self.fetch.polyfill=!0}}();
|
1740
docker/app/www/graphiql/graphiql.css
Normal file
1740
docker/app/www/graphiql/graphiql.css
Normal file
File diff suppressed because it is too large
Load Diff
39655
docker/app/www/graphiql/graphiql.js
Normal file
39655
docker/app/www/graphiql/graphiql.js
Normal file
File diff suppressed because it is too large
Load Diff
149
docker/app/www/graphiql/index.html
Normal file
149
docker/app/www/graphiql/index.html
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<!--
|
||||||
|
* Copyright (c) Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#graphiql {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This GraphiQL example depends on Promise and fetch, which are available in
|
||||||
|
modern browsers, but can be "polyfilled" for older browsers.
|
||||||
|
GraphiQL itself depends on React DOM.
|
||||||
|
If you do not want to rely on a CDN, you can host these files locally or
|
||||||
|
include them directly in your favored resource bunder.
|
||||||
|
-->
|
||||||
|
<script src="/graphiql/es6-promise.auto.min.js"></script>
|
||||||
|
<script src="/graphiql/fetch.min.js"></script>
|
||||||
|
<script src="/graphiql/react.min.js"></script>
|
||||||
|
<script src="/graphiql/react-dom.min.js"></script>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
These two files can be found in the npm module, however you may wish to
|
||||||
|
copy them directly into your environment, or perhaps include them in your
|
||||||
|
favored resource bundler.
|
||||||
|
-->
|
||||||
|
<link rel="stylesheet" href="/graphiql/graphiql.css" />
|
||||||
|
<script src="/graphiql/graphiql.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="graphiql">Loading...</div>
|
||||||
|
<script>
|
||||||
|
var serverUri = '/';
|
||||||
|
/**
|
||||||
|
* This GraphiQL example illustrates how to use some of GraphiQL's props
|
||||||
|
* in order to enable reading and updating the URL parameters, making
|
||||||
|
* link sharing of queries a little bit easier.
|
||||||
|
*
|
||||||
|
* This is only one example of this kind of feature, GraphiQL exposes
|
||||||
|
* various React params to enable interesting integrations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Parse the search string to get url parameters.
|
||||||
|
var search = window.location.search;
|
||||||
|
var parameters = {};
|
||||||
|
search.substr(1).split('&').forEach(function (entry) {
|
||||||
|
var eq = entry.indexOf('=');
|
||||||
|
if (eq >= 0) {
|
||||||
|
parameters[decodeURIComponent(entry.slice(0, eq))] =
|
||||||
|
decodeURIComponent(entry.slice(eq + 1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// if variables was provided, try to format it.
|
||||||
|
if (parameters.variables) {
|
||||||
|
try {
|
||||||
|
parameters.variables =
|
||||||
|
JSON.stringify(JSON.parse(parameters.variables), null, 2);
|
||||||
|
} catch (e) {
|
||||||
|
// Do nothing, we want to display the invalid JSON as a string, rather
|
||||||
|
// than present an error.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the query and variables string is edited, update the URL bar so
|
||||||
|
// that it can be easily shared
|
||||||
|
function onEditQuery(newQuery) {
|
||||||
|
parameters.query = newQuery;
|
||||||
|
updateURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEditVariables(newVariables) {
|
||||||
|
parameters.variables = newVariables;
|
||||||
|
updateURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEditOperationName(newOperationName) {
|
||||||
|
parameters.operationName = newOperationName;
|
||||||
|
updateURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateURL() {
|
||||||
|
var newSearch = '?' + Object.keys(parameters).filter(function (key) {
|
||||||
|
return Boolean(parameters[key]);
|
||||||
|
}).map(function (key) {
|
||||||
|
return encodeURIComponent(key) + '=' +
|
||||||
|
encodeURIComponent(parameters[key]);
|
||||||
|
}).join('&');
|
||||||
|
history.replaceState(null, null, newSearch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defines a GraphQL fetcher using the fetch API. You're not required to
|
||||||
|
// use fetch, and could instead implement graphQLFetcher however you like,
|
||||||
|
// as long as it returns a Promise or Observable.
|
||||||
|
function graphQLFetcher(graphQLParams) {
|
||||||
|
// This example expects a GraphQL server at the path /graphql.
|
||||||
|
// Change this to point wherever you host your GraphQL server.
|
||||||
|
return fetch(serverUri, {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(graphQLParams),
|
||||||
|
credentials: 'include',
|
||||||
|
}).then(function (response) {
|
||||||
|
return response.text();
|
||||||
|
}).then(function (responseBody) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(responseBody);
|
||||||
|
} catch (error) {
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render <GraphiQL /> into the body.
|
||||||
|
// See the README in the top level of this module to learn more about
|
||||||
|
// how you can customize GraphiQL by providing different values or
|
||||||
|
// additional child elements.
|
||||||
|
ReactDOM.render(
|
||||||
|
React.createElement(GraphiQL, {
|
||||||
|
fetcher: graphQLFetcher,
|
||||||
|
query: parameters.query,
|
||||||
|
variables: parameters.variables,
|
||||||
|
operationName: parameters.operationName,
|
||||||
|
onEditQuery: onEditQuery,
|
||||||
|
onEditVariables: onEditVariables,
|
||||||
|
onEditOperationName: onEditOperationName
|
||||||
|
}),
|
||||||
|
document.getElementById('graphiql')
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
15
docker/app/www/graphiql/react-dom.min.js
vendored
Normal file
15
docker/app/www/graphiql/react-dom.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
12
docker/app/www/graphiql/react.min.js
vendored
Normal file
12
docker/app/www/graphiql/react.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
26
docker/app/www/index.php
Normal file
26
docker/app/www/index.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
//define('SERVER', 'sparql'); # switch resolver to pure sparql
|
||||||
|
header('Access-Control-Allow-Credentials: true', true);
|
||||||
|
header('Access-Control-Allow-Origin: *');
|
||||||
|
header('Access-Control-Allow-Headers: Content-Type');
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_SERVER['CONTENT_TYPE']) && $_SERVER['CONTENT_TYPE'] === 'application/json') {
|
||||||
|
$rawBody = file_get_contents('php://input');
|
||||||
|
$requestData = json_decode($rawBody ?: '', true);
|
||||||
|
} else {
|
||||||
|
$requestData = $_POST;
|
||||||
|
}
|
||||||
|
$payload = isset($requestData['query']) ? $requestData['query'] : null;
|
||||||
|
|
||||||
|
require_once __DIR__.'/../vendor/autoload.php';
|
||||||
|
|
||||||
|
$processor = \Datatourisme\Api\DatatourismeApi::create('http://blazegraph:9999/blazegraph/namespace/kb/sparql');
|
||||||
|
$response = $processor->process($payload);
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode($response);
|
||||||
|
exit;
|
65
docker/app/www/voyager/index.html
Normal file
65
docker/app/www/voyager/index.html
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#voyager {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This GraphQL Voyager example depends on Promise and fetch, which are available in
|
||||||
|
modern browsers, but can be "polyfilled" for older browsers.
|
||||||
|
GraphQL Voyager itself depends on React DOM.
|
||||||
|
If you do not want to rely on a CDN, you can host these files locally or
|
||||||
|
include them directly in your favored resource bunder.
|
||||||
|
-->
|
||||||
|
<script src="//cdn.jsdelivr.net/es6-promise/4.0.5/es6-promise.auto.min.js"></script>
|
||||||
|
<script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>
|
||||||
|
<script src="//cdn.jsdelivr.net/react/15.4.2/react.min.js"></script>
|
||||||
|
<script src="//cdn.jsdelivr.net/react/15.4.2/react-dom.min.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://apis.guru/graphql-voyager/releases/v1.x/voyager.css" />
|
||||||
|
<script src="https://apis.guru/graphql-voyager/releases/v1.x/voyager.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="voyager">Loading...</div>
|
||||||
|
<script>
|
||||||
|
// Defines a GraphQL introspection fetcher using the fetch API. You're not required to
|
||||||
|
// use fetch, and could instead implement introspectionProvider however you like,
|
||||||
|
// as long as it returns a Promise
|
||||||
|
// Voyager passes introspectionQuery as an agrument for this function
|
||||||
|
function introspectionProvider(introspectionQuery) {
|
||||||
|
// This example expects a GraphQL server at the path /graphql.
|
||||||
|
// Change this to point wherever you host your GraphQL server.
|
||||||
|
return fetch('/', {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({query: introspectionQuery}),
|
||||||
|
credentials: 'include',
|
||||||
|
}).then(function (response) {
|
||||||
|
return response.text();
|
||||||
|
}).then(function (responseBody) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(responseBody);
|
||||||
|
} catch (error) {
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Render <Voyager /> into the body.
|
||||||
|
GraphQLVoyager.init(document.getElementById('voyager'), {
|
||||||
|
introspection: introspectionProvider
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user