Introduction

This tutorial will show you how to develop a linked data application using Callimachus. You will learn how to navigate the Callimachus user interface . As well, you will learn how to use Callimachus resources to develop an application - how to create them and how they work together. Finally, you will learn how to use three Callamachus templates and the underlying Callimachus template language . This working application can be downloaded as meeting-notes.car.

If you have not installed Callimachus yet, please follow the installation instructions in the Getting Started with Callimachus document.

Time Required: About 1 hour

About this tutorial

In this tutorial you will develop an application to help manage meeting notes. Journals are used to store the notes. The notes are identified by the date they were entered combined with the journal they are in.

The notes consist of topics, and topics have a state such as being "open" or "closed" to further discussion.

Part I. Develop the Note class

Overview

In this part you will create a folder to store your application. You will then create a Note class to manage Note resources , and develop three templates to create, view and edit the Notes.

A. Create a root folder for the application

Task

Create a folder for the application.

Instructions

Step Action Notes
1 Using the Callimachus main menu click on the “Home folder” item.
2 Using the create menu click on the folder link. You will be prompted to name the folder.
3 Name the folder. Name it “schema”
4 Press the Create button.

B. Create a Note class

Task

Create a Note class and provide a comment to describe it.

Instructions

Step Action Notes
1 From the folder created previously, such as /schema/ folder.
2 Using the create menu,  click on the Class link. You will be presented with the New Class form.
3 Give the class a Label and Comment.
  • Label: Note   
  • Comment: Used to take notes during or after a meeting.
4 Check the “These resources contain other resources” checkbox. This will allow us to have nested Topics.
5 Press the Create button.

C. Create three templates to manage Notes

Task

Create three initial templates to allow users to create, view and edit Notes.

Instructions

Step Action Notes
1 Navigate to the Note class.
2 Open the Edit tab.
3 Under the Page Templates section, click on each of the three icons and add/save the default template for each. This action does not save the Class resource. Make sure you don't skip Step 4!

Name the corresponding templates as follows:

  • note-create
  • note-view
  • note-edit
4 Click on the Save button to save the class. Result: The Note class will have the three initial templates associated with it.

D. Modify the Note templates

Task

Modify the three Note templates so that the current date is used as the default title for notes.

Modify the note-create template

Modify the default create template code to specify that Notes are the type of resource being created, and that the current date should be the default title for new notes.

Instructions
Step Action Notes
1 Navigate to the Note class, click on the note-create template, it will open in the Edit tab.
2 Specify that Notes are the type of resource being created. See code: note-create v1.1
3 Modify the default input field to accept a date value. See code: note-create v1.2
4 Set the value of the date field to the current date. See code: note-create v1.3
5 Save the template to the server.

Modify the note-view template

Modify the default view template code to show the date as the title.

Instructions
Step Action Notes
1 Modify the page title to show the date. See code: note-view v1.1
2 Save the template to the server.

Modify the note-edit template

Modify the default edit template code to display the date as the title, and to only allow editing the comment.

Instructions
Step Action Notes
1 Modify the title and h1 elements to display the date of the note. See code: note-edit v1.1
2 Remove the input field since the date should not be changed. See code: note-edit v1.2
3 Save the template to the server.

Part II. Develop the Journal class

Overview

Here you will develop a Journal class, which is used to contain related Notes.

A. Create the Journal class

Task

Create a Journal class that contains Note resources.

Instructions

Step Action Notes
1 Create a new class in the schema folder.
  • Label: Journal
  • Comment: Collection of meeting notes
2 Check the “These resources contain other resources” checkbox.
3 Save the class.

B. Create the three initial Journal templates

Task

Create three initial templates for managing Journals.

Instructions

Step Action Notes
1 Navigate to the Journal class, then click on the Edit tab.
2 Add each of the three templates for the class.
  • Create template: Change the contents of title and h1 tags to “New Journal”.
  • View and edit templates: No changes required, the default code is okay.
3 Save each template file  Name them journal-create, journal-view and journal-edit.
4 Save the Journal class. Result: The Journal class will be saved with the three required templates associated with it.

