Skip to content

Commit

Permalink
Some documentation for 10.27
Browse files Browse the repository at this point in the history
  • Loading branch information
DominicWatson committed Jul 15, 2024
1 parent 790900b commit 08c598b
Show file tree
Hide file tree
Showing 4 changed files with 278 additions and 1 deletion.
7 changes: 6 additions & 1 deletion docs/02.devguides/47.extensions/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ You can find publicly available extensions on [Forgebox](https://forgebox.io/typ

Extensions live under the `/application/extensions` folder within your Preside application, each extension with its own folder, e.g.

_(as of Preside 10.27, you are also able to create extensions in an `/extensions_app`. Great for separating locally committed extensions for organising your application's code.)_

```
/application
...
Expand All @@ -21,9 +23,12 @@ Extensions live under the `/application/extensions` folder within your Preside a
/my-extension-2
/my-extension-3
...
...
/extensions_app
/my-app-extension-1
...
```


Each extension can then contain *all of the valid convention-based folders that your application can contain*, i.e. `/handlers`, `/services`, `/i18n`, `/preside-objects`, etc.:

```
Expand Down
45 changes: 45 additions & 0 deletions docs/02.devguides/53.adminenvheader/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
id: adminenvheader
title: Admin development environment banner header
---

## Overview

As of Preside 10.27, you are able to have the admin user interface display a banner showing the working environment (i.e. staging vs production).

## Configuring the banner

In Config.cfc, you are able to configure whether or not the banner shows + configure an icon, alert class + optionally configure a specific message to display:

```luceescript
settings.environmentMessage = "Some message to display"; // default is empty, using i18n approach as detailed below
settings.environmentBannerConfig = {
icon = "fa-code"
, cssClass = "alert-info"
, display = true
};
```

Using this approach, you can use Coldbox environments system to provide different configuration for different environments. i.e. Have "local", and "staging" environment configurations by using corresponding methods in your Config.cfc:

```
function local() {
super.local();
settings.environmentBannerConfig = { display=false };
}
function staging() {
settings.environmentBannerConfig = { display=true, icon="fa-code", cssClass="alert-warning" };
// ...
}
```

## Using i18n for the message

If you leave `settings.environmentMessage` empty, then you can use i18n to specify the message. The key for the i18n resource will be: `cms:environment.#environment#.label`, where `environment` is the coldbox environment. So in `/i18n/cms.properties`, you could have:

```
environment.staging.label=This is the staging environment
environment.dev.label=This is the dev environment
```
225 changes: 225 additions & 0 deletions docs/02.devguides/53.features/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
---
id: features
title: Feature flagging
---

## Overview

Preside has a concept of feature flags that can be used to turn on and off various features of the core platform and of your extensions. It is important to note, that these are designed to be specified **in code** and effect the fundamental makeup of your application including its database structure. They are **not** feature flags that can be turned on and off for a running application.

## Definition

Feature flags are defined in your application/extension's `Config.cfc` file in a `settings.features` struct. The keys of this struct are the IDs of the feature flags. Each feature flag value is a structure with the following keys:

```luceescript
settings.features.myfeature = {
enabled = true // the only required key, whether or not the feature is enabled
, dependsOn = [ "featurex" ] // as of Preside 10.27, features can depend on other features. If any parent is disabled, this feature will be disabled
, widgets = [ "widgetx", "widgety" ] // an array of widget IDs that should only be available when this feature is enabled
, siteTemplates = [ "*" ] // if using site templates, can specify which site templates have this feature enabled
};
```

## Disabling/enabling a feature

If Preside core, or any extension defines a feature that you would like to override, then you will need to override the enabled property for that feature in your _application's_ Config.cfc file. e.g.

```luceescript
settings.features.admin.enabled = false;
settings.features.websiteUsers.enabled = false;
settings.features.somneExtensionFeature.enabled = true;
```

## Checking whether or not a feature is enabled

From handlers and views, Preside offers a helper function, `isFeatureEnabled( feature )`. In services that make use of the [[presidesuperclass]], you have a `$isFeatureEnabled( feature )` helper. Examples:

```luceescript
// in a handler or view
if ( isFeatureEnabled( "myFeature" ) ) {
// something
}
// in a service
if ( $isFeatureEnabled( "myCoolFeature" ) ) {
// something
}
// as of Preside 10.26
if ( isFeatureEnabled( "feature1 or ( feature2 and feature3 )" ) ) {
// something
}
```

## Limiting functionality using features

The general approach to applying feature flags is to decorate your code with `@feature` annotations. Depending on the source code file type, the way you annotate will differ. The core Preside platform allows you to flag the following resource types:

* Preside objects
* Preside object properties
* Forms, tabs, fieldsets and fields
* Widgets
* Handlers (as of Preside 10.27)
* Views (as of Preside 10.27)
* Services (as of Preside 10.27)

_Note: Various extensions may also use their own feature flagging approaches to their resources._

### Preside objects & their properties

To feature flag a Preside object, annotate the `component` directive with either of the following approaches:

```luceescript
/**
* Approach one. Using @ in javadoc style block
*
* @feature somefeature
*/
component {
// ...
}
```

```luceescript
component feature="approach2Feature" {
// ...
}
```

Feature flagging properties is a case of adding a `feature` attribute to the property:


```luceescript
component {
property name="asset" relationship="many-to-one" relatedto="asset" feature="assetManager";
}
```

### Forms, tabs, fieldsets and fields

Documentation for feature flagging forms can be found here: [[presideforms-features]]. In essence, however, you can add `feature` attributes to the `form`, `tab`, `fieldset` and `field` elements:

```xml
<form feature="myfeature">
<tab id="tab1" feature="myfeaturex">
<fieldset id="fs1" feature="myfeaturey">
<field name="somefield" feature="myfeaturez" />
<!-- ... -->
</fieldset>
<!-- ... -->
</tab>
<!-- ... -->
</form>
```

### Widgets

Due to widgets being definable in multiple ways, widgets must be specified in the feature flag struct in Config.cfc. i.e.

```luceescript
settings.features.someFeature = { enabled=true, widgets=[ "widget1", "widget3" ] };
```

Note: if you want to add a widget to a feature that is defined elsewhere, you should use something like the following approach:

```luceescript
// ensure widgets array exists and then *append* to it
// rather than overwriting it completely which may destroy existing
// feature widget definitions
settings.features.featurex.widgets = settings.features.featurex.widgets ?: [];
ArrayAppend( settings.features.featurex.widgets, "my-new-widget" );
```

### Handlers & services

As of Preside 10.27, handlers and services may be feature flagged. If the feature is disabled, the service/handler will then not be enabled. The benefit of this, is that handlers and services will not be loaded into memory if their feature flag is disabled. Annotating a handler CFC is the same as annotating a preside object, i.e.

```luceescript
/**
* Approach 1, javadoc comment style
*
* @feature someFeature || anotherfeature
* @presideservice true
* @singletone
*/
component {
// ...
}
```

Or:

```luceescript
component feature="someFeature || anotherfeature" {
// ...
}
```

#### Wirebox injections

If you have a service that depends on another service that is feature flagged, you may use the `featureInjection` dsl to avoid issues. For example:


```luceescript
/**
* @singleton true
* @presideService true
*/
component {
// featureInjection allows injection of a singleton without
// any errors when the feature is disabled
property name="aFeatureSpecificService" inject="featureInjection:myfeature:AFeatureSpecificService";
// ...
function someFunction() {
// always do a feature check before attempting
// to use the service - otherwise you will get errors
// when the feature is not enabled and the service does not exist
if ( $isFeatureEnabled( "myFeature" ) ) {
aFeatureSpecificService.doSomething();
}
}
}
```

### Views

As of Preside 10.27, a view may be feature flagged. This has the benefit of avoiding loading the view into memory when it is not used. To feature flag a view **the first line** of the `.cfm` file must add an annotation in the following form:

```lucee
<!---@feature myFeature--->
```

## .presideIgnore.json file

As of Preside 10.27, you may find that you have a `.presideIgnore.json` file in the root of your project. This file is used by Preside in production to ignore files that are feature flagged with features that are disabled. This avoids the system ever having to read the files and can be a useful strategy to improve startup times and resource usage of your applications when running with a lot of disabled features.

### Controlling use of the feature

By _default_, the application will **write** to this file in local mode and **read** from the file in production mode. This allows you to optimize production and have your local development environment maintain the content of the file.

To control this feature, use the following in your application's Config.cfc file:

```luceescript
// local mode
settings.ignoreFile.read = false;
settings.ignoreFile.write = true;
// production mode
settings.ignoreFile.read = true;
settings.ignoreFile.write = false;
// completely disabled
settings.ignoreFile.read = false;
settings.ignoreFile.write = false;
```

### Strategy for use

If using this feature, you should have your application run with "local mode" at least once to generate the ignore file **before** the code makes it to production. This could be simply running the application locally in your production branch and committing the resultant `.presideIgnore.json` file, or having this run as a warmup routine in a docker build in a pipeline or similar.

If in doubt and experiencing issues with this feature, you are perfectly safe to disable it.
2 changes: 2 additions & 0 deletions docs/02.devguides/chapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ In this chapter, you should find detailed guides on developing with the Preside
* [[workingwiththericheditor]]
* [[datamanager]]
* [[routing]]
* [[features]]
* [[cmspermissioning]]
* [[websiteusersandpermissioning]]
* [[editablesystemsettings]]
Expand Down Expand Up @@ -54,3 +55,4 @@ In this chapter, you should find detailed guides on developing with the Preside
* [[selectdataviews]]
* [[customdbmigrations]]
* [[systemalerts]]
* [[adminenvheader]]

0 comments on commit 08c598b

Please sign in to comment.