#Collections
Under the hood, Collections are called Datastores and Entries are called DataItems. "Datastore" and "DataItem" will be used in this documentation when talking about API access while "Collection" and "Entry" will be used when talking about user interface.
#Datastore Schema
The schema for a Datastore is shown below. We will go into what each property does here.
{
// uneditable properties
_id: '639cf545ea990f22e697185e',
parentVersionId: '639cf555ea990f22e6971860',
managedByAddonId: '639b8f837f5fb8a39404280a',
createdAt: 1671250792833,
updatedAt: 1671250878818,
// basic properties
name: 'Vehicle',
description: 'Vehicles for sale',
icon: 'directions_car',
// general properties
isEnabled: true,
isGlobal: false,
isGlobalSelectable: false,
isInNav: false,
isAddonDataItemCreateEnabled: false,
isAddonDataItemDeleteEnabled: false,
// fields
fields: [],
// form layout
tabs: [],
sections: [],
// display fields
displayField: 'displayTitle',
displayFieldSecondary: '',
displayFieldExtra: '',
displayFieldContent: 'description',
displayFieldImage: 'images',
// sorting fields
sortBy: 'listedAt',
sortOrder: 'desc',
// archive fields
archiveField: 'listedAt',
archiveAfterDays: 90,
// build-time properties
functions: [],
buildScript: '',
}
#Uneditable Properties
Name | Description |
---|---|
_id | Assigned by MercuryCMS when the Datastore is created |
parentVersionId | Used by MercuryCMS to manage revision history |
createdAt | JavaScript Date the Datastore was created |
updatedAt | JavaScript Date the Datastore was last modified |
managedByAddonId | All of your created Datastores have this automatically added so they can be removed when the Addon is uninstalled |
#Basic Properties
Name | Description |
---|---|
name | All Datastores must have a name. Use something that won't conflict with Datastores the user has created |
description | Optional, but good form to include a description of what the Datastore contains |
icon | Material Icons icon, for example: star |
#General Properties
Name | Description |
---|---|
isEnabled | Set this to false to disable the Datastore. The user can override this value |
isGlobal | When true , a single DataItem is used for the whole site |
isGlobalSelectable | When true , the user can select which DataItem to use from the available DataItems in the Datastore. When false , there should be a single DataItem provided |
isInNav | When true will show this Datastore in the Sidebar |
isAddonDataItemCreateEnabled | When true , the user can manually create DataItems in this Datastore. See User Modification below |
#Fields
An array of Fields. Fields have common properties and properties unique to that type. Each type is explained below. All properties other than name
and type
have a default value and can be omitted when creating a Field or Datastore. See Collection Fields for more information.
#Common Field Properties
These properties are available on most Field types.
Name | Description |
---|---|
name | This is the display name of the Field. For example "Full Name" |
description | This is used below the Field's label on forms. For example: "Your full name including first and last name." |
type | The type of Field. This can be one of "string" (Text), "number" , "date" , "color" , "richText" , "media" , "asset" , "boolean" , "reference" (Relation), "enum" (Enumerable), "array" , or "object" |
initialValue | This is the value that will initially be in the Field when the user creates a new Entry in the interface. This is not the default value if no value is provided and has no effect when creating DataItems through the API. Supported by all types but array and object . See Initial Values for more information |
computedValue | The computed value that will automatically update when the user types into the form when editing the Entry. This does not compute when setting values through the API. Supported by all types but array and object . See Computed Values for more information |
minLength , maxLength | Either "" to disable, or a number indicating the min/max length/items. This applies to string , richText , and array |
isReadonly | When true , the Field's value cannot be edited by the user in the form. This is useful for showing the user a computed value. This is also useful when used in conjunction with Shared Fields as described below in Importing From External APIs |
isRequired | When true the form will require the user to fill out this Field before saving |
isUniqueInDatastore | When true , no two DataItems may have the same value for this Field. Supported by all types but array , boolean , and object |
#String (Text)
Strings have the following special properties they can optionally specify.
Name | Description |
---|---|
stringType | One of "" (General), "email" , "fullName" , "materialIcon" , "phone" |
format | An array of formats to apply to the string when the user is editing the form. They apply in order. (see below) |
Formats have the following properties. Note that only type
is required for all but the "replace"
format type.
Name | Description |
---|---|
type | One of "camelcase" , "kebabcase" , "lowercase" , "snakecase" , "studlycase" , "uppercase" , "alphanumeric" (Letters and Numbers Only), "alpha" (Letters Only), "capitalize" , "capitalizewords" , "replace" , "reverse" , or "trim" . Required |
match | The value to replace. This will be used to create a RexExp match. Required if type is "replace" |
matchOptions | Either "gi" or "g" . Required if type is "replace" |
replacement | The replacement text. Required if type is "replace" |
#Number
Numbers have the following special properties they can optionally specify.
Name | Description |
---|---|
minValue , maxValue | Either "" to disable, or a number indicating the min/max value. This only affects what the user can enter in the form |
#Date
Dates have the following special properties they can optionally specify.
Name | Description |
---|---|
dateType | One of "" (Date YYYY-MM-DD), "time" (Time HH:mm), "datetime" (JavaScript Date) |
You must provide date values for this Field in the format you specify with dateType
. For example:
'2023-02-03' // dateType: ''
'23:49' // dateType: 'time' (always 24-hour format)
1678003648592 // dateType: 'datetime' (JavaScript Date)
#Rich Text
Rich Text Fields have the following special properties they can optionally specify.
Name | Description |
---|---|
assetUploadPath | An optional path in Assets the user can upload files to. Cannot include spaces or special characters. The directory will automatically be created if it doesn't exist. Ex: /documents/rental_agreements |
mediaUploadPath | An optional path in the Media Library the user can upload files to. Can include spaces. The directory will be automatically created if it doesn't exist. Ex: "Property Images/Interior" |
#Media
Media Fields have the following special properties they can optionally specify.
Name | Description |
---|---|
mediaType | One of "" (Any), "image" , "video" , "image/video" , or "audio" |
mediaUploadPath | An optional path in the Media Library the user can upload files to. Can include spaces. The directory will be automatically created if it doesn't exist. Ex: "Property Images/Interior" |
#Asset
Asset Fields have the following special properties they can optionally specify.
Name | Description |
---|---|
assetType | A comma-separated list of accepted MIME types and/or file extensions. For example: "image/*, .pdf, .zip, application/msword" |
assetUploadPath | An optional path in Assets the user can upload files to. Cannot include spaces or special characters. The directory will automatically be created if it doesn't exist. Ex: /documents/rental_agreements |
#Enum (Enumerable)
Enum Fields have the following special properties they can optionally specify.
Name | Description |
---|---|
enumType | One of "" (String), or "number" |
enumValues | An array of selectable enumerable options with the format {name: 'Some Name', value: 'someValue'} . |
You can also specify isEnumValueCreateDisabled
on the Field to prevent the user from creating their own enumValues.
#Reference (Relation)
Reference Fields have the following special properties. referenceTo
is required.
Name | Description |
---|---|
referenceTo | Required for reference fields. This is the _id of the Datastore to reference to |
#Array
Array Fields must specify the field
property.
Name | Description |
---|---|
field | The description of what the Array's Field should be. This is another field object with all of the same properties this Field has (name , type , etc.) |
For example, an array of images might look like this:
{
name: 'Images',
type: 'array',
minLength: 1,
maxLength: 20,
field: {
type: 'media',
mediaType: 'image',
uploadPath: 'Blog Post Images',
},
}
#Object
Object Fields can optionally specify many of the same properties the Datastore can. Specifically tabs
, sections
, fields
, displayField
, displayFieldSecondary
, displayFieldExtra
, displayFieldContent
, and displayFieldImage
.
#Form Layout
Datastores and Object Fields can define a tabs
and sections
array. Tabs are currently under development, and thus, do nothing.
The form is described by a list of sections. These sections are shown vertically in the order they're defined in the array. Any Fields not specified in the form's sections are hidden. Here's an example:
sections: [
{
rows: [1, 1, 1],
items: [
{type: 'field', field: 'title'},
{type: 'field', field: 'excerpt'},
{type: 'field', field: 'body'},
]
},
{
rows: [1, 1],
items: [
{type: 'field', field: 'metaTitle'},
{type: 'field', field: 'metaDescription'},
]
},
{
location: 'sidebar',
rows: [2, 1, 1, 1, 1, 1],
items: [
{type: 'field', field: 'isFeatured'}, // first row
{type: 'field', field: 'isHidden'},
{type: 'field', field: 'slug'}, // second row
{type: 'field', field: 'featuredImage'}, // third row
{type: 'field', field: 'publishedAt'}, // fourth row
{type: 'field', field: 'category'}, // fifth row
{type: 'field', field: 'author'}, // sixth row
]
},
]
Each section has a location
which is either "main"
or "sidebar"
and defaults to "main"
. It then has an array called rows
which defines how many items go into each row. You can see in the sidebar in this example that the isFeatured
and isHidden
Fields will be beside each other. It is recommended you do no more than 4 columns in the main sections and 2 columns in the sidebar.
Each item in the items
array has a type
. The only type available now is "field"
which requires that you specify a field
property which is the name of the field to show. This can be a Field from the Datastore or one of its Shared Fields. You can also have null
as an item instead of an object for an empty space for that column.
In the future, additional item types will be added.
#Display Fields
Name | Description |
---|---|
displayField | The name of the Field to show in dropdowns and the Collection Entries screen. Typically something like Author's name or a computed property that combines some of the Fields like the House's full address or Vehicle's year, make, model, and VIN |
displayFieldSecondary | The name of the second-line display Field, like a Staff Member's title |
displayFieldExtra | The name of the extra display Field with helpful data, like the Member's joinedAt Date |
displayFieldContent | The name of the full text content Field to be previewed, like a Blog Post's body or Property's description |
displayFieldImage | The name of the Media, Media Array, or Icon Field to be used for the image/icon |
#Sorting Fields
Name | Description |
---|---|
sortBy | Name of the Field to sort by in the interface, many times the same as the displayField . Also accepts _createdAt and _updatedAt |
sortOrder | Either asc or desc depending on which direction to sort |
#Archive Fields
Name | Description |
---|---|
archiveField | Name of the Field to archive Entries in this Collection by. This must be a date field with a dateType of "" or "datetime" . Leave blank to not archive. Also accepts _createdAt and _updatedAt |
archiveAfterDays | Number of days in the past this field must be to archive the Entry |
#Build-time Properties
Name | Description |
---|---|
functions | Array of functions the Datastore or its DataItems should have available, explained below |
buildScript | Code to run during the Build. See Collection Build Scripts |
An example function is below. For more information, see Collection Functions
{
type: 'instance',
script: 'function doStuff(arg1, arg2) {\n //do stuff\n}',
}
To make a function available on each DataItem (blogPost.getRelated()
), use type: 'instance'
. To make the function available on the Datastore (blogPostList.getRecentPosts()
), use type: 'static'
.
#User Modification
Collections created by your Addon behave slightly differently than Collections created by the user. The following rules apply:
- Any Datastores your Addon creates will be automatically deleted when the Addon is uninstalled. This includes all of its DataItems including those created by the user.
- The user cannot create or delete DataItems in any Datastore you create. You can specify
isAddonDataItemCreateEnabled: true
in the Datastore to allow the user to create and delete their own DataItems, but still not delete any created by your Addon. SpecifyisAddonDataItemDeleteEnabled: true
in the Datastore to allow the user to delete DataItems created by your Addon. - The user cannot change the name of the Datastore or whether it is global, but can change whether it shows in the Sidebar, its Sorting Fields, Archive behavior, and its Display Fields.
- The user can rearrange Fields, hide Fields from the form, and add their own, but not delete Fields you have created.
- The user can add their own
enumValues
toenum
Fields but not removeenumValue
s your Addon has created. To prevent the user from creating their ownenumValues
, setisEnumValueCreateDisabled: true
on the field. - The user can modify the
assetUploadPath
andmediaUploadPath
on Asset, Media, and Rich Text Fields. - The user can create their own Collection Functions but not remove ones you have created.
You must write your Addon in a way that allows for the user to extend your Addon's Datastore. They are expected to add their own fields as needed and it is part of MercuryCMS' design to allow the user to combine multiple Addons' data in their own Collections and Components. Do not write code that routinely destroys and recreates Datastore field schema or destroys all current schema when updating.
#Getting Datastores
You can get a list of all of your Datastores by calling cms.getDatastores()
. This will return a full list of the Datastores your Addon has created and does not include any created by the user or other Addons.
// use static-cms-addon
import cms from 'static-cms-addon'
let datastores = await cms.getDatastores()
console.log(datastores.map(datastore => datastore.name)) // ['Blog Post', 'Category', 'Author']
// use axios
let response = await axios.get(`http://localhost:${cmsPort}/api/addon/${addonId}/datastore`)
console.log(response.data.datastores.map(datastore => datastore.name)) // ['Blog Post', 'Category', 'Author']
#Creating Datastores
You can create Datastores by using cms.upsertDatastore()
. This function will look to see if a specific Datastore exists and update it, or create it if it doesn't exist. This will return the created Datastore including its assigned _id
. You can then use that _id
when creating Reference Fields.
You typically want to create Datastores right when your Addon starts. Updating Datastores will this function will not overwrite user-managed settings like any functions they have created, custom fields they've added, etc.
let datastores = await cms.getDatastores()
let blogCategoryDatastore = datastores.find(datastore => datastore.name == 'Blog Category')
let blogAuthorDatastore = datastores.find(datastore => datastore.name == 'Blog Author')
let blogPostDatastoreDef = {
name: 'Blog Post',
description: 'Blog Posts imported from WordPress',
icon: 'edit',
displayField: 'title',
displayFieldSecondary: '',
displayFieldContent: 'body',
displayFieldImage: 'featuredImage',
sortBy: 'publishedAt',
sortOrder: 'desc',
fields: [
{name: 'Title'},
{name: 'Excerpt'},
{name: 'Body', type: 'richText'},
{name: 'Meta Title'},
{name: 'Meta Description'},
{name: 'Is Featured', type: 'boolean'},
{name: 'Is Hidden', type: 'boolean'},
{name: 'Slug', computedValue: '{{ this.title }}', format: [{type: 'kebabcase'}]},
{name: 'Featured Image', type: 'media', mediaType: 'image'},
{name: 'PublishedAt', type: 'date', dateType: 'datetime'},
{name: 'Category', type: 'reference', referenceTo: blogCategoryDatastore._id},
{name: 'Author', type: 'reference', referenceTo: blogAuthorDatastore._id}
],
sections: [
{
rows: [1, 1, 1, 1, 1],
items: [
{type: 'field', field: 'title'},
{type: 'field', field: 'excerpt'},
{type: 'field', field: 'body'},
]
},
{
rows: [1, 1],
items: [
{type: 'field', field: 'metaTitle'},
{type: 'field', field: 'metaDescription'},
]
},
{
location: 'sidebar',
rows: [2, 1, 1, 1, 1, 1],
items: [
{type: 'field', field: 'isFeatured'},
{type: 'field', field: 'isHidden'},
{type: 'field', field: 'slug'},
{type: 'field', field: 'featuredImage'},
{type: 'field', field: 'publishedAt'},
{type: 'field', field: 'category'},
{type: 'field', field: 'author'},
]
},
]
}
// use static-cms-addon
import cms from 'static-cms-addon'
let blogPostDatastore = await cms.upsertDatastore({name: 'Blog Post'}, blogPostDatastoreDef, 'Added Meta Title and Meta Description.')
console.log(blogPostDatastore._id) // "639e58c84b851d93f27dc830"
// use axios
let response = await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/datastore`, blogPostDatastoreDef)
console.log(response.data.datastore._id) // "639e58c84b851d93f27dc830"
The first argument to upsertDatastore()
is the fields to match against. This should typically just be name
. The second argument is the Datastore definition, and the third argument is an optional Publish Comment. You can use this to provide information about what changed in the Datastore. This will not be used if the Datastore is new, and will only be shown if the Datastore you are upserting has actually changed.
When specifying reference fields, instead of using the reference Datastore's _id
, you can instead use their camelCase name. For example, to reference a Datastore named "Blog Author", you could use {name: 'Author', type: 'reference', referenceTo: 'blogAuthor'}
. The reference Datastore will still need to first exist before you can reference to it.
You can also load the Datastore from a zip or folder using cms.loadDatastorePackage()
.
let componentDef = cms.loadDatastorePackage('components/myComponent.datastore.zip').datastore
let component = await cms.upsertDatastore(componentDef)
#Deleting Datastores
You can use cms.deleteDatastores()
to delete Datastores your Addon has created. This will also delete all of its DataItems.
// use static-cms-addon
import cms from 'static-cms-addon'
let datastores = await cms.getDatastores()
let datastore = datastores.find(datastore => datastore.name == 'My Datastore')
await cms.deleteDatastores([datastore._id])
// use axios
let response = await axios.get(`http://localhost:${cmsPort}/api/addon/${addonId}/datastore`)
let datastore = response.data.datastores.find(datastore => datastore.name == 'My Datastore')
await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/datastore/delete`, {datastoreIds: [datastore._id]})
#DataItems
DataItem schema is shown below:
{
// uneditable properties
_id: '639e8eb64b851d93f27dc843',
parentVersionId: '639e8ef54b851d93f27dc845',
managedByAddonId: '639b8f837f5fb8a39404280a',
createdAt: 1671335606730,
updatedAt: 1671335669405,
// datastore that determines dataitem fields
datastoreId: '639e8eb64b851d93f27dc843',
// general properties
isEnabled: true,
// field metadata
overriddenFields: [],
// field values
fields: {},
}
#Uneditable DataItem Properties
Name | Description |
---|---|
_id | Assigned by MercuryCMS when the DataItem is created |
parentVersionId | Used by MercuryCMS to manage revision history |
createdAt | JavaScript Date the DataItem was created |
updatedAt | JavaScript Date the DataItem was last modified |
managedByAddonId | All of your created DataItems have this automatically added so they can be removed when the Addon is uninstalled |
#General Properties
Name | Description |
---|---|
isEnabled | Set this to false to disable the DataItem. The user can override this field |
#Field Metadata
These properties are automatically managed by the interface. For example, when the user clicks the "Override" switch and enters their own value in place of a Computed Value, MercuryCMS adds the name of the Field to overriddenFields
.
Name | Description |
---|---|
overriddenFields | A list of Computed Fields that have been overridden by the user. Ex: ["slug"] |
#DataItem Fields
The fields
object contains the values of the Fields. For example:
fields: {
title: 'My Blog Post',
excerpt: 'My post\'s excerpt',
body: '# Some Heading\n\nSome text',
metaTitle: 'My Blog Post',
metaDescription: 'A post I made',
isFeatured: true,
isHidden: false,
slug: 'my-blog-post',
featuredImage: '639e92b24b851d93f27dc847',
keywords: ['post', 'blog', 'my', 'demo'],
publishedAt: 1671336660864,
category: '639e92f14b851d93f27dc848',
author: '639e92f84b851d93f27dc84a',
review: {
overriddenFields: [],
fields: {
title: 'My Review',
stars: 4,
body: 'This blog post is pretty good.',
reviewer: {
overriddenFields: [],
fields: {
name: 'John Doe',
email: 'johndoe@example.com',
}
}
}
}
}
As you can see, all values are stored in their native type (string
Fields are strings, number
Fields are numbers, array
Fields are arrays, etc. The only special Field type is object
, which has its own fields
property and Field metadata (overriddenFields
etc.) When you retrieve a DataItem from the API, you will need to account for this format.
#Getting DataItems
You can get DataItems by using cms.getDataItem()
and cms.getDataItems()
. You can optionally provide a match
key to getDataItems()
. This is a Mongo-compatible query which supports all directives like $in
and $ne
. datastoreId
is automatically added to your match
query based on the path parameters in the request. You can also specify an array of dataItemIds
rather than having to use a cumbersome combination of $in
and $oid
.
// use static-cms-addon
import cms from 'static-cms-addon'
let authorDataItem = await cms.getDataItem({datastoreId: authorDatastore._id, dataItemId: '639ea4aa4b851d93f27dc84f'})
let allBlogPostDataItems = await cms.getDataItems({datastoreId: blogPostDatastore._id})
let authorBlogPostDataItems = await cms.getDataItems({datastoreId: blogPostDatastore._id, match: {'fields.author': authorDataItem._id}})
let categoryDataItems = await cms.getDataItems({datastoreId: categoryDatastore._id, dataItemIds: ['639ea62e4b851d93f27dc851', '639ea6394b851d93f27dc857']})
// use axios
let response = await axios.get(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${authorDatastore._id}/639ea4aa4b851d93f27dc84f`)
let authorDataItem = response.data.dataItem
response = await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${blogPostDatastore._id}/list`)
let allBlogPostDataItems = response.data.dataItems
response = await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${blogPostDatastore._id}/list`, {match: 'fields.author': authorDataItem._id})
let authorBlogPostDataItems = response.data.dataItems
response = await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${categoryDatastore._id}/list`, {dataItemIds: ['639ea62e4b851d93f27dc851', '639ea6394b851d93f27dc857']})
let categoryDataItems = response.data.dataItems
#Creating DataItems
You can create DataItems by calling cms.upsertDataItems()
. You can either pass a DataItem that already contains fields
, or you can pass raw: true
to the request and pass in DataItems in the same format you would see them when Templating. This is very useful when pulling the data from an external API so you don't have to parse the raw objects yourself.
Note: You never need to set datastoreId
on a DataItem. This is always done automatically by MercuryCMS.
let rawBlogPosts = [
{
title: 'My Blog Post',
excerpt: 'My post\'s excerpt',
body: '# Some Heading\n\nSome text',
metaTitle: 'My Blog Post',
metaDescription: 'A post I made',
isFeatured: true,
isHidden: false,
slug: 'my-blog-post',
featuredImage: '639e92b24b851d93f27dc847',
keywords: ['post', 'blog', 'my', 'demo'],
publishedAt: 1671336660864,
category: '639e92f14b851d93f27dc848',
author: '639e92f84b851d93f27dc84a',
review: {
title: 'My Review',
stars: 4,
body: 'This blog post is pretty good.',
reviewer: {
name: 'John Doe',
email: 'johndoe@example.com',
}
}
}
]
// use static-cms-addon
import cms from 'static-cms-addon'
let blogPostDataItems = await cms.upsertDataItems({
datastoreId: blogPostDatastore._id,
match: ['fields.slug'],
dataItems: rawBlogPosts,
publishComment: 'Import from my website',
raw: true,
})
console.log(blogPostDataItems[0].fields.review.fields.title) // "My Review"
// use axios
let response = await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${blogPostDatastore._id}`, {match: ['fields.slug'], dataItems: rawBlogPosts, publishComment: 'Import from my website', raw: true})
console.log(response.data.dataItems[0].fields.review.fields.title) // "My Review"
The match
option allows you to provide an array of values that will be checked on each DataItem. In the above example, each Blog Post being passed in will be matched against an existing Blog Post based on its slug
. You can provide multiple values to match against.
The Publish Comment is optional. You can use this to provide information about what changed in the DataItem. This will not be used if the DataItem is new, and will only be shown if the DataItem you are upserting has actually changed.
You can also create individual DataItems using cms.upsertDataItem()
. In the following example, an object is used for match
, but this call also supports simply passing ['fields.slug']
as well.
let blogPostDataItem = await cms.upsertDataItem({
datastoreId: blogPostDatastore._id,
match: {'fields.slug': blogPostDataItem.slug},
dataItems: rawBlogPost,
publishComment: 'Import from my website',
raw: true,
})
console.log(blogPostDataItem.fields.review.fields.title) // "My Review"
// use axios
let response = await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${blogPostDatastore._id}`, {match: {'fields.slug': rawBlogPost.slug}, dataItems: [rawBlogPost], publishComment: 'Import from my website', raw: true})
console.log(response.data.dataItems[0].fields.review.fields.title) // "My Review"
#Deleting DataItems
You can delete DataItems by using cms.deleteDataItems()
. You must provide a match
key. This is a Mongo-compatible query which supports all directives like $in
and $ne
. datastoreId
is automatically added to your match
query based on the path parameters in the request. You can also specify an array of dataItemIds
rather than having to use a cumbersome combination of $in
and $oid
, or an array of notDataItemIds
rather than $nin
and $oid
.
// use static-cms-addon
import cms from 'static-cms-addon'
let authorDataItems = await cms.getDataItems({datastoreId: authorDatastore._id, match: {'fields.name': 'John Doe'}})
let authorDataItem = authorDataItems[0]
await cms.deleteDataItems({datastoreId: blogPostDatastore._id, match: {'fields.author': authorDataItem._id}})
// use axios
await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${blogPostDatastore._id}/delete`, {match: {'fields.author', authorDataItem._id}})
#Enabling and Disabling Data Items
You can enable and disable DataItems using cms.enableDataItems()
and cms.disableDataItems()
.
// use static-cms-addon
import cms from 'static-cms-addon'
await cms.enableDataItems({datastoreId: storeItemDatastore._id, match: {'fields.onSale': true}, publishComment: 'Listing sale items.'})
await cms.disableDataItems({datastoreId: storeItemDatastore._id, match: {'fields.sourceId': 863}, publishComment: 'Disabling discount supplier.'})
// use axios
await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${storeItemDatastore._id}/enable`, {match: {'fields.onSale': true}, publishComment: 'Listing sale items.'})
await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/dataitem/${storeItemDatastore._id}/disable`, {match: {'fields.sourceId': 863}, publishComment: 'Disabling discount supplier.'})
You can also specify dataItemIds
or notDataItemIds
. This is useful when importing from an external source and disabling all DataItems except the ones you just imported. Do this rather than deleting all of the DataItems not found, so the user can manually enable them if they wish, and their overrides won't be destroyed.
#Importing From External APIs
One of the most common use-cases for Addons is to pull data from an external source and make them available in MercuryCMS for Templating. Because of this, there are a number of built-in features that allow you to make this as simple as possible. Let's do a simple example first, then build on it.
import cms from 'static-cms-addon'
let storeItemDatastore = await cms.upsertDatastore({name: 'Store Item'}, {
name: 'Store Item',
description: 'Your Store Items from your Example.com Store',
icon: 'shopping_bag',
fields: [
{name: 'ID', type: 'number', isReadonly: true, isManagedByAddon: true},
{name: 'Price', type: 'number', isReadonly: true, isManagedByAddon: true},
{name: 'Name', isReadonly: true, isManagedByAddon: true},
],
sections: [
{
rows: [1],
items: [
{type: 'field', field: 'name'},
]
},
{
location: 'sidebar',
rows: [1, 1],
{type: 'field', field: 'id'},
{type: 'field', field: 'price'},
}
]
})
let response = await axios.get('https://example.com/api/items')
let storeItems = response.data.storeItems
console.log(storeItems)
// [
// {id: 736273, price: 999, name: 'Coffee Mug'},
// {id: 137823, price: 1299, name: 'Hat'},
// {id: 321232, price: 2499, name: 'T-Shirt'},
// ]
let dataItems = await cms.upsertDataItems({
datastoreId: storeItemDatastore._id,
match: ['id'],
dataItems: storeItems,
raw: true
})
await cms.disableDataItems({datastoreId: storeItemDatastore._id, notDataItemIds: dataItems.map(dataItem => dataItem._id)})
In this example, you can see how easy it is for us to update the Store Item Collection and disable unused items. The user can use this data via storeItemList
when Templating and we can provide some Components for the user to quickly get started.