C. Modify the Journal view template

Task

Modify the journal-view template to allow Notes to be created and listed.

Instruction

Step Action Notes
1 Navigate to the Journal class and edit the journal-view template.
2 Create an aside well with a link to create a new Note in this Journal. See code: journal-view v1.1
3 Use the dcterms:isPartOf to list links to notes in this Journal. See code: journal-view v1.2
4 Save the template.

D. Modify the Note create template

Task

Modify the note-create template to make Notes part-of a Journal.

Instructions

Step Action Notes
1 Navigate to the Note class and edit the note-create template.
3 Add the dc:isPartOf relationship to the note-create form and jQuery function. See code: note-create v1.4
4 Save the template.

E. Test the Journal class

Task

Test the Journal class by adding a Note to it.

Instructions

Step Action Notes
1 Create a folder named “resources” in the home folder. The application data is stored in the “resources” folder, separate from the schema folder that stores the application itself.
2 Use the create menu to select the Journal entry
3 Create a new Journal using the create form provided.
  • Label: R&D Journal
  • Save it in the /resources folder.
4 Navigate to the “R&D Journal” you just created in the /resources folder and create a Note in it.
5 Save the note. Notice that you were not prompted to specify a folder to save it in.
6 View the Describe tab. Notice that dcterms:isPartOf relationship is added to the resource.

When creating the Journal resource, be sure to use the create menu "Journal" and not the journal create template link. 


Part III. Develop the Topic class

Overview

In this part you will modify the Note class to make it into a container for Topics.

A. Create a Topic class with its templates

Task

Create a Topic class along with its create, view and edit templates.

Instruction

Step Action Notes
1 Create a Topic class in the /schema/ folder.
  • Label: Topic
  • Comment: Topics discussed in a meeting.
2 Add/save the default templates for creating, viewing and editing Topics. The default templates are fine.
3 Save the Topic class.

B. Edit the note-edit template to contain Topics

Task

Edit the note-edit template to include Topics as a composite resource.

Instruction

Step Action Notes
1 Navigate to and edit the note-edit template.
2 Create a topic-search.rq SPARQL query file. see code: topic-search.rq
3 Create a note.js JavaScript file. see code: note.js_v1
2 Create a field for topics. see code: note-edit v1.3
3 Include the URL to create a new topic. see code: note-edit v1.4
4 Create new topics that don't yet exist see code: note.js_v2
5 Save the template.


Part IV. Record the state of a Topic

Overview

In this part you will create Concepts to populate a drop down field and record the state of a Topic.

A. Create concepts to record the state of a Topic

Task

Create three concepts that record the states a Topic may be in.

Instruction

Step Action Notes
1 Create a folder to store the concepts in. Use the folder name /schema/topic-state
2 Create a concept named “new”. Definition: The topic has not yet been discussed.
3 Create a concept named “open”. Definition: The topic is under discussion.
4 Create a concept named “closed”. Definition: The topic requires no further discussion.

B. Modify the topic-create template

Task

Modify the topic-create template to include a relationship to its state, and then test it by changing the state of a Topic.

Instruction

Step Action Notes
1 Open the topic-create template.
2 Copy suggested label from URL fragment See code: topic-create v1.1
3 Include the namespace for the relationship. See code: topic-create v1.2
4 Add the RDFa markup for the relationship. See code: topic-create v1.3
5 Save the template.

Test

Test the topic-create template by changing the state of a topic.

Step Action Notes
1 Navigate from a Journal to a Note.
2 Add a Topic.
3 Save the Topic and Note
4 View Note Describe Tab Result: The Describe tab will now show the relationship from the Note to the Topic.
5 View Topic Describe tab Observe the meeting:state property from the Topic to the state concept

C. Modify the topic-edit template

Task

Modify the topic-edit template to include a relationship to its state, and then test it by changing the state of a Topic.

Instruction

Step Action Notes
1 Create topic-state-list.rq See code: topic-state-list.rq
2 Open the Topic class and then the topic-edit template.
3 Create the meeting namespace. See code: topic-edit v1.1
4 Add a dropdown field. See code: topic-edit v1.2
5 Save the template.

Test

Test the topic-edit template by changing the state of a Topic.

Step Action Notes
1 Navigate from a Journal to a Note to a Topic.
2 Edit the Topic to change its State.
3 Save the Topic. Result: The Describe tab will now show the relationship from the Topic to selected State concept.

D. Modify the note-view template

Task

In this task you will modify the note-view template to list the topic state.

Instruction

Step Action Notes
1 Open the Note class, then the note-view template.
2 Include the namespace for the relationship. See code: note-view v1.2
3 Include the relationship state in the Topic list. See code: note-view v1.3
4 Display the name of the concept rather than its URL. See code: note-view v1.4
5 Save the template. Congratulations! You have completed your first Callimachus application.

Part V. Conclusion and appendices

Conclusion

Summary of what was learned and concluding remarks go here.

A. Templates by task

The following table contains tasks that involve changes to the templates.

Part Task Related Template Code
A Modify the note-create template
Modify the note-view template
Modify the note-edit template
B Modify the journal-view template
Modify the note-create template
C Edit the note-edit template to contain Topics
D Modify the topic-create template
Modify the topic-edit template
Modify the note-view template

Note: Your file names should not include a version number.


B. Note-create template code

Overview

This shows the development of the note-create template.

note-create v1.1

Description

The contents of the <title> and <h1> elements are updated to specify that the resource is a Note.

Code
<?xml version="1.0" encoding="UTF-8" ?>
<html version="XHTML+RDFa 1.0" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title>New Note</title>
</head>
<body>
    <div class="container">
        <div class="page-header">
            <h1>New Note</h1>
        </div>
        <form role="form" method="POST" action="" enctype="text/turtle" resource="" typeof="" class="row"
                onsubmit="calli.submitTurtle(event,calli.slugify($('#label').val()))">
            <fieldset class="col-sm-4">
                <div class="form-group">
                    <label for="label">Label</label>
                    <input type="text" class="form-control" id="label" value="{rdfs:label}" required="required" autofocus="autofocus"
                                onchange="calli.updateProperty(event, 'rdfs:label')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-success">Create</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

note-create v1.2

Description

The default <input> field is updated to accept a date value and update the onsubmit handler with the new @id of the field.

Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title>New Note</title>
</head>
<body>
    <div class="container">
        <div class="page-header">
            <h1>New Note</h1>
        </div>
        <form method="POST" action="" enctype="text/turtle" resource="" typeof="" class="row"
                onsubmit="calli.submitTurtle(event, $('#datetime').val().replace(/\W/g,''))">
            <fieldset class="col-sm-4">
                <div class="form-group">
                    <label for="datetime">Date</label>
                    <input id="datetime" type="datetime" datatype="xsd:dateTime" value="{dcterms:date}" required="required" class="form-control"
                        onchange="calli.updateProperty(event, 'dcterms:date')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control" autofocus="autofocus"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-success">Create</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

note-create v1.3

Description

The value of the date variable is set to the current date by using a Javascript jQuery function and autofocus on the comment field.

Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title>New Note</title>
    <script type="text/javascript">
    jQuery(function($){
        $('#datetime').val(new Date().toISOString()).change();
    });
    </script>
</head>
<body>
    <div class="container">
        <div class="page-header">
            <h1>New Note</h1>
        </div>
        <form method="POST" action="" enctype="text/turtle" typeof="" resource="" class="row"
                onsubmit="calli.submitTurtle(event, $('#datetime').val().replace(/\W/g,''))">
            <fieldset class="col-sm-4">
                <div class="form-group">
                    <label for="datetime">Date</label>
                    <input id="datetime" type="datetime" datatype="xsd:dateTime" value="{dcterms:date}" required="required" class="form-control"
                        onchange="calli.updateProperty(event, 'dcterms:date')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control" autofocus="autofocus"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-success">Create</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

note-create v1.4

Description

To make a new Note resource part of a Journal resource, the dc:isPartOf relationship is added to the note-create form.

A second jQuery function is added to declare that a Note is in a isPartOf relationship.

Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title>New Note</title>
    <script type="text/javascript">
    jQuery(function($){
        $('#datetime').val(new Date().toISOString()).change();
        $('#isPartOf').append($('<span/>').attr('resource', location.pathname));
    });
    </script>
</head>
<body>
    <div class="container">
        <div class="page-header">
            <h1>New Note</h1>
        </div>
        <form method="POST" action="" enctype="text/turtle" resource="" typeof="" class="row"
                onsubmit="calli.submitTurtle(event, $('#datetime').val().replace(/\W/g,''))">
            <fieldset class="col-sm-4">
                <span id="isPartOf" rel="dcterms:isPartOf">
                    <span resource="?journal" />
                </span>
                <div class="form-group">
                    <label for="datetime">Date</label>
                    <input id="datetime" type="datetime" datatype="xsd:dateTime" value="{dcterms:date}" required="required" class="form-control"
                        onchange="calli.updateProperty(event, 'dcterms:date')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control" autofocus="autofocus"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-success">Create</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>


C. Note-view template code

Overview

This shows the development of the note-view template from v1.1 to v1.4.

note-view v1.1

Description

The date this note was created is shown in the title and h1 tags.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title resource="?this">{dcterms:date}</title>
</head>
<body resource="?this">
    <div class="container">
        <div class="page-header">
            <h1><time datetime="{dcterms:date}" /></h1>
            <script type="text/javascript">
                $('h1 time[datetime]').text(calli.parseDateTime("{dcterms:date}").toLocaleString());
            </script>
        </div>
        <p property="rdfs:comment" />
    </div>
</body>
</html>

note-view v1.2

Description

The skos and meeting namespaces are added.

Code


<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/"
    xmlns:skos="http://www.w3.org/2004/02/skos/core#"
    xmlns:meeting="http://localhost:8080/schema/">
<head>
    <title resource="?this">{dcterms:date}</title>
</head>
<body resource="?this">
    <div class="container">
        <div class="page-header">
            <h1><time datetime="{dcterms:date}" /></h1>
            <script type="text/javascript">
                $('h1 time[datetime]').text(calli.parseDateTime("{dcterms:date}").toLocaleString());
            </script>
        </div>
        <p property="rdfs:comment" />
    </div>
</body>
</html>

note-view v1.3

Description

The relationship state is included in the topic list.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/"
    xmlns:skos="http://www.w3.org/2004/02/skos/core#"
    xmlns:meeting="http://localhost:8080/schema/">
<head>
    <title resource="?this">{dcterms:date}</title>
</head>
<body resource="?this">
    <div class="container">
        <div class="page-header">
            <h1><time datetime="{dcterms:date}" /></h1>
            <script type="text/javascript">
                $('h1 time[datetime]').text(calli.parseDateTime("{dcterms:date}").toLocaleString());
            </script>
        </div>
        <p property="rdfs:comment" />
        <ul>
            <li rel="dcterms:hasPart" resource="?topic">
                <a href="?topic">{rdfs:label}</a>
                <span rel="meeting:state" resource="?state">
                </span>
            </li>
        </ul>
    </div>
</body>
</html>

note-view v1.4

Description

The SKOS definition is used to display the name of the Concept.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/"
    xmlns:skos="http://www.w3.org/2004/02/skos/core#"
    xmlns:meeting="http://localhost:8080/schema/">
<head>
    <title resource="?this">{dcterms:date}</title>
</head>
<body resource="?this">
    <div class="container">
        <div class="page-header">
            <h1><time datetime="{dcterms:date}" /></h1>
            <script type="text/javascript">
                $('h1 time[datetime]').text(calli.parseDateTime("{dcterms:date}").toLocaleString());
            </script>
        </div>
        <p property="rdfs:comment" />
        <ul>
            <li rel="dcterms:hasPart" resource="?topic">
                <a href="?topic">{rdfs:label}</a>
                <span rel="meeting:state" resource="?state">
                    [<span title="{skos:definition}">
                        {skos:prefLabel}
                    </span>]
                </span>
            </li>
        </ul>
    </div>
</body>
</html>


D. Note-edit template code

Overview

This shows the progression of the note-edit template.

note-edit v1.1

Description

The title and h1 elements are modified to display the date of the note.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title resource="?this">{dcterms:date}</title>
</head>
<body resource="?this" onload="comparison=calli.copyResourceData('#form')">
    <div class="container">
        <div class="page-header">
            <h1><time datetime="{dcterms:date}" /></h1>
            <script type="text/javascript">
                $('h1 time[datetime]').text(calli.parseDateTime("{dcterms:date}").toLocaleString());
            </script>
        </div>
        <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" class="row"
                onsubmit="calli.submitUpdate(comparison,event)">
            <fieldset class="col-sm-4">
                <div class="form-group">
                    <label for="label">Label</label>
                    <input type="text" class="form-control" id="label" value="{rdfs:label}" required="required"
                        onchange="calli.updateProperty(event, 'rdfs:label')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Save</button>
                    <button type="button" class="btn btn-default" onclick="location.replace('?view')">Cancel</button>
            		<button type="button" class="btn btn-danger" onclick="calli.deleteResource(event)">Delete</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

note-edit v1.2

Description

The input field is removed since the date should not be changed.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title resource="?this">{dcterms:date}</title>
</head>
<body resource="?this" onload="comparison=calli.copyResourceData('#form')">
    <div class="container">
        <div class="page-header">
            <h1><time datetime="{dcterms:date}" /></h1>
            <script type="text/javascript">
                $('h1 time[datetime]').text(calli.parseDateTime("{dcterms:date}").toLocaleString());
            </script>
        </div>
        <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" class="row"
                onsubmit="calli.submitUpdate(comparison,event)">
            <fieldset class="col-sm-6">
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Save</button>
                    <button type="button" class="btn btn-default" onclick="location.replace('?view')">Cancel</button>
            		<button type="button" class="btn btn-danger" onclick="calli.deleteResource(event)">Delete</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

Topic Search Query

A Named RDF Query is required to to implement the autocomplete feature of the topic field.


# topic-search.rq
#
# @Cache-Control: no-store
#
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX meeting: <http://localhost:8080/schema/>

SELECT ?resource ?label {
    ?resource a <Topic>; rdfs:label ?label
    {
        ?resource meeting:state <topic-state/new>
    } UNION {
        ?resource meeting:state <topic-state/open>
    }
    FILTER regex(?label, "$q")
} ORDER BY ?label LIMIT 10

Topic Field Script v1

The autocomplete topic field will used selectize.js to render the suggestions using the results from the above query. Selectize.js is included in every Callimachus page (by default) and including it explicitly is not necessary. Rather then using an embedded URL for the query, which are resolved against the current page URL, the query URL is read from the template (and relative to the template URL and not the note page).


// note.js

jQuery(function($){
    $('#topics').selectize({
        load: function(query, callback) {
            var url = $('#topic-search').prop('href').replace('{q}', encodeURIComponent(query));
            calli.getJSON(url).then(function(json){
                return json.results.bindings.map(function(bindings){
                    return {
                        value: bindings.resource.value,
                        text: bindings.label.value
                    };
                });
            }).then(callback, function(error){
                callback();
                return calli.error(error);
            });
        }
    });
});

note-edit v1.3

Description

The above script is included and the URL for the query is placed in the template header. The query URL is placed in the template using a relative URL. Callimachus will rewrite this @href to be absolute, so the URI of the node will not effect the location.

A select field is created for topics that includes the existing values, already selected.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title resource="?this">{dcterms:date}</title>
    <link id="topic-search" href="topic-search.rq?results&amp;tqx=out:sparql-json&amp;q={q}" />
    <script type="text/javascript" src="note.js"></script>
</head>
<body resource="?this" onload="comparison=calli.copyResourceData('#form')">
    <div class="container">
        <div class="page-header">
            <h1><time datetime="{dcterms:date}" /></h1>
            <script type="text/javascript">
                $('h1 time[datetime]').text(calli.parseDateTime("{dcterms:date}").toLocaleString());
            </script>
        </div>
        <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" class="row"
                onsubmit="calli.submitUpdate(comparison,event)">
            <fieldset class="col-sm-6">
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <label for="topics">Topics</label>
                    <select id="topics" class="form-control" multiple="multiple"
                            onchange="calli.updateResource(event,'dcterms:hasPart')">
                        <option selected="selected" rel="dcterms:hasPart" resource="?topic" value="{?topic}">{rdfs:label}</option>
                    </select>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Save</button>
                    <button type="button" class="btn btn-default" onclick="location.replace('?view')">Cancel</button>
            		<button type="button" class="btn btn-danger" onclick="calli.deleteResource(event)">Delete</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

note-edit v1.4

Description

Include the URL to create a new topic in the header, for use by the script below. This is placed in the template, so that it is resolved relative to the template and not the note edit page location.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title resource="?this">{dcterms:date}</title>
    <link id="topic" href="Topic" />
    <link id="topic-search" href="topic-search.rq?results&amp;tqx=out:sparql-json&amp;q={q}" />
    <script type="text/javascript" src="note.js"></script>
</head>
<body resource="?this" onload="comparison=calli.copyResourceData('#form')">
    <div class="container">
        <div class="page-header">
            <h1><time datetime="{dcterms:date}" /></h1>
            <script type="text/javascript">
                $('h1 time[datetime]').text(calli.parseDateTime("{dcterms:date}").toLocaleString());
            </script>
        </div>
        <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" class="row"
                onsubmit="calli.submitUpdate(comparison,event)">
            <fieldset class="col-sm-6">
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <label for="topics">Topics</label>
                    <select id="topics" class="form-control" multiple="multiple"
                            onchange="calli.updateResource(event,'dcterms:hasPart')">
                        <option selected="selected" rel="dcterms:hasPart" resource="?topic" value="{?topic}">{rdfs:label}</option>
                    </select>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Save</button>
                    <button type="button" class="btn btn-default" onclick="location.replace('?view')">Cancel</button>
            		<button type="button" class="btn btn-danger" onclick="calli.deleteResource(event)">Delete</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

Topic Field Script v2

By including a create function option in selectize.js initializer, one can call calli.createResource to bring up the create form in a dialogue.


// note.js

jQuery(function($){
    $('#topics').selectize({
        load: function(query, callback) {
            var url = $('#topic-search').prop('href').replace('{q}', encodeURIComponent(query));
            calli.getJSON(url).then(function(json){
                return json.results.bindings.map(function(bindings){
                    return {
                        value: bindings.resource.value,
                        text: bindings.label.value
                    };
                });
            }).then(callback, function(error){
                callback();
                return calli.error(error);
            });
        },
        create: function(label, callback) {
            var url = window.location.pathname + '/' + calli.slugify(label);
            calli.headText(url).then(function(){
                return url; // already exists
            }, function(xhr) {
                if (xhr.status != 404) return calli.reject(xhr);
                return calli.createResource('#topics', '?create=' + encodeURIComponent($('#topic').prop('href')) + '#' + encodeURIComponent(label));
            }).then(function(resource){
                return resource && {
                    value: resource,
                    text: resource.replace(/.*\//,'')
                };
            }).then(callback, function(error){
                callback();
                return calli.error(error);
            });
        }
    });
});

E. Journal-view template code

Overview

Here is the development of the journal-view template.

journal-view v1.1

Description

A link is added to create a new Note in a Journal. Boostrap grid is used to position the link on the right hand side of the page.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title resource="?this">{rdfs:label}</title>
</head>
<body resource="?this">
    <div class="container">
        <div class="page-header">
            <h1 property="rdfs:label" />
        </div>
        <div class="row">
            <div class="col-sm-8">
                <p property="rdfs:comment" />
            </div>
            <div class="col-sm-4">
                <aside class="well well-sm">
                    <p class="lead">
                        <a resource="Note" href="Note" onclick="href='?create='+encodeURIComponent(getAttribute('resource'))">Create a new note</a>
                    </p>
                </aside>
            </div>
        </div>
    </div>
</body>
</html>

journal-view v1.2

Description

An unordered list is added in order to create new Notes in a Journal.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
	<title resource="?this">{rdfs:label}</title>
</head>
<body resource="?this">
    <div class="container">
        <div class="page-header">
            <h1 property="rdfs:label" />
        </div>
        <div class="row">
            <div class="col-sm-8">
                <p property="rdfs:comment" />
                <ul>
                    <li rev="dcterms:isPartOf" resource="?note">
                        <a href="?note">
                            <time datetime="{dcterms:date}" />
                        </a>
                    </li>
                </ul>
                <script type="text/javascript">
                    $('li time[datetime]').text(function(){
                        return calli.parseDateTime(this).toLocaleString();
                    });
                </script>
            </div>
            <div class="col-sm-4">
                <aside class="well well-sm">
                    <p class="lead">
                        <a resource="Note" href="Note" onclick="href='?create='+encodeURIComponent(getAttribute('resource'))">Create a new note</a>
                    </p>
                </aside>
            </div>
        </div>
    </div>
</body>
</html>


F. Topic-create template code

Overview

This shows the development of the topic-create template from v1.1 to v1.3.

topic-create v1.1

Description

The title and h1 tags are updated to name the resource being created - a topic. Increase the width of the column, since it will be opened in a dialogue. Copy suggested label from URL fragment to pre-populate label field.

Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/">
<head>
    <title>New Topic</title>
    <script type="text/javascript">
        jQuery(function($){
            $('#label').val(decodeURIComponent(window.location.hash.substring(1))).change();
        });
    </script>
</head>
<body>
    <div class="container">
        <div class="page-header">
            <h1>New Topic</h1>
        </div>
        <form method="POST" action="" enctype="text/turtle" resource="" typeof="" class="row"
                onsubmit="calli.submitTurtle(event, calli.slugify($('#label').val()))">
            <fieldset class="col-sm-6">
                <div class="form-group">
                    <label for="label">Label</label>
                    <input type="text" id="label" value="{rdfs:label}" class="form-control" required="required" autofocus="autofocus"
                            onchange="calli.updateProperty(event, 'rdfs:label')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                            onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Add</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

topic-create v1.2

Description

The namespace for the meeting application is added.

Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/"
    xmlns:meeting="http://localhost:8080/schema/">
<head>
    <title>New Topic</title>
    <script type="text/javascript">
        jQuery(function($){
            $('#label').val(decodeURIComponent(window.location.hash.substring(1))).change();
        });
    </script>
</head>
<body>
    <div class="container">
        <div class="page-header">
            <h1>New Topic</h1>
        </div>
        <form method="POST" action="" enctype="text/turtle" resource="" typeof="" class="row"
                onsubmit="calli.submitTurtle(event, calli.slugify($('#label').val()))">
            <fieldset class="col-sm-6">
                <div class="form-group">
                    <label for="label">Label</label>
                    <input type="text" id="label" value="{rdfs:label}" class="form-control" required="required" autofocus="autofocus"
                            onchange="calli.updateProperty(event, 'rdfs:label')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                            onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Add</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

topic-create v1.3

Description

The default state for a topic is added using a span with @rel="meeting:state"

Code
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:dcterms="http://purl.org/dc/terms/"
    xmlns:meeting="http://localhost:8080/schema/">
<head>
    <title>New Topic</title>
    <script type="text/javascript">
        jQuery(function($){
            $('#label').val(decodeURIComponent(window.location.hash.substring(1))).change();
        });
    </script>
</head>
<body>
    <div class="container">
        <div class="page-header">
            <h1>New Topic</h1>
        </div>
        <form method="POST" action="" enctype="text/turtle" resource="" typeof="" class="row"
                onsubmit="calli.submitTurtle(event, calli.slugify($('#label').val()))">
            <fieldset class="col-sm-6">
                <span rel="meeting:state" resource="topic-state/new" />
                <div class="form-group">
                    <label for="label">Label</label>
                    <input type="text" id="label" value="{rdfs:label}" class="form-control" required="required" autofocus="autofocus"
                            onchange="calli.updateProperty(event, 'rdfs:label')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                            onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Add</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>


G. Topic-edit template code

Overview

This shows the development of the topic-edit template from v1.1 to v1.2.

List of Possible Topic States Query

The query below returns a list of states available to a topic. This query will be used to populate a drop down in the topic edit form.

The relationship for a folder to its members is cali.hasComponent. Concepts should be displayed using the skos:prefLabel property.


# topic-state-list.rq
#
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX calli: <http://callimachusproject.org/rdf/2009/framework#>

SELECT ?resource ?label {
    <topic-state/> calli:hasComponent ?resource .
    ?resource skos:prefLabel ?label
} ORDER BY ?label

topic-edit v1.1

Description

Use your own relationship namespace term, such as xmlns:meeting.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:skos="http://www.w3.org/2004/02/skos/core#"
    xmlns:dcterms="http://purl.org/dc/terms/"
    xmlns:meeting="http://localhost:8080/schema/">
<head>
    <title resource="?this">{rdfs:label}</title>
</head>
<body resource="?this" onload="comparison=calli.copyResourceData('#form')">
    <div class="container">
        <div class="page-header">
            <h1 property="rdfs:label" />
        </div>
        <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" class="row"
                onsubmit="calli.submitUpdate(comparison,event)">
            <fieldset class="col-sm-4">
                <div class="form-group">
                    <label for="label">Label</label>
                    <input type="text" id="label" value="{rdfs:label}" class="form-control" required="required"
                        onchange="calli.updateProperty(event, 'rdfs:label')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Save</button>
                    <button type="button" class="btn btn-default" onclick="location.replace('?view')">Cancel</button>
                    <button type="button" class="btn btn-danger" onclick="calli.deleteResource(event)">Delete</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>

topic-edit v1.2

Description

Add a dropdown field to select the state of a topic. It will display the available states by listing all the concepts in the folder created earlier. The pragma ?select of RDF Queries will return a select element populated with the query result set.

Code

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:skos="http://www.w3.org/2004/02/skos/core#"
    xmlns:dcterms="http://purl.org/dc/terms/"
    xmlns:meeting="http://localhost:8080/schema/">
<head>
    <title resource="?this">{rdfs:label}</title>
</head>
<body resource="?this" onload="comparison=calli.copyResourceData('#form')">
    <div class="container">
        <div class="page-header">
            <h1 property="rdfs:label" />
        </div>
        <form id="form" method="POST" action="" enctype="application/sparql-update" resource="?this" class="row"
                onsubmit="calli.submitUpdate(comparison,event)">
            <fieldset class="col-sm-4">
                <div class="form-group">
                    <label for="label">Label</label>
                    <input type="text" id="label" value="{rdfs:label}" class="form-control" required="required"
                        onchange="calli.updateProperty(event, 'rdfs:label')" />
                </div>
                <div class="form-group">
                    <label for="comment">Comment</label>
                    <textarea id="comment" class="form-control"
                        onchange="calli.updateProperty(event, 'rdfs:comment')">{rdfs:comment}</textarea>
                </div>
                <div class="form-group">
                    <label for="state" class="control-label">State</label>
                    <xi:include href="topic-state-list.rq?select&amp;rel=meeting:state&amp;id=state" />
                    <div rel="meeting:state" resource="?state" />
                    <script type="text/javascript">
                        $('div[rel="meeting:state"]').filter(calli.selectEachResourceIn('#state')).remove();
                    </script>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Save</button>
                    <button type="button" class="btn btn-default" onclick="location.replace('?view')">Cancel</button>
                    <button type="button" class="btn btn-danger" onclick="calli.deleteResource(event)">Delete</button>
                </div>
            </fieldset>
        </form>
    </div>
</body>
</html>


H. Callimachus Support

3 Round Stones offers commercial support and private virtual cloud hosting for enterprises running Callimachus.

Commuity support may be access through our mailing list.