Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/about.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<li>authentication using WebID and OpenID Connect</li>
<li><a href="../reference/administration/acl/" target="_blank">access control</a> using WAC authorizations</li>
</ul>
<p class="lead">Checkout the user guide on <a href="../user-guide/build-apps/">application building</a>.</p>
<p class="lead">Follow the <a href="../tutorial/">tutorial</a> to build your first app, then see the user guide on <a href="../user-guide/build-apps/">application building</a> for the extension layers.</p>
</div>
<div>
<h2 id="kms">Federated knowledge management and collaboration system</h2>
Expand Down
1 change: 1 addition & 0 deletions docs/get-started.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<p class="lead">All the basics of LinkedDataHub. From installation to customizing the model and user interface.</p>
<p>This guide will show how a LinkedDataHub application can be used to manage domain-specific RDF classes and instances. As an example, we will use <a href="https://www.w3.org/TR/skos-primer/" target="_blank">SKOS</a> concepts and concept schemes.</p>
<p>Note that most management actions can also be performed using the <a href="../reference/command-line-interface/" target="_blank">CLI (Command Line Interface)</a>. Where applicable, the UI and CLI instructions are shown side by side. The <a href="https://github.com/AtomGraph/LinkedDataHub-Apps/tree/master/demo/unesco-thesaurus" target="_blank">UNESCO Thesaurus demo app</a> demonstrates how SKOS vocabularies can be managed in LinkedDataHub.</p>
<p class="lead">New to LinkedDataHub? The <a href="../tutorial/" target="_blank">tutorial</a> builds a complete application, from an empty dataspace to a published app.</p>
<div>
<h2 id="setup">Setup</h2>
<p>Setup is only required if you plan to run your own instance of LinkedDataHub. It consists of few steps, which involve creating a configuration file and running a
Expand Down
37 changes: 37 additions & 0 deletions docs/tutorial.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@prefix ldh: <https://w3id.org/atomgraph/linkeddatahub#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dh: <https://www.w3.org/ns/ldt/document-hierarchy#> .
@prefix dct: <http://purl.org/dc/terms/> .

<> a dh:Container ;
dct:title "Tutorial" ;
dct:description "Build your first Knowledge Graph application, from an empty dataspace to a published app" ;
rdf:_1 <#content> .

<#content> a ldh:XHTML ;
rdf:value """<div xmlns="http://www.w3.org/1999/xhtml">
<p class="lead">Build your first Knowledge Graph application, from an empty dataspace to a published app</p>
<p>This tutorial rebuilds the <a href="https://github.com/AtomGraph/LinkedDataHub-Apps/tree/master/demo/northwind-traders" target="_blank">Northwind Traders demo application</a>: the iconic sample
database, reborn as an RDF Knowledge Graph. Every stage ends with a result you can see in the browser. Most steps are shown two ways: point-and-click in the user interface, and as
<a href="../reference/command-line-interface/" target="_blank">CLI commands</a> that you can script, version and replay.</p>
<p>Before you start you need a running LinkedDataHub instance and the owner's WebID certificate. The <a href="../get-started/" target="_blank">Get started</a> section covers both. The command line
examples assume the <code>bin/</code> scripts are on your <code>PATH</code> and use these shell variables throughout:</p>
<pre>base="https://localhost:4443/"
cert_pem_file="ssl/owner/cert.pem"
cert_password="..."</pre>
<div>
<h2 id="stages">Stages</h2>
<ol>
<li><a href="hello-dataspace/">Hello dataspace</a> — give your app an identity and a landing page</li>
<li><a href="structure/">Structure</a> — lay out the document hierarchy</li>
<li><a href="model/">Model</a> — define the vocabulary that describes your domain</li>
<li><a href="data/">Data</a> — import CSV data using SPARQL mappings</li>
<li><a href="media/">Media</a> — upload files and link them to resources</li>
<li><a href="insight/">Insight</a> — turn SPARQL queries into charts and views</li>
<li><a href="composition/">Composition</a> — assemble the landing page from content blocks</li>
<li><a href="publish/">Publish</a> — grant public access and ship it</li>
<li><a href="app-as-repository/">App as a repository</a> — make the app reproducible</li>
<li><a href="beyond-low-code/">Beyond low-code</a> — where to go when data alone is not enough</li>
</ol>
</div>
</div>"""^^rdf:XMLLiteral .
50 changes: 50 additions & 0 deletions docs/tutorial/app-as-repository.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@prefix ldh: <https://w3id.org/atomgraph/linkeddatahub#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dh: <https://www.w3.org/ns/ldt/document-hierarchy#> .
@prefix dct: <http://purl.org/dc/terms/> .

