Skip to content

Commit bf9a37a

Browse files
authored
Merge pull request #7325 from umbraco/cms/sign-providers
Flag providers and backoffice signs
2 parents 22c4d36 + 920d1a3 commit bf9a37a

File tree

3 files changed

+129
-1
lines changed

3 files changed

+129
-1
lines changed

16/umbraco-cms/SUMMARY.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
* [Vite Package Setup](customizing/development-flow/vite-package-setup.md)
153153
* [Extensions Overview](customizing/extending-overview/README.md)
154154
* [Extension Registry](customizing/extending-overview/extension-registry/README.md)
155-
* [Register an Extension](customizing/extending-overview/extension-registry/extension-registry.md)
155+
* [Register an Extension](customizing/extending-overview/extension-registry/register-extensions.md)
156156
* [Extension Manifest](customizing/extending-overview/extension-registry/extension-manifest.md)
157157
* [Replace, Exclude or Unregister](customizing/extending-overview/extension-registry/replace-exclude-or-unregister.md)
158158
* [Extension Types](customizing/extending-overview/extension-types/README.md)
@@ -213,6 +213,7 @@
213213
* [Sections & Trees](customizing/section-trees.md)
214214
* [Property Level UI Permissions](customizing/property-level-ui-permissions.md)
215215
* [Icons](customizing/foundation/icons.md)
216+
* [BackOffice Signs](customizing/back-office-signs.md)
216217
* [Searchable Trees (ISearchableTree)](customizing/searchable-trees.md)
217218
* [Property Editors](customizing/property-editors/README.md)
218219
* [Property Editor Validation](customizing/property-editors/property-editor-validation.md)
@@ -257,6 +258,7 @@
257258
* [Using Azure Blob Storage for Media and ImageSharp Cache](extending/filesystemproviders/azure-blob-storage.md)
258259
* [Configuring Azure Key Vault](extending/key-vault.md)
259260
* [Server Events From SignalR](extending/server-events.md)
261+
* [Flag Providers](extending/flag-providers.md)
260262
* [Packages](extending/packages/README.md)
261263
* [Creating a Package](extending/packages/creating-a-package.md)
262264
* [Language file for packages](extending/packages/language-files-for-packages.md)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
description: Describes how to use sign information provided in management API responses to present additional details to consumers.
3+
---
4+
5+
# Backoffice Signs
6+
7+
When trees, collections and items are presented in the backoffice, additional information can be displayed in the form of Signs.
8+
9+
A Backoffice sign is a client-side extension point that determines how each sign is displayed in the backoffice.
10+
11+
A Sign can utilize conditions in the same way as other Extensions or it can be bound to a Flag coming from the Management API.
12+
13+
For example, a Document scheduled for future publishing will have a Flag defined as part of trees, collections and item response:
14+
15+
```json
16+
"flags": [
17+
{
18+
"alias": "Umb.ScheduledForPublish"
19+
}
20+
],
21+
```
22+
23+
A Flag can be the determinant for a Sign by declaring the `forEntityFlags` as part of its Manifest.
24+
25+
Example:
26+
```json
27+
...
28+
forEntityFlags: "Umb.ScheduledForPublish",
29+
...
30+
```
31+
32+
Using this binding lets the server determine which signs are present in the response via the registered collection of [flag providers](../extending/flag-providers.md).
33+
34+
## Displaying a Sign
35+
36+
{% hint style="info" %}
37+
The client extension for backoffice signs will be available in Umbraco 16.4 / 17.0.
38+
{% endhint %}
39+
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
description: Describes how to use provide flags in management API responses for use in presenting additional details to consumers.
3+
---
4+
5+
# Flag Providers
6+
7+
The Umbraco management APIs for trees, collections, and items include a `flags` collection for each item. These indicate additional information for the item that can be presented to users.
8+
9+
The Umbraco backoffice uses this to provide additional overlay icons on tree, collection, and item presentations. This core behavior and extension point is described in the article on [backoffice signs](../customizing/back-office-signs.md).
10+
11+
## Core Flag Providers
12+
13+
Umbraco ships with four flag providers that will provide indications of the following document or media states:
14+
15+
- **Is Protected** - indicates the document is not available for public access.
16+
- **Has Pending Changes** - indicates that the document is published but has changes in draft waiting for publication
17+
- **Has Schedule** - indicates that the document is scheduled for publishing in the future
18+
- **Has Collection** - indicates that the document or media is based on a content type that is configured for display as a collection
19+
20+
For example, an item that is scheduled for publication would contain the following in the tree, collection or item API response:
21+
22+
```json
23+
"flags": [
24+
{
25+
"alias": "Umb.ScheduledForPublish"
26+
}
27+
],
28+
```
29+
30+
## Providing a Custom Flag Provider
31+
32+
If your package or project needs to present additional information for a tree, collection or item value, a custom flag provider can be created. This will be coupled with a presentation extension to determine how the information is interpreted for display as a [backoffice sign](../customizing/back-office-signs.md).
33+
34+
To create a flag provider, implement the `IFlagProvider` interface. There are two methods to implement:
35+
36+
- `CanProvideFlags<TItem>` - returns `bool` indicating whether this provider can provide flags for the tree, collection or item view model.
37+
- `PopulateFlagsAsync<TItem>(IEnumerable<TItem> itemViewModels)` - populates the `Flags` property for the provided collection of view models.
38+
39+
An illustrative implementation is as follows:
40+
41+
```csharp
42+
using Umbraco.Cms.Api.Management.ViewModels;
43+
using Umbraco.Cms.Core;
44+
45+
internal class MyDocumentFlagProvider : IFlagProvider
46+
{
47+
private const string Alias = Constants.Conventions.Flags.Prefix + "MyDocumentFlag";
48+
49+
// Indicate that this flag provider only provides flags for documents.
50+
public bool CanProvideFlags<TItem>()
51+
where TItem : IHasFlags =>
52+
typeof(TItem) == typeof(DocumentTreeItemResponseModel) ||
53+
typeof(TItem) == typeof(DocumentCollectionResponseModel) ||
54+
typeof(TItem) == typeof(DocumentItemResponseModel);
55+
56+
public Task PopulateFlagsAsync<TItem>(IEnumerable<TItem> itemViewModels)
57+
where TItem : IHasFlags
58+
{
59+
foreach (TItem item in itemViewModels)
60+
{
61+
if (ShouldAddFlag(item))
62+
{
63+
item.AddFlag(Alias);
64+
}
65+
}
66+
67+
return Task.CompletedTask;
68+
}
69+
70+
private bool ShouldAddFlag(TItem item) => return true; // Provide custom logic here.
71+
}
72+
```
73+
74+
The flag provider needs to be registered with Umbraco in a composer or application startup with:
75+
76+
```csharp
77+
builder.FlagProviders()
78+
.Append<MyDocumentFlagProvider>();
79+
```
80+
81+
For some flags, there may be sufficient information on the view models to map whether a flag should be created.
82+
83+
For an example of this, please see the core flag provider `IsProtectedFlagProvider` whose [source code can be found here](https://github.com/umbraco/Umbraco-CMS/blob/main/src/Umbraco.Cms.Api.Management/Services/Flags/IsProtectedFlagProvider.cs).
84+
85+
More complex flags will require additional information, using the identifiers of the view models to retrieve the necessary data. It's important to avoid "N+1" issues. The aim should be to retrieve all the data needed to populate the flags for the whole collection in one step.
86+
87+
In core, the flag provider `HasScheduleFlagProvider` shows a good example of this. The [source code can be found here](https://github.com/umbraco/Umbraco-CMS/blob/main/src/Umbraco.Cms.Api.Management/Services/Flags/HasScheduleFlagProvider.cs).

0 commit comments

Comments
 (0)