Relatude Help

The content as the screens see it

cms.data is the DataClient the content screens run on: the site's model as collections of nodes with plain values. A plugin that lists or edits content through it gets the same lists, display names and saving as those screens. It works in the offline demo too, where cms.store is null. For typed queries, relations, transactions and types that are not collections, use cms.store (chapter 19).

import { useEffect, useState } from 'react';
import { useCms, type CmsApi, type NodeData } from '@relatude/sdk';

/** The ten articles changed last, kept current as editors save. */
function useLatestArticles() {
  const cms = useCms();
  const [items, setItems] = useState<NodeData[]>([]);
  useEffect(() => {
    const load = () => void cms.data.query('IArticle', { pageSize: 10 }).then(r => setItems(r.items));
    load();
    return cms.data.onChange(load);   // returns the unsubscribe
  }, [cms]);
  return items;
}

/** Changes one value: save() writes only what differs from the base. */
async function retitle(cms: CmsApi, id: string, title: string) {
  const node = await cms.data.get(id);
  if (node) await cms.data.save({ ...node, values: { ...node.values, Title: title } }, node.values);
}
DataClient Does
schema(), typeSchema(typeId) the collections (the concrete node types of the site's model, without Relatude.DB's own), or one by CodeName
query(typeId, { search?, page?, pageSize?, sort? }) { items, total }; page counts from 0, 50 to a page; sort is newest (the default), oldest or name
get(id), nodes(ids) one node with its relation ends; several nodes, in the order asked
refs(ids) { id, type, name } for each id, to show linked nodes by name
search(text) up to eight nodes of any collection
displayName(node) the name lists show
create(typeId) an unsaved draft with the type's default values; its id starts with draft-
save(node, base?) inserts a draft, or writes the values that differ from base; answers the node as stored
remove(id) deletes the node
onChange(listener) content changed, here or by another editor; returns the unsubscribe
meta(id), metaChoices(), saveMeta(id, changes) the node's address, access groups, site, release and expiry; what they can be set to; writing those changes names (null clears one)
uploadFile(id, property, file, { signal?, onProgress? }) puts a file into a file property at once; answers the file as stored
copyFile(id, property, { node, property }), removeFile(id, property) copies another node's file in, on the server; takes the file out
contentLinks(links), contentLink(id, file?) what stored links (#…) in HTML point at; the stored link to a node or its picture
saveLayout(typeId, layout) saves a type's form layout (Form layouts)

save writes only what differs from base, or else from the node as this client last read it, so it never overwrites what someone else saved in the meantime. onChange passes the ids of the changed nodes, or none when anything may have changed. nodes and refs leave out nodes that are gone or that the user cannot read. The file, link and layout methods are optional in the type: call them as cms.data.uploadFile?.(…).

A NodeData is { id, type, createdUtc, updatedUtc, values, image? }, plus revision, status (whether readers see it) and site from the CMS. values are keyed by CodeName:

Property Its value
a date ISO 8601 text
an enum its name
a relation's "one" end, a Reference<T> the related node's id
a relation's "many" end, a References<T> the related nodes' ids, in order
an embedded list its inner nodes, { id, type, values, image? }
a file a FileData: { name, size, contentType, width, height, url, thumbnailUrl?, previewUrl?, converting? }

save never writes files: the file methods write them at once. image is the node's first thumbnail. While one is still being made, such as a video's frame, imageConverting says which property and how far along it is, and fileInfo(id, property) asks again.

TypeSchema Is
id the CodeName, IArticle
name the model's title ([Node(Title = "…")]), else one made from the CodeName: IArticlePage is "Article page"
description the model's [Node(Description = "…")], shown in the create wizard
icon the node type's icon as SVG ([Node(Icon = "…")], else the closest base type's), else an icon name guessed from the type's name
properties the editable properties: id (the CodeName), name, type (the editor type), required, declaredBy, defaultValue and more
inherits the base types, nearest first
nameProperty the property that names the node, shown above the form's tabs

Title, description and icon can also be set in the Relatude.DB admin UI. Draw the icon with <Icon name={type.icon} />, which takes an icon name or SVG source.