State
Authoring state
Content Element Edit
component has the ability to emit the data
object that needs to be stored by the Tailor CMS
; which is later on used to render Display
component. This is achived by emitting the save
event. The emitted data
is stored on the ContentElement
entity under the same key. Here is a Content Element Edit
Counter component from the Example section, displaying the amount of times user clicked on a button:
<template>
<div>
<div>Times clicked: {{ element.data.count }}</div>
<button @click="increment">Increment</button>
</div>
</template>
<script setup lang="ts">
import { Element } from 'tce-manifest';
const props = defineProps<{ element: Element }>();
const emit = defineEmits(['save']);
const increment = () => {
const { data } = props.element;
const count = data.count + 1;
emit('save', { ...data, count });
};
</script>
<template>
<div>
<div>Times clicked: {{ element.data.count }}</div>
<button @click="increment">Increment</button>
</div>
</template>
<script setup lang="ts">
import { Element } from 'tce-manifest';
const props = defineProps<{ element: Element }>();
const emit = defineEmits(['save']);
const increment = () => {
const { data } = props.element;
const count = data.count + 1;
emit('save', { ...data, count });
};
</script>
Initializing the state
By emitting the save
event, count
value is stored alongside other data in the element.data
key-value property bag.
What about the first time Edit
component gets rendered? count
does not exist on the data
object and data.count
will return undefined. That is where initState
function kicks in. Each Content Element package exposes initState
function, which is called upon adding a new Content Element
. As name suggests, the goal of initState
function is to properly initialize data
field of respective element. To support our data structure, we would define initState
as:
const initState = () => ({ count: 0 })
const initState = () => ({ count: 0 })
data.assets
property
By inspecting the data
property of some of the Tailor core Content Elements, you might run into data.assets
object, containing something like:
{
assets: {
'url': 'repository://assets/sample_pdf.jpeg',
'aux.cover': 'repository://assets/cover.jpeg'
}
}
{
assets: {
'url': 'repository://assets/sample_pdf.jpeg',
'aux.cover': 'repository://assets/cover.jpeg'
}
}
data.assets
is a special key-value dictionary which is used to declare all authored static assets (e.g. uploaded image or attached file). The key denotes the location within the data
property bag where the value needs to be injected. Value should be the URL
or the uploaded entity.
To securely deliver assets at scale, there is a mechanism in place which generates access token, making assets accessible for a limited amount of time. The key will be used to denote key within the data
object if value is a local url (denoted with repository://
prefix) file URL will be resolved and signed with a short lived token. For the example above, after entity has been fetched, data
property will have following structure:
{
url: 'https://s3.amazon.com/my_bucket.......'
aux: {
cover: 'https://s3.amazon.com/my_bucket.......'
}
assets: {
'url': 'repository://assets/sample_pdf.jpeg',
'aux.cover': 'repository://assets/cover.jpeg'
}
}
{
url: 'https://s3.amazon.com/my_bucket.......'
aux: {
cover: 'https://s3.amazon.com/my_bucket.......'
}
assets: {
'url': 'repository://assets/sample_pdf.jpeg',
'aux.cover': 'repository://assets/cover.jpeg'
}
}
For more details on developing Edit
components and Content Element
manifest specification, please visit dedicated sections within the documentation.
Server entity
Content Element Kit fully replicates Tailor CMS
Content Element model to ensure consistency and compatibility. The same ORM
is used to instantiate entities on the backend (Sequalize.js
), and compatible mechanism is implemented to hydrate front-end component in case of changes.
interface ContentElement {
// Current primary id
id: number;
// Future primary id
uid: string;
// Repository is a top level grouping entity within the Tailor CMS, it usually
// maps to a Course concept, but it can be different thing depending on the
// learning pedagogy and intended use.
repositoryId: number;
// Activities are structural groupings within a repository. As an example,
// Within a 'Course' repository, 'Activities' can be used to create 'Modules',
// 'Pages', 'Sections' and other structures to segment the Learning
// activities. They usually have hierarchical structure.
activityId: number;
// Type is a unique, reserved string, denoting 'Content Element' type id.
// Each Content Element defines unique type id within the Tailor CMS which is
// used to resolve which components needs to be used to handle specific
// Content Element instance. The external types should follow 'ORG/TYPE'
// convention.
type: string;
// Elements are placed within a container, which can be a standard container
// or a custom container. Great example of a standard container is
// a simple Page. Sometimes there is a need to create a custom one, like
// Exam, hosting Assessment Content Elements. The position
// property is used to order elements within a container.
position: number;
// Data is a JSON field exposed to the element creator for data storage. Each
// Element defines its own data structure. For more details see manifest and
// Edit package documentation.
data: ElementData;
// Tailor CMS has concept of configurable metadata. Each Content Element, in
// addition to its custom developed behaviour can be extended with a field
// configuration, enabling additional inputs. Let's use image Content Element
// as an example. One might add configuration to require 'Alt text' metadata
// input field. Without coding this functionality, Tailor CMS will add input
// for 'Alt text' in the 'Content Element' sidebar once element is selected.
// For more details see Tailor documentation.
meta: { [key: string]: any };
// In Tailor CMS, it is possible to configure relationships between
// the Content Elements. These references are stored within refs property.
refs: { [key: string]: any };
// Future functionality support
linked: boolean;
// Boolean for marking elements for which parent structural item has been
// deleted
detached: boolean;
// Unique element uid, persisted upon creating the element copy
contentId: string;
// SHA-1 of 'data' value, uniquely identifying the Content Element data
contentSignature: string;
// Date element got created
createdAt: string;
// Date element got last updated
updatedAt: string;
// Date element got deleted
deletedAt: string | null;
}
interface ContentElement {
// Current primary id
id: number;
// Future primary id
uid: string;
// Repository is a top level grouping entity within the Tailor CMS, it usually
// maps to a Course concept, but it can be different thing depending on the
// learning pedagogy and intended use.
repositoryId: number;
// Activities are structural groupings within a repository. As an example,
// Within a 'Course' repository, 'Activities' can be used to create 'Modules',
// 'Pages', 'Sections' and other structures to segment the Learning
// activities. They usually have hierarchical structure.
activityId: number;
// Type is a unique, reserved string, denoting 'Content Element' type id.
// Each Content Element defines unique type id within the Tailor CMS which is
// used to resolve which components needs to be used to handle specific
// Content Element instance. The external types should follow 'ORG/TYPE'
// convention.
type: string;
// Elements are placed within a container, which can be a standard container
// or a custom container. Great example of a standard container is
// a simple Page. Sometimes there is a need to create a custom one, like
// Exam, hosting Assessment Content Elements. The position
// property is used to order elements within a container.
position: number;
// Data is a JSON field exposed to the element creator for data storage. Each
// Element defines its own data structure. For more details see manifest and
// Edit package documentation.
data: ElementData;
// Tailor CMS has concept of configurable metadata. Each Content Element, in
// addition to its custom developed behaviour can be extended with a field
// configuration, enabling additional inputs. Let's use image Content Element
// as an example. One might add configuration to require 'Alt text' metadata
// input field. Without coding this functionality, Tailor CMS will add input
// for 'Alt text' in the 'Content Element' sidebar once element is selected.
// For more details see Tailor documentation.
meta: { [key: string]: any };
// In Tailor CMS, it is possible to configure relationships between
// the Content Elements. These references are stored within refs property.
refs: { [key: string]: any };
// Future functionality support
linked: boolean;
// Boolean for marking elements for which parent structural item has been
// deleted
detached: boolean;
// Unique element uid, persisted upon creating the element copy
contentId: string;
// SHA-1 of 'data' value, uniquely identifying the Content Element data
contentSignature: string;
// Date element got created
createdAt: string;
// Date element got last updated
updatedAt: string;
// Date element got deleted
deletedAt: string | null;
}
Full Content Element entity ORM instance is available within server-side hooks. For more info on that. Please visit Server package
section.