Skip to content

Commit

Permalink
chore: enhance documentation of the rules engine
Browse files Browse the repository at this point in the history
  • Loading branch information
cpaulve-1A committed May 17, 2024
1 parent 33c1c2d commit 1ce95b0
Show file tree
Hide file tree
Showing 63 changed files with 2,365 additions and 1,981 deletions.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 5 additions & 8 deletions apps/showcase/src/app/rules-engine/rules-engine.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { AsyncPipe } from '@angular/common';
import { AfterViewInit, ChangeDetectionStrategy, Component, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core';
import { RouterModule } from '@angular/router';
import { NgbNav, NgbNavContent, NgbNavItem, NgbNavLink, NgbNavOutlet } from '@ng-bootstrap/ng-bootstrap';
import { Store } from '@ngrx/store';
import { ApplicationDevtoolsModule } from '@o3r/application';
import { ComponentsDevtoolsModule } from '@o3r/components';
import { ConfigOverrideStoreModule, ConfigurationBaseServiceModule, ConfigurationDevtoolsModule } from '@o3r/configuration';
Expand All @@ -23,8 +22,7 @@ import {
RulesEngineDevtoolsModule,
RulesEngineRunnerModule,
RulesEngineRunnerService,
RulesetsStore,
setRulesetsEntities,
Ruleset,
UnaryOperator
} from '@o3r/rules-engine';
import { firstValueFrom } from 'rxjs';
Expand Down Expand Up @@ -84,9 +82,8 @@ export class RulesEngineComponent implements AfterViewInit {
private readonly inPageNavPresService: InPageNavPresService,
private readonly dynamicContentService: DynamicContentService,
private readonly tripFactsService: TripFactsService,
private readonly rulesEngineService: RulesEngineRunnerService,
public currentTimeFactsService: CurrentTimeFactsService,
private readonly store: Store<RulesetsStore>,
rulesEngineService: RulesEngineRunnerService,
configHandle: ConfigurationRulesEngineActionHandler,
assetsHandler: AssetRulesEngineActionHandler,
localizationHandler: LocalizationRulesEngineActionHandler
Expand Down Expand Up @@ -119,15 +116,15 @@ export class RulesEngineComponent implements AfterViewInit {
);

const resultCall = await fetch(path);
const result = await resultCall.json();
const result = await resultCall.json() as {rulesets: Ruleset[]};

this.store.dispatch(setRulesetsEntities({ entities: result.rulesets }));
this.rulesEngineService.upsertRulesets(result.rulesets);
const [
newYorkAvailableRule,
helloNewYorkRule,
summerOtterRule,
lateOtterRule
] = result.rulesets[0].rules as Rule[];
] = result.rulesets[0].rules;
this.newYorkAvailableRule = JSON.stringify(this.formatRule(newYorkAvailableRule), null, 2);
this.helloNewYorkRule = JSON.stringify(this.formatRule(helloNewYorkRule), null, 2);
this.summerOtterRule = JSON.stringify(this.formatRule(summerOtterRule), null, 2);
Expand Down
3 changes: 2 additions & 1 deletion apps/showcase/src/assets/locales/en-GB.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"o3r-rules-engine-pres.whenQuestion": "When do you want to go?"
"o3r-rules-engine-pres.whenQuestion": "When do you want to go?",
"o3r-rules-engine-pres.hurry-up-question": "You are leaving soon, where will you go?"
}
114 changes: 104 additions & 10 deletions apps/showcase/src/assets/rules/rulesets.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,25 @@
"id": "6194b61a-1bf3-4c02-8b7c-20f782d68324",
"name": "rules-engine",
"disabled": false,
"validityRange": {
"from": "09/01/2021",
"to": "11/01/2025"
},

"linkedComponents": {
"or": [{
"library": "showcase",
"name": "RulesEnginePresConfig"
}]
},
"rules": [
{
"id": "5467e501-b9ff-414f-8026-56885d0d7a4b",
"name": "New-York availability",
"disabled": false,
"outputRuntimeFacts": [],
"outputRuntimeFacts": ["MY_FACT_UPDATE"],
"inputRuntimeFacts": [],
"inputFacts": ["outboundDate"],
"rootElement": {
"elementType": "RULE_BLOCK",
"blockType": "IF_ELSE",
Expand Down Expand Up @@ -41,11 +53,19 @@
"library": "showcase",
"property": "destinations",
"value": [
{ "cityCode": "LON", "available": true },
{ "cityCode": "PAR", "available": true },
{ "cityCode": "NYC", "available": true }
{
"cityCode": "LON",
"available": true
},
{
"cityCode": "PAR",
"available": true
},
{
"cityCode": "NYC",
"available": true
}
]

}
],
"failureElements": []
Expand Down Expand Up @@ -79,12 +99,41 @@
"value": "o3r-rules-engine-pres.whenQuestion"
}
],
"failureElements": []
"failureElements": [
{
"elementType": "RULE_BLOCK",
"blockType": "IF_ELSE",
"condition": {
"any": [
{
"lhs": {
"type": "FACT",
"value": "outboundDate"
},
"rhs": {
"type": "LITERAL",
"value": "2880"
},
"operator": "dateInNextMinutes"
}
]
},
"successElements": [
{
"elementType": "ACTION",
"actionType": "UPDATE_LOCALISATION",
"key": "o3r-rules-engine-pres.question",
"value": "o3r-rules-engine-pres.hurry-up-question"
}
],
"failureElements": []
}
]
}
},
{
"id": "5467e501-b9ff-414f-8026-56885d0d7a4d",
"name":"The otter is on vacation",
"name": "The otter is on vacation",
"disabled": false,
"outputRuntimeFacts": [],
"inputRuntimeFacts": [],
Expand Down Expand Up @@ -120,6 +169,50 @@
"failureElements": []
}
},
{
"id": "5467e501-b9ff-414f-8026-56885d0d7a4d",
"name": "The otter is on vacation 2",
"disabled": false,
"outputRuntimeFacts": [],
"inputRuntimeFacts": [],
"rootElement": {
"elementType": "RULE_BLOCK",
"blockType": "IF_ELSE",
"condition": {
"all": [
{
"lhs": {
"type": "FACT",
"value": "outboundDate"
},
"operator": "isDefined"
},
{
"lhs": {
"type": "FACT",
"value": "outboundDate"
},
"operator": "duringSummer"
}
]
},
"successElements": [
{
"elementType": "ACTION",
"actionType": "UPDATE_ASSET",
"asset": "otter.svg",
"value": "otter-summer.svg"
}

],
"failureElements": [ {
"elementType": "ACTION",
"actionType": "SET_FACT",
"fact": "MY_FACT_UPDATE",
"value": "FALSE"
}]
}
},
{
"id": "5467e501-b9ff-414f-8026-56885d0d7a4c",
"name": "The otter is late",
Expand All @@ -137,8 +230,8 @@
"value": "outboundDate"
},
"rhs": {
"type": "LITERAL",
"value": "2880"
"type": "LITERAL",
"value": "2880"
},
"operator": "dateInNextMinutes"
}
Expand All @@ -155,7 +248,8 @@
"failureElements": []
}
}
]
],
"description": ""
},
{
"id": "5945e501-b9ff-414f-8025-56885d0d7a4b-5945e501-b9ff-414f-8025-56885d0d7a4b",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ConfigObserver, ConfigurationBaseService, ConfigurationObserver, Dynami
import { O3rComponent } from '@o3r/core';
import { DynamicContentModule } from '@o3r/dynamic-content';
import { Localization, LocalizationModule, LocalizationService, Translatable } from '@o3r/localization';
import { RulesEngineRunnerModule } from '@o3r/rules-engine';
import {RulesEngineRunnerModule, RulesEngineRunnerService} from '@o3r/rules-engine';
import { distinctUntilChanged, map, Observable, Subscription } from 'rxjs';
import { TripFactsService } from '../../../facts/trip/trip.facts';
import { DatePickerInputPresComponent } from '../../utilities';
Expand Down Expand Up @@ -65,6 +65,7 @@ export class RulesEnginePresComponent implements OnDestroy, OnChanges, DynamicCo
@Optional() configurationService: ConfigurationBaseService,
fb: FormBuilder,
tripService: TripFactsService,
public readonly rulesService: RulesEngineRunnerService,
localizationService: LocalizationService
) {
this.dynamicConfig$ = new ConfigurationObserver<RulesEnginePresConfig>(RULES_ENGINE_PRES_CONFIG_ID, RULES_ENGINE_PRES_DEFAULT_CONFIG, configurationService);
Expand Down Expand Up @@ -110,12 +111,17 @@ export class RulesEnginePresComponent implements OnDestroy, OnChanges, DynamicCo
private formatDate(dateTime: number) {
return formatDate(dateTime, 'yyyy-MM-dd', 'en-GB');
}
public ngOnInit() {
this.rulesService.enableRuleSetFor(RULES_ENGINE_PRES_CONFIG_ID);

}
public ngOnChanges(changes: SimpleChanges) {
if (changes.config) {
this.dynamicConfig$.next(this.config);
}
}
public ngOnDestroy() {
this.rulesService.disableRuleSetFor(RULES_ENGINE_PRES_CONFIG_ID);
this.subscription.unsubscribe();
}

Expand Down
100 changes: 100 additions & 0 deletions docs/components/PLACEHOLDERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ The component only has 1 input and supports a *content value*.
- The *content value* (or child nodes), if provided, will be used by the placeholder component as default display when
no template has been found.

## Supported features (check how-it-works section for more details)

* HTML limited to Angular sanitizer supported behavior
* URLs (relative ones will be processed to add the `dynamic-media-path`)
* Facts references
* Dynamic translation

## How it works

Based on the **id** provided to the placeholder component, it will register itself to the event coming from **placeholderTemplate** and will display the template corresponding to its ID in the store.
Expand Down Expand Up @@ -81,6 +88,49 @@ export class MyComponentModule {
export class MyComponent {
}
```
The loading message is provided by projection. Feel free to provide a spinner if you need.

### How to generate your placeholder metadata

Once your placeholder has been created, you will need to manually create the metadata file and add the path to the
extract-components property in your angular.json
Metadata file example:

```json
[
{
"library": "@scope/app",
"name": "ExampleComponent",
"placeholders": [
{
"id": "pl2358lv-2c63-42e1-b450-6aafd91fbae8",
"description": "Example component placeholder from app"
}
]
}
]
```

And then, in the `angular.json` file:

```json5
{
//...
"extract-components": {
"builder": "@o3r/components:extractor",
"options": {
"tsConfig": "./tsconfig.cms.json",
"libraries": [
"@scope/components"
],
"placeholdersMetadataFilePath": "placeholders.metadata.manual.json"
}
}
//...
}
```

The placeholders will be merged inside the component metadata file that will be sent to the CMS.

### Static localization

Expand Down Expand Up @@ -346,3 +396,53 @@ depend on the event itself (Easter or next Summer Holidays for example).
This means that ``increment`` might have a different value depending on the context of the page which might be tricky to
maintain and to debug.
Try to keep it as simple as possible.

[//]: # (These sections come from the placeholder.md and should be reworked in a dedicated PR)
### Multiple templates in same placeholder

You can use placeholder actions to target the same placeholderId with different template URLs.
It groups the rendered templates in the same placeholder, and you can choose the order by using the `priority` attribute
in the action.
If not specified, the priority defaults to 0. Then the higher the number, the higher the priority. The final results are
displayed in descending order of priority.
The placeholder component waits for all the calls to be resolved (not pending) to display the content.
The placeholder component ignores a template if the application failed to retrieve it.


## Reference CSS classes from an external styling file

You need to reference one or several CSS files from your application in the `cms.json` file:

```json
{
"assetsFolder": "dist/assets",
"libraries": [
{
"npmName": "@o3r/styling"
}
],
"defaultLanguage": "en-GB",
"placeholderCssFiles": [
"dist/assets/placeholders/placeholders.css"
]
}
```

Those files will be loaded by the CMS to show the placeholder preview.
Note that you could provide an empty file and update it with the dynamic content mechanism from AEM, to be able to
reference the new classes afterward.
There is just no user-friendly editor available yet.
You can include this file in your application using the style loader service in your app component:

```typescript
this.styleLoader.asyncLoadStyleFromDynamicContent({id: 'placeholders-styling', href: 'assets/rules/placeholders.css'});
```


## Investigate issues

If the placeholder is not rendered properly, you can perform several checks to find out the root cause, simply looking
at the store state.

Example:
![store-state.png](../../.attachments/screenshots/rules-engine-debug/store_state.png)

0 comments on commit 1ce95b0

Please sign in to comment.