Tutorial

In this tutorial we will create a simple blog using Kamra CMS. We won't need to write any Java code, we'll be using the built in functionality of the CMS system to define the BlogEntry content type and create standard views and layouts.

Define the BlogEntry object type

A newly created Kamra instance has no object types defined. 

  1. Browse to http://localhost:8080/admin
  2. Click "Configuration"
  3. You should see a single configuration called "Initial". Click the "Edit" button. The page shows the initial configuration with two layouts (Site and FrontPage) and nothing else.
  4. Click "Create" next to "Object types"
  5. Copy the following XML into the editor window and click "Save".
<entity name="BlogEntry" type="CONTENT">
<capability checks="Public" name="VIEW"/>
<capability checks="Admin Owner" name="REMOVE"/>
<capability checks="Admin" name="PUBLISH"/>
<facet name="Summary">
<panel component="ContentLinkLabel"/>
<panel component="HtmlLabel" property="description"/>
</facet>
<facet name="Details">
<panel component="TitleLabel"/>
<div class="inlined pull-right">
<panel component="SmartDateTimeLabel" property="time"/>
<panel component="PersonLabel"/>
</div>
<panel class="lead" component="HtmlLabel" property="description" translated="true"/>
<panel class="body" component="HtmlLabel" property="body" translated="true"/>
<panel component="TagLabel" property="tags"/>
<link links="PersistentEditLink PersistentDeleteLink" linkClass="btn btn-default"/>
</facet>
<facet name="Editor">
<textfield property="title" required="true"/>
<richtexteditor property="description" required="true" />
<richtexteditor property="body" required="true"/>
<panel class="tags" component="TagSelector"/>
<datefield property="time"/>
</facet>
</entity>

This file defines a new object type. Let's dissect the XML line by line:

<entity name="BlogEntry" type="CONTENT">

We give the entity a name and tell Kamra it is going to be a content object. This type defines which database table holds objects of this type in the Kamra database.

<capability checks="Public" name="VIEW"/>
<capability checks="Admin Owner" name="REMOVE"/>
<capability checks="Admin" name="PUBLISH"/>

We need to define who can access (view), create (publish) and delete (remove) instances of this object type. The access definition is written in a boolean logic conditional dsl used throught Kamra. 

Next we define 3 different facets - UI structures for different purposes that a Blog entry can be presented in: a summary view, a full detail view, and an editor view.

<facet name="Summary">
<panel component="ContentLinkLabel"/>
<panel component="HtmlLabel" property="description"/>
</facet>

The summary view is represented as  a link to the content page with the title, and the description of the blog entry. All labels between hashmarks (#)show a missing localization that you can later add to the portal:

 <facet name="Details">
<panel component="TitleLabel"/>
<div class="inlined pull-right">
<panel component="SmartDateTimeLabel" property="time"/>
<panel component="PersonLabel"/>
</div>
<panel class="lead" component="HtmlLabel" property="description" translated="true"/>
<panel class="body" component="HtmlLabel" property="body" translated="true"/>
<panel component="TagLabel" property="tags"/>
<link links="PersistentEditLink PersistentDeleteLink" linkClass="btn btn-default"/>
</facet>

The full detail view shows the title, the date the entry was published at, the user who published it, the description and the body of the blog entry, then a list of tags associated with the entry, some links to edit and delete.

 <facet name="Editor">
<textfield property="title" required="true"/>
<richtexteditor property="description" required="true" />
<richtexteditor property="body" required="true"/>
<panel component="TagSelector"/>
<datefield property="time"/>
</facet>

The editor view lets a user edit the title, description and body fields, the latter two become WYSIWYG editors. It also adds a tag selector component, a date and time editor to edit the time field, and an image selector component.

After copying the whole XML structure into the editor, click Save. You will return to the configuration editor and notice two changes: the BlogEntry object type will appear under the object types and a "New entity: BlogEntry" item will appear in the change tracker panel.

Test the object type

Our changes to the configuration are only active in our own browser session, they only exist in the server's memory. But we can still test them without persisting the changes anywhere. Without closing the browser, open a new tab or window and browse to the following URL: 

http://localhost:8080/content/edit?class=BlogEntry

Exercise: open an incognito browser tab and try the same url there. It will open in a new session which is not associated with the changes you made, so you wil see an error message instead.

In the same browser instance you should see an editor similar to this one:

Try saving the form without entering anything - you should see error messages indicating there are empty required fields. Add values to each required field to save the blog entry. You should get redirected to a content page showing the full detail view of the blog entry.

Note: when the editor appears the URL of the page changes to one showing a numeric id. This happens because when you open a content edit screen, the system first saves a draft blog entry, and redirects your browser to edit the draft with the specifid id. Every 30 seconds drafts are automatically saved into the database and in case of a browser crash you can return to the last auto-saved state of the blog entry. Non published auto-drafts are removed after 24 hours of inactivity from the database.