webiny-js
webiny-js copied to clipboard
Enhanced naming functionality for entities in headlessCMS
Is your feature request related to a problem? Please describe.
Hi there,
titleFieldId
allows us to define entities based on a single property. It'd be useful to enable entities to be named by custom logic that is calculated on save.
For instance, it'd help to name the entity below boom.com - My Industry
Thanks for your time
Describe the solution you'd like.
- Define a template eg,
${myVar1} - ${myVar2}
- Define a custom function, stored in
api/code
, that takes the current entity as an arg
Describe alternatives you've considered.
The only alternative I see is to have a property on the entity specifically for its display name. This is pretty common, I know. But I've found it challenging to rely on content writers to adhere to naming conventions (my current "CMS" in google docs would make u cry). The best solution would separate naming from the users of the admin ui
This issue is stale because it was opened 120 days with no activity. Remove the "stale-issue" label or leave a comment to revive the issue. Otherwise, it will be closed in 7 days.
This issue is stale because it was opened 120 days with no activity. Remove the "stale-issue" label or leave a comment to revive the issue. Otherwise, it will be closed in 7 days.
@bpietravalle - I had a similar(ish) use case, where I wanted to calculate field values on insert/update. I took the approach of creating a GraphQL API plugin that hooks in to the headless CMS entry lifecycle.
import {
OnEntryBeforeCreateTopicParams,
OnEntryBeforeUpdateTopicParams
} from "@webiny/api-headless-cms/types";
import { PbContext } from "@webiny/api-page-builder/types";
import { ContextPlugin } from "@webiny/handler-aws";
const contextPlugin = new ContextPlugin<PbContext>(async context => {
const cb = async ({
model,
entry
}: OnEntryBeforeUpdateTopicParams | OnEntryBeforeCreateTopicParams) => {
// If the model is tagged to auto-calculate the title field
if (model.tags?.find((value) => value === "calculate:title")) {
const titleFieldId = model.titleFieldId;
const titleValue = /* Formatting logic goes here... */;
// Apply any additional validation such as a regex, uniqueness (below), etc.
const manager = await context.cms.getEntryManager(model);
const [existing] = await manager.listLatest({
where: {
[titleFieldId]: titleValue
},
limit: 1
});
if (existing.length > 0) {
throw new Error(`Title of "${titleValue}" already exists.`);
}
// Override any previously-store or user-supplied value with the calculated value
entry.values[titleFieldId] = titleValue;
}
};
context.cms.onEntryBeforeCreate.subscribe(cb);
context.cms.onEntryBeforeUpdate.subscribe(cb);
});
export default contextPlugin;
You could make this even more dynamic. For your use case, I think you could create tags on the model that represent format strings and call sprintf from within the plugin. But that does open up a number of potential injection opportunities.
Hopefully this gets you started.
@owenfarrell Thanks for sharing the example! Tags are a cool way to enable functionality dynamically, that's what we are doing ourselves in different scenarios, and not only with Headless CMS :)
It would be great to have this in our docs @swapnilmmane.