Skip to content

Commit

Permalink
feat(chrome-ext): toggle button for placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
matthieu-crouzet committed Apr 10, 2024
1 parent 56e22af commit 7588891
Show file tree
Hide file tree
Showing 29 changed files with 238 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,14 @@ export class DebugPanelPresComponent {
toggle: (event.target as HTMLInputElement).checked
});
}

/**
* Toggle placeholder debug mode
* @param event
*/
public togglePlaceholder(event: UIEvent) {
this.connection.sendMessage('placeholderDebug', {
debug: (event.target as HTMLInputElement).checked
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,17 @@ <h4 class="d-inline-block">Information</h4>
<div>
<h4>Actions</h4>
<div>
<div class="form-check">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" (change)="toggleVisualTestingRender($event)" id="toggleVisualTesting">
<label class="form-check-label" for="toggleVisualTesting">
Toggle visual testing
</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" (change)="togglePlaceholder($event)" id="togglePlaceholder">
<label class="form-check-label" for="togglePlaceholder">
Toggle placeholder debug mode
</label>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</div>
}
</div>
<div class="form-check d-flex flex-column gap-2">
<div class="form-check form-switch d-flex flex-column gap-2">
<div>
<input class="form-check-input" type="checkbox" formControlName="showKeys" id="displayLocalizationKey" [attr.aria-describedby]="isTranslationDeactivationEnabled() ? null : 'show-keys-hint'">
<label class="form-check-label text-nowrap" for="displayLocalizationKey">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<form [formGroup]="form">
@for (item of controlsType() | keyvalue; track item.key) {
<div class="mb-2" [ngClass]="item.value === 'boolean' ? 'form-check' : 'form-group'">
<div class="mb-2" [ngClass]="item.value === 'boolean' ? 'form-check form-switch' : 'form-group'">
@switch (item.value) {
@case ('boolean') {
<input class="form-check-input" [formControlName]="item.key" type="checkbox" [id]="item.key" />
Expand Down
13 changes: 12 additions & 1 deletion apps/showcase/placeholders.metadata.manual.json
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
[]
[
{
"library": "@o3r/showcase",
"name": "PlaceholderComponent",
"placeholders": [
{
"id": "placeholder-showcase",
"description": "Showcase placeholder in app"
}
]
}
]
1 change: 1 addition & 0 deletions apps/showcase/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const appRoutes: Routes = [
{path: 'home', loadComponent: () => import('./home/index').then((m) => m.HomeComponent), title: 'Otter Showcase - Home'},
{path: 'run-app-locally', loadComponent: () => import('./run-app-locally/index').then((m) => m.RunAppLocallyComponent), title: 'Otter Showcase - Run App Locally'},
{path: 'sdk', loadComponent: () => import('./sdk/index').then((m) => m.SdkComponent), title: 'Otter Showcase - SDK'},
{path: 'placeholder', loadComponent: () => import('./placeholder/index').then((m) => m.PlaceholderComponent), title: 'Otter Showcase - Placeholder'},
{path: '**', redirectTo: '/home', pathMatch: 'full'}
];

Expand Down
7 changes: 4 additions & 3 deletions apps/showcase/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ export class AppComponent implements OnDestroy {
]
},
{
label: 'CMS',
label: 'Personalization',
links: [
{ url: '/configuration', label: 'Configuration' },
{ url: '/localization', label: 'Localization' },
{ url: '/design-token', label: 'Design Tokens' },
{ url: '/dynamic-content', label: 'Dynamic content' },
{ url: '/component-replacement', label: 'Component replacement' },
{ url: '/rules-engine', label: 'Rules engine' },
{ url: '/component-replacement', label: 'Component Replacement' },
{ url: '/design-token', label: 'Design Tokens' }
{ url: '/placeholder', label: 'Placeholder' }
]
},
{
Expand Down
1 change: 1 addition & 0 deletions apps/showcase/src/app/placeholder/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './placeholder.component';
48 changes: 48 additions & 0 deletions apps/showcase/src/app/placeholder/placeholder.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { type AfterViewInit, ChangeDetectionStrategy, Component, type QueryList, ViewChildren, ViewEncapsulation } from '@angular/core';
import { RouterModule } from '@angular/router';
import { O3rComponent } from '@o3r/core';
import { PlaceholderModule } from '@o3r/components';
import { PlaceholderRulesEngineActionHandler, PlaceholderRulesEngineActionModule } from '@o3r/components/rules-engine';
import { RulesEngineDevtoolsModule, RulesEngineRunnerModule, RulesEngineRunnerService } from '@o3r/rules-engine';
import { IN_PAGE_NAV_PRES_DIRECTIVES, type InPageNavLink, InPageNavLinkDirective, InPageNavPresService, RulesEnginePresComponent } from '../../components';
import { TripFactsService } from '../../facts';
import { AsyncPipe } from '@angular/common';

@O3rComponent({ componentType: 'Page' })
@Component({
selector: 'o3r-placeholder-page',
standalone: true,
imports: [
RulesEnginePresComponent,
RulesEngineRunnerModule,
RulesEngineDevtoolsModule,
PlaceholderRulesEngineActionModule,
PlaceholderModule,
RouterModule,
IN_PAGE_NAV_PRES_DIRECTIVES,
AsyncPipe
],
templateUrl: './placeholder.template.html',
styleUrl: './placeholder.style.scss',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PlaceholderComponent implements AfterViewInit {
@ViewChildren(InPageNavLinkDirective)
private readonly inPageNavLinkDirectives!: QueryList<InPageNavLink>;
public links$ = this.inPageNavPresService.links$;

constructor(
private readonly inPageNavPresService: InPageNavPresService,
private readonly tripFactsService: TripFactsService,
rulesEngine: RulesEngineRunnerService,
placeholderRulesEngineActionHandler: PlaceholderRulesEngineActionHandler
) {
this.tripFactsService.register();
rulesEngine.actionHandlers.add(placeholderRulesEngineActionHandler);
}

public ngAfterViewInit() {
this.inPageNavPresService.initialize(this.inPageNavLinkDirectives);
}
}
23 changes: 23 additions & 0 deletions apps/showcase/src/app/placeholder/placeholder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { PlaceholderComponent } from './placeholder.component';

describe('PlaceholderComponent', () => {
let component: PlaceholderComponent;
let fixture: ComponentFixture<PlaceholderComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [PlaceholderComponent]
})
.compileComponents();

fixture = TestBed.createComponent(PlaceholderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
3 changes: 3 additions & 0 deletions apps/showcase/src/app/placeholder/placeholder.style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
o3r-placeholder {

}
32 changes: 32 additions & 0 deletions apps/showcase/src/app/placeholder/placeholder.template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<h1>Placeholder</h1>
<div class="row">
<div class="right-nav order-1 order-lg-2 col-12 col-lg-2 sticky-lg-top pt-5 pt-lg-0">
<o3r-in-page-nav-pres
id="localization-nav"
[links]="links$ | async"
>
</o3r-in-page-nav-pres>
</div>
<div class="order-2 order-lg-1 col-12 col-lg-10">
<h2 id="localization-description">Description</h2>
<div>
<p>The Otter framework provides a placeholder component mechanism to help integrate dynamic HTML elements (with a basic rendering system) at a predefined position in the application.</p>
</div>

<h2 id="localization-example">Example</h2>
<div class="d-flex flex-column">
<o3r-placeholder id="placeholder-showcase">
Placeholder is loading...
</o3r-placeholder>
<o3r-rules-engine-pres></o3r-rules-engine-pres>
</div>
<h2 id="localization-references">References</h2>
<div>
<ul>
<li>
<a href="https://github.com/AmadeusITGroup/otter/blob/main/docs/components/PLACEHOLDERS.md" target="_blank" rel="noopener">Placeholder documentation</a>
</li>
</ul>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"template": "<p>My fact: <%= outboundDate %></p>",
"vars": {
"outboundDate": {
"value": "outboundDate",
"type": "fact"
}
}
}
14 changes: 1 addition & 13 deletions apps/showcase/src/style/dark-theme/dark-theme.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
@import "highlight.js/styles/a11y-dark.css";

:root {
/* --- BEGIN THEME Auto-generated --- */
Expand Down Expand Up @@ -97,15 +96,4 @@
.card { --bs-card-color: #ffffff; }
.card { --bs-card-bg: #000000; }
/* --- END THEME Auto-generated --- */

.nav.nav-pills .nav-link {
--bs-scrollspy-color: #ffffff;
--bs-nav-pills-link-active-bg: transparent;
}
.input-group-text {
background-color: var(--bs-tertiary-bg);
}
.form-select {
--bs-form-select-bg-img: url("data:image/svg+xml;charset=utf8,%3Csvg version='1.1' viewBox='0 0 1792 1792' style='fill%3a%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z'/%3E%3C/svg%3E");
}
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
"@commitlint/cli": "^18.0.0",
"@commitlint/config-conventional": "^18.0.0",
"@compodoc/compodoc": "^1.1.19",
"@design-factory/design-factory": "~17.1.0",
"@ng-bootstrap/ng-bootstrap": "^16.0.0",
"@ngrx/effects": "~17.1.0",
"@ngrx/entity": "~17.1.0",
Expand Down
15 changes: 13 additions & 2 deletions packages/@o3r/components/src/devkit/components-devkit.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ export interface ToggleInspectorMessage extends OtterMessageContent<'toggleInspe
isRunning: boolean;
}

/**
* Message to toggle the placeholder debug mode
*/
export interface PlaceholderDebugMessage extends OtterMessageContent<'placeholderDebug'> {
/** Is the placeholder show in debug mode */
debug: boolean;
}

/**
* Message to know the component selection availability
*/
Expand All @@ -31,7 +39,8 @@ export interface IsComponentSelectionAvailableMessage extends OtterMessageConten
type ComponentsMessageContents =
| IsComponentSelectionAvailableMessage
| SelectedComponentInfoMessage
| ToggleInspectorMessage;
| ToggleInspectorMessage
| PlaceholderDebugMessage;

/** List of possible DataTypes for Components messages */
export type ComponentsMessageDataTypes = MessageDataTypes<ComponentsMessageContents>;
Expand All @@ -52,5 +61,7 @@ export const isComponentsMessage = (message: any): message is AvailableComponent
message.dataType === 'connect' ||
message.dataType === 'selectedComponentInfo' ||
message.dataType === 'isComponentSelectionAvailable' ||
message.dataType === 'toggleInspector');
message.dataType === 'placeholderDebug' ||
message.dataType === 'toggleInspector'
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Inject, Injectable, OnDestroy, Optional } from '@angular/core';
import { DevtoolsServiceInterface, filterMessageContent, sendOtterMessage } from '@o3r/core';
import { LoggerService } from '@o3r/logger';
import { Store } from '@ngrx/store';
import { firstValueFrom, fromEvent, Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { type PlaceholderTemplateState, toggleDebugPlaceholderTemplate } from '../stores';
import { AvailableComponentsMessageContents, ComponentsDevtoolsServiceOptions, ComponentsMessageDataTypes, isComponentsMessage } from './components-devkit.interface';
import { OTTER_COMPONENTS_DEVTOOLS_DEFAULT_OPTIONS, OTTER_COMPONENTS_DEVTOOLS_OPTIONS } from './components-devtools.token';
import { OtterInspectorService, OtterLikeComponentInfo } from './inspector';
Expand All @@ -19,8 +21,10 @@ export class ComponentsDevtoolsMessageService implements OnDestroy, DevtoolsServ
private readonly sendMessage = sendOtterMessage<AvailableComponentsMessageContents>;

constructor(
private readonly logger: LoggerService,
@Optional() @Inject(OTTER_COMPONENTS_DEVTOOLS_OPTIONS) options?: ComponentsDevtoolsServiceOptions) {
private readonly logger: LoggerService,
private readonly store: Store<PlaceholderTemplateState>,
@Optional() @Inject(OTTER_COMPONENTS_DEVTOOLS_OPTIONS) options?: ComponentsDevtoolsServiceOptions
) {
this.options = {
...OTTER_COMPONENTS_DEVTOOLS_DEFAULT_OPTIONS,
...options
Expand Down Expand Up @@ -93,6 +97,10 @@ export class ComponentsDevtoolsMessageService implements OnDestroy, DevtoolsServ
this.inspectorService.toggleInspector(message.isRunning);
break;
}
case 'placeholderDebug': {
this.store.dispatch(toggleDebugPlaceholderTemplate({ debug: message.debug }));
break;
}
default: {
this.logger.warn('Message ignored by the components service', message);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import { PlaceholderTemplateStoreModule } from '../stores/placeholder-template/placeholder-template.module';
import type { ComponentsDevtoolsServiceOptions } from './components-devkit.interface';
import { ComponentsDevtoolsMessageService } from './components-devtools.message.service';
import { OTTER_COMPONENTS_DEVTOOLS_DEFAULT_OPTIONS, OTTER_COMPONENTS_DEVTOOLS_OPTIONS } from './components-devtools.token';

@NgModule({
imports: [
StoreModule
StoreModule,
PlaceholderTemplateStoreModule
],
providers: [
{ provide: OTTER_COMPONENTS_DEVTOOLS_OPTIONS, useValue: OTTER_COMPONENTS_DEVTOOLS_DEFAULT_OPTIONS },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import {PlaceholderTemplateModel} from './placeholder-template.state';

const ACTION_DELETE_ENTITY = '[PlaceholderTemplate] delete entity';
const ACTION_SET_ENTITY = '[PlaceholderTemplate] set entity';
const ACTION_TOGGLE_DEBUG = '[PlaceholderTemplate] toggle debug';

/** Action to delete a specific entity */
export const deletePlaceholderTemplateEntity = createAction(ACTION_DELETE_ENTITY, props<{ id: string }>());

/** Action to clear all placeholderTemplate and fill the store with the payload */
export const setPlaceholderTemplateEntity = createAction(ACTION_SET_ENTITY, props<SetEntityActionPayload<PlaceholderTemplateModel>>());

export const toggleDebugPlaceholderTemplate = createAction(ACTION_TOGGLE_DEBUG, props<{ debug: boolean }>());
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ export const placeholderTemplateAdapter = createEntityAdapter<PlaceholderTemplat
/**
* PlaceholderTemplate Store initial value
*/
export const placeholderTemplateInitialState: PlaceholderTemplateState = placeholderTemplateAdapter.getInitialState();
export const placeholderTemplateInitialState: PlaceholderTemplateState = placeholderTemplateAdapter.getInitialState({
debug: false
});

/**
* List of basic actions for PlaceholderTemplate Store
Expand All @@ -30,6 +32,12 @@ export const placeholderTemplateReducerFeatures: ReducerTypes<PlaceholderTemplat
return state;
}
return placeholderTemplateAdapter.removeOne(id, state);
}),
on(actions.toggleDebugPlaceholderTemplate, (state, payload) => {
return {
...state,
debug: payload.debug
};
})
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ describe('selectPlaceholderRenderedTemplates', () => {
}
]
}
}
},
debug: false
};
placeholderRequestState = {
requestIds: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,6 @@ export const selectPlaceholderRenderedTemplates = (placeholderId: string) => cre
isPending: placeholderData.isPending
};
});


export const selectPlaceholderTemplateDebug = createSelector(selectPlaceholderTemplateState, (state) => state.debug);
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface PlaceholderTemplateModel {
* PlaceholderTemplate store state
*/
export interface PlaceholderTemplateState extends EntityState<PlaceholderTemplateModel> {
debug: boolean;
}

/**
Expand Down
Loading

0 comments on commit 7588891

Please sign in to comment.