Skip to content

Tutorial Walkthrough

Julian Rojas edited this page Oct 25, 2019 · 1 revision

Tutorial walkthrough

This is a tutorial on how to build a simple Web app using the LDflex as a query language to extract data from distributed RDF Knowledge Graphs.

Concretely, this tutorial shows how to build a Solid/FOAF profile viewer in React using the LDflex React Components.

The final version of the profile viewer can be found on [TODO: add gh-pages link](some link), and the full source code is available at https://github.com/julianrojas87/Tutorial-ISWC2019-LDflex-on-React.

This tutorial was inspired by the Profile Viewer app but here we also show how to create your own LDflex-based React Components.

Requirements

You need the following tools:

  • git
  • Node.js (version 10 or higher)
  • Any kind of text editor that support JavaScript files.
  • Any modern browser.

Steps

  1. Creating a React app
  2. Viewing a profile
  3. Linking friends
  4. Custom LDflex Components

1. Creating a React app

Initializing a React project is very easy. Assuming you have Node.js installed, you can execute the following command:

npx create-react-app profile-viewer-ldflex

This will create an npm project in the profile-viewer-ldflex directory with all the required dependencies.

After that, you can enter the directory and start a live development Web server to look at the newly initialized app:

cd profile-viewer-ldflex
npm start 

This should open a new tab in your browser for http://localhost:3000/. If you see a spinning React icon, then everything is working as expected.

2. Viewing a profile

In this part of the tutorial we will create a basic visualization containing data from a FOAF or Solid profile on the Web. The data will be obtained through LDflex queries executed through existing React Components.

2.1 Structure and style

First, let's setup the basic structure for visualizing the data of a profile. For this you can replace all the content of src/App.js with the following code:

import React from 'react';
import './App.css';

class App extends React.Component {

  render() {
    return (
      <div>
        <h1>Profile viewer</h1>
        <p>
          <label htmlFor="profile">Profile:</label>
          <input id="profile"/>
          <button>View</button>
        </p>
      </div>
    );
  }
}

export default App;

Next let's add some basic styling. Copy/paste the following into the src/App.css file:

body {
  max-width: 800px;
  margin: 0 auto;
}

body, input, button {
  font: 11pt/1.3 "Helvetiva Neue", Helvetica, Arial, sans-serif;
}

button, label {
  font-weight: bold;
}
button, input {
  margin-left: 1ex;
  margin-bottom: 1ex;
}

#profile {
  width: 400px;
}

li button {
  border: none;
  background: none;
  padding: 0;
  color: #0d1b9b;
  cursor: pointer;
  text-decoration: underline;
}

li button:hover {
  color: #9b79fc;
}

.profile-img {
  border: 2px solid orange;
  border-radius: 3px;
  padding: 7px;
  width: 10%;
}

2.2 State handling parameters

Since we will allow the users to manually input the URI of the profile to be queried, we need to keep track of it. Let's add the following code to the src/App.js file:

class App extends React.Component {

  state = {
    profile: '',
    renderProfile: false
  };

  viewProfile(profile) {
    this.setState({ profile: profile, renderProfile: true });
  }

  render() {
    const { profile, renderProfile } = this.state;
    return (
      <div>
        <h1>Profile viewer</h1>
        <p>
          <label htmlFor="profile">Profile:</label>
          <input id="profile" value={profile} onChange={e => this.setState({ profile: e.target.value })} />
          <button onClick={() => this.viewProfile(profile)}>View</button>
        </p>
      </div>
    );
  }
}

2.3 LDflex React Components

The next step is to query and visualize some basic data from a FOAF or Solid profile on the Web using LDflex. For this we will reuse the LDflex for Solid React Components, which we can install using the following command:

npm install @solid/react

Once installed, let's import the Components that we will use for this application. Add the following code to your src/App.js file:

import { Value, Image, List } from '@solid/react';

Now, let's use the Image and Value components to visualize (if available) the profile picture and the name from a given profile through LDflex path expression queries. Add the following code to the render() function of your src/App.js script:

...
  render() {
    const { profile, renderProfile } = this.state;
    return (
      <div>
        <h1>Profile viewer</h1>
        <p>
          <label htmlFor="profile">Profile:</label>
          <input id="profile" value={profile} onChange={e => this.setState({ profile: e.target.value })} />
          <button onClick={() => this.viewProfile(profile)}>View</button>
        </p>
	    {renderProfile && 
          <div>
            <p>
              <Image className="profile-img" src={`[${profile}][foaf:img]`} />
              <br />
              <label htmlFor="name">Name: </label>
              <span id="name">
                <Value src={`[${profile}][foaf:name]`} />
              </span>
            </p>
          </div>
        }
      </div>
    );
  }

As you can see above, we use the path expressions [profile_URI][foaf:img] and [profile_URI][foaf:name] to define the profile picture and name LDflex queries respectively. As forprofile_URI we use the value stored in the profile state parameter.

Now you can run npm start again and enter the URI of a FOAF or Solid profile (e.g. https://julianrojas.org/#me) to see it working.

3. Linking friends

In this step we will make use of the List React component which allow us to perform LDflex queries that return lists of values and visualize them. Let's add the following code to to the render() function of your src/App.js script:

...
  render() {
    ...
    {renderProfile && 
     <div>
         <p>
             <Image className="profile-img" src={`[${profile}][foaf:img]`} />
             <br />
             <label htmlFor="name">Name: </label>
             <span id="name">
                 <Value src={`[${profile}][foaf:name]`} />
             </span>
             <br />
             <label htmlFor="friends">Friends: </label>
         </p>
         <List src={`[${profile}][foaf:knows]`}>{friend =>
         	<li key={friend}>
             	<Image className="profile-img" src={`[${friend}][foaf:img]`} />
             	<br/>
             	<label>Name: </label>
             	<button onClick={() => this.viewProfile(friend)}>
                	<Value src={`[${friend}].name`}>{`${friend}`}</Value>
             	</button>
        	</li>}
         </List>
     </div>
    }
    ...

As you can see in the code above, in this step we are performing three different queries:

  • [profile_URI][foaf:knows] to query for the list of friends of the given profile.
  • [friend_URI][foaf:img] to query for the profile pictures of every linked friend.
  • [friend_URI][foaf:name] to query for the name of every linked friend.

Inside the List component we perform further LDflex queries to visualize more details (profile pic and name) of every linked friend.

4. Custom LDflex Components

Lastly we will show how can we create our own LDflex React Components. For this example we will define a new Component called Email that allows to query for the foaf:mbox of a profile and visualize it as a html anchor tag.

4.1 Creating a new Component

First let's create a new file in the root src folder called Email.jsx with the following command:

touch src/Email.jsx

Now add the following content to it:

import React from 'react';
import { useLDflexValue } from '@solid/react';

/** Displays an anchor with proper email reference. */
export default function Email({ src, defaultSrc, children = null, ...props }) {
  src = useLDflexValue(src) || defaultSrc;
  let href = `${src}`.startsWith('mailto:') ? src : `mailto:${src}`;
  return src ? <a href={`${href}`}>{`${src}`}</a> : children;
}

This Component uses the useLDflexValue React Hook to execute a LDflex path query that expects a single value as a result (See other available Hooks). Once the query has been resolved, it returns an anchor tag assigning the proper href property.

4.2 Using the new Component

Finally let's use our new Component. The first step is to import it into the main App function:

import Email from './Email';

Now, let's add the following code to the src/App.js file to use the Component within the profile visualization:

...
  render() {
    ...
    {renderProfile && 
     <div>
         <p>
             ...
             <br />
             <label htmlFor="email">Email: </label>
             <span id="email">
             	<Email src={`[${profile}][foaf:mbox]`} />
             </span>
             <br />
             <label htmlFor="friends">Friends: </label>
         </p>
         <List src={`[${profile}][foaf:knows]`}>{friend =>
         	<li key={friend}>
             	<Image className="profile-img" src={`[${friend}][foaf:img]`} />
                <br/>
             	<button onClick={() => this.viewProfile(friend)}>
                	<Value src={`[${friend}].name`}>{`${friend}`}</Value>
             	</button>
                <br />
                <label>Email: </label>
                <Email src={`[${friend}][foaf:mbox]`} />
        	</li>}
         </List>
     </div>
    }
    ...

Note that we added the Email component to query for the foaf:mbox of the main profile and also for its friends.