<> a dh:Item ;
dct:title "App as a repository" ;
dct:description "Make the app reproducible: a git repository that installs into any instance" ;
rdf:_1 <#content> .

<#content> a ldh:XHTML ;
rdf:value """<div xmlns="http://www.w3.org/1999/xhtml">
<p class="lead">Make the app reproducible: a git repository that installs into any instance</p>
<p>Every stage so far produced files — document descriptions, mapping queries, CSV data, media. Kept in a repository with a small install script, they <em>are</em> the application: versionable,
diffable, reviewable, and replayable into any LinkedDataHub instance. This is the layout the <a href="https://github.com/AtomGraph/LinkedDataHub-Apps/tree/master/demo/northwind-traders" target="_blank">Northwind Traders repository</a> uses:</p>
<pre>northwind-traders/
├── root.ttl # one .ttl per document...
├── categories.ttl
├── categories/ # ...and a folder for the files it imports
│ ├── categories.csv
│ ├── categories.rq
│ └── *.gif
├── admin/model/
│ ├── ns.ttl # the namespace ontology
│ ├── patch-ontology.ru # resets it before re-import
│ └── import-ns.sh
├── imports.csv # the CSV import manifest
├── install.sh # replays everything against a base URI
├── update-folder.sh
├── .ldhignore # files that are not documents
└── Makefile</pre>
<div>
<h2 id="convention">The convention</h2>
<p>The document URL is derived from the file path: <samp>categories.ttl</samp> installs to <samp>${base}categories/</samp>, <samp>root.ttl</samp> to <samp>${base}</samp> itself.
<samp>update-folder.sh</samp> walks the tree applying that rule — resolving each file's relative URIs against its document URL and <code>PUT</code>ting the result — and skips anything
matched by <samp>.ldhignore</samp>.</p>
</div>
<div>
<h2 id="idempotency">Idempotency</h2>
<p>Re-running the install converges instead of duplicating: <code>PUT</code> replaces each document's description outright, and the one place that appends rather than replaces — the
namespace ontology — is first reset by <samp>patch-ontology.ru</samp>, a SPARQL update that clears the previously imported terms.</p>
</div>
<div>
<h2 id="install">Installing</h2>
<pre>make install</pre>
<p>prompts for the base URI, certificate and password, then runs <samp>install.sh</samp>: make public, import the ontology, replay the documents, upload the files, run the CSV imports. The
entire tutorial, replayed in one command — against localhost today, against production tomorrow.</p>
</div>
<p class="lead">Next: <a href="../beyond-low-code/">Beyond low-code</a></p>
</div>"""^^rdf:XMLLiteral .
26 changes: 26 additions & 0 deletions docs/tutorial/beyond-low-code.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@prefix ldh: <https://w3id.org/atomgraph/linkeddatahub#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dh: <https://www.w3.org/ns/ldt/document-hierarchy#> .
@prefix dct: <http://purl.org/dc/terms/> .

<> a dh:Item ;
dct:title "Beyond low-code" ;
dct:description "Where to go when data alone is not enough" ;
rdf:_1 <#content> .

<#content> a ldh:XHTML ;
rdf:value """<div xmlns="http://www.w3.org/1999/xhtml">
<p class="lead">Where to go when data alone is not enough</p>
<p>Everything in this tutorial was done with data: documents, queries and authorizations, applied over HTTP. That is the ceiling of the low-code approach — and there is a door in it. Each layer
of LinkedDataHub can be extended without forking it:</p>
<ul>
<li><strong>Layout</strong> — write an XSLT stylesheet that imports the system one and overrides only the templates you need. Start with the
<a href="../../user-guide/change-layout/" target="_blank">Change layout</a> guide and the <a href="../../reference/stylesheets/" target="_blank">stylesheets reference</a>.</li>
<li><strong>Docker and Java</strong> — mount files into the stock image, build your own image on top of it, or add JAX-RS endpoints via a WAR overlay. The
<a href="../../user-guide/build-apps/" target="_blank">Build apps</a> guide covers each layer with working build files.</li>
<li><strong>More examples</strong> — the <a href="https://github.com/AtomGraph/LinkedDataHub-Apps" target="_blank">LinkedDataHub-Apps repository</a> holds the complete Northwind Traders
source alongside further demo apps and installable packages.</li>
</ul>
<p>If you get stuck or build something worth showing, open a thread on <a href="https://github.com/AtomGraph/LinkedDataHub/discussions" target="_blank">GitHub Discussions</a>.</p>
<p class="lead">Back to the <a href="../">Tutorial</a> overview</p>
</div>"""^^rdf:XMLLiteral .
39 changes: 39 additions & 0 deletions docs/tutorial/composition.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@prefix ldh: <https://w3id.org/atomgraph/linkeddatahub#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dh: <https://www.w3.org/ns/ldt/document-hierarchy#> .
@prefix dct: <http://purl.org/dc/terms/> .

<> a dh:Item ;
dct:title "Composition" ;
dct:description "Assemble the landing page from content blocks" ;
rdf:_1 <#content> .

<#content> a ldh:XHTML ;
rdf:value """<div xmlns="http://www.w3.org/1999/xhtml">
<p class="lead">Assemble the landing page from content blocks</p>
<p>Everything the app can show is now in place — text, data, charts, views. The landing page is their composition: an ordered sequence of
<a href="../../reference/data-model/blocks/" target="_blank">content blocks</a> on the root document. Two block types exist: <code>ldh:XHTML</code> holds authored markup, and
<code>ldh:Object</code> embeds any other resource — a chart, a view, a document. Anything that is not markup gets wrapped in an object block.</p>
<p>The demo's finished root document interleaves them into an executive dashboard:</p>
<pre>&lt;&gt; a def:Root ;
dct:title "Northwind Traders" ;
rdf:_1 &lt;#page-header&gt; ; # XHTML — title and pitch
rdf:_2 &lt;#overview-intro&gt; ; # XHTML — dashboard intro
rdf:_3 &lt;#sales-trend-block&gt; ; # Object — monthly sales line chart
rdf:_4 &lt;#revenue-by-country-block&gt; ; # Object — geo chart
rdf:_5 &lt;#top-selling-products&gt; ; # Object — product ranking
rdf:_6 &lt;#top-manager-header&gt; ; # XHTML — section heading
rdf:_7 &lt;#top-manager&gt; ; # Object — employee of the quarter
rdf:_8 &lt;#navigation-prompt&gt; ; # XHTML — where to go next
rdf:_9 &lt;#select-children&gt; . # Object — children view</pre>
<p>The narrative rhythm — prose, then evidence, then prose — is an editorial choice, and it is made entirely in data: reordering the page is renumbering <code>rdf:_N</code>. In the browser the
same composition is drag-and-drop in edit mode; from the command line it is the <samp>root.ttl</samp> from the <a href="../hello-dataspace/">first stage</a> grown to its final form, applied
with the same <code>PUT</code>.</p>
<div>
<h2 id="result">What you now see</h2>
<p>The homepage is the finished application: branded header, live charts over the imported graph, and navigation into the containers — every pixel of it a rendering of one document's
description.</p>
<!-- screenshot: the finished Northwind landing page -->
</div>
<p class="lead">Next: <a href="../publish/">Publish</a></p>
</div>"""^^rdf:XMLLiteral .
75 changes: 75 additions & 0 deletions docs/tutorial/data.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
@prefix ldh: <https://w3id.org/atomgraph/linkeddatahub#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dh: <https://www.w3.org/ns/ldt/document-hierarchy#> .
@prefix dct: <http://purl.org/dc/terms/> .

<> a dh:Item ;
dct:title "Data" ;
dct:description "Import CSV data using SPARQL mappings" ;
rdf:_1 <#content> .

<#content> a ldh:XHTML ;
rdf:value """<div xmlns="http://www.w3.org/1999/xhtml">
<p class="lead">Import CSV data using SPARQL mappings</p>
<p>Northwind's data ships as plain CSV files. LinkedDataHub <a href="../../reference/imports/csv/" target="_blank">imports CSV</a> by running a SPARQL <code>CONSTRUCT</code> mapping over each
row: the row's cells are bound as properties of a row resource, and the query builds the RDF you want from them. The mapping for categories, <samp>categories.rq</samp>:</p>
<pre>PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
PREFIX dct: &lt;http://purl.org/dc/terms/&gt;
PREFIX schema: &lt;https://schema.org/&gt;

CONSTRUCT
{
GRAPH ?graph
{
?graph dct:title ?categoryName ;
foaf:primaryTopic ?category .

?category a schema:ProductGroup ;
dct:title ?categoryName ;
schema:name ?categoryName ;
schema:identifier ?categoryID ;
schema:description ?description .
}
}
WHERE
{
?category_row &lt;#categoryID&gt; ?categoryID ;
&lt;#description&gt; ?description ;
&lt;#categoryName&gt; ?categoryName .

BIND(uri(concat(str($base), "categories/")) AS ?container)
BIND(uri(concat(str(?container), encode_for_uri(?categoryID), "/")) AS ?graph)
BIND(uri(concat(str(?graph), "#this")) AS ?category)
}</pre>
<p>The three <code>BIND</code>s carry the whole document model of the import:</p>
<ul>
<li><code>?container</code> — the target container from the <a href="../structure/">Structure</a> stage, resolved against <code>$base</code></li>
<li><code>?graph</code> — one document (named graph) per row, minted inside the container from the row's identifier</li>
<li><code>?category</code> — the document's topic: the document is <em>about</em> the category, so the category is a <samp>#this</samp> fragment of it</li>
</ul>
<div>
<h2 id="browser">In the browser</h2>
<p>Create the import from the UI — upload the CSV file, pick the mapping query and the target container — following the <a href="../../user-guide/import-data/import-csv-data/" target="_blank">Import CSV data</a>
guide.</p>
</div>
<div>
<h2 id="cli">From the command line</h2>
<p>Each import pairs a mapping query with a CSV file and a target container. The demo lists them in a manifest, <samp>imports.csv</samp>:</p>
<pre>query_filename,csv_filename,target,title
categories/categories.rq,categories/categories.csv,categories/,Categories
products/products.rq,products/products.csv,products/,Products
orders/orders.rq,orders/orders.csv,orders/,Orders
...</pre>
<p>and replays the manifest with a small script built on the <a href="../../reference/command-line-interface/" target="_blank">CLI</a>'s <code>create-csv-import.sh</code>:</p>
<pre>./import-csv.sh "$base" "$cert_pem_file" "$cert_password" "$PWD/imports.csv"</pre>
<p>Imports run asynchronously — each one is itself a document that records its status.</p>
</div>
<div>
<h2 id="result">What you now see</h2>
<p>The Categories container lists eight category documents. Open one: the category renders with its name, description and identifier, typed as a product group — with the labels coming from
the <a href="../model/">Model</a> stage. Repeat the pattern for the remaining entities and the Knowledge Graph fills in, orders linking to products, products to suppliers and
categories.</p>
<!-- screenshot: the Categories container listing after the import -->
</div>
<p class="lead">Next: <a href="../media/">Media</a></p>
</div>"""^^rdf:XMLLiteral .
Loading
Loading