Item Metadata Builders
Added item metadata builders, an opt-in feature allowing users to automatically build an item’s title and/or description according to some predefined logic.
The API has a new endpoint api/items/{id}/metadata and its client code has been updated accordingly.
Updating API
Item metadata builders are components which can be configured from the API profile to generate title and/or description of a given item from its parts. ⚠️ To avoid errors at startup when using versions of backend core Cadmus components from version 14 onwards, ensure to add this code to your API Program.ConfigureAppServices:
// metadata builder factory provider
services.AddSingleton<IItemMetadataBuilderFactoryProvider>(_ =>
// TODO if using this feature, replace this provider with your API app's provider
new StandardItemMetadataBuilderFactoryProvider(
config.GetConnectionString("Default")!));
If you just need to avoid errors, this is all what you have to add.
Usage
API
If you want to use the feature, unless you are using the stock builder sampled above you will need to:
- create your own builder for your project’s logic and facets. You can look at EidItemMetadataBuilder in
Cadmus.General.Partsfor an example. - in your API
Servicesfolder, add a provider for it like this, adding to itsGetHostthe assembly including your builder, and replaceStandardItemMetadataBuilderFactoryProviderin the above API code with it:
using Cadmus.Core.Config;
using Cadmus.General.Parts;
using Fusi.Microsoft.Extensions.Configuration.InMemoryJson;
using Microsoft.Extensions.Hosting;
using System;
using System.Reflection;
namespace Cadmus__PRJ__Api.Services;
/// <summary>
/// Implementation of <see cref="IItemMetadataBuilderFactoryProvider"/>.
/// </summary>
public sealed class AppItemMetadataBuilderFactoryProvider :
IItemMetadataBuilderFactoryProvider
{
private readonly string _connectionString;
/// <summary>
/// Initializes a new instance of the
/// <see cref="AppItemMetadataBuilderFactoryProvider"/> class.
/// </summary>
/// <param name="connectionString">The connection string.</param>
public AppItemMetadataBuilderFactoryProvider(string connectionString)
{
_connectionString = connectionString ??
throw new ArgumentNullException(nameof(connectionString));
}
private static IHost GetHost(string config)
{
// build the tags to types map for parts/fragments
Assembly[] browserAssemblies =
[
// Cadmus.General.Parts
typeof(NotePart).Assembly,
// TODO: add your builder's assembly here
];
TagAttributeToTypeMap map = new();
map.Add(browserAssemblies);
return new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
ItemMetadataBuilderFactory.ConfigureServices(services,
new StandardPartTypeProvider(map),
browserAssemblies);
})
// extension method from Fusi library
.AddInMemoryJson(config)
.Build();
}
/// <summary>
/// Gets the item metadata builder factory.
/// </summary>
/// <param name="profile">The profile.</param>
/// <returns>Factory.</returns>
/// <exception cref="ArgumentNullException">profile</exception>
public ItemMetadataBuilderFactory GetFactory(string profile)
{
ArgumentNullException.ThrowIfNull(profile);
return new ItemMetadataBuilderFactory(GetHost(profile), _connectionString);
}
}
Frontend
-
configure builders in your
seed-profile.json: for each builder specify its ID (equal to its tag attribute) and key(s) with the item’s facet ID(s) it targets (separated by space) like in this example:{ "metadataBuilders": [ { "id": "item-metadata-builder.eid", "keys": "facet1 facet2" } ] } -
in your frontend, add this
env.jsvariable:
// https://www.jvandemo.com/how-to-use-environment-variables-to-configure-your-angular-application-without-a-rebuild/
(function (window) {
window.__env = window.__env || {};
// ...
// enable item metadata builders in item editor
window.__env.hasMetadataBuilders = true;
})(this);