@o3r/application
Version:
This module provides development help to monitor your Otter Application
262 lines (252 loc) • 12.4 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, DOCUMENT, Injectable, DestroyRef, NgModule } from '@angular/core';
import { isProductionEnvironment, sendOtterMessage, filterMessageContent } from '@o3r/core';
import { ENVIRONMENT_CONFIG_TOKEN } from '@o3r/routing';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { LoggerService } from '@o3r/logger';
import { fromEvent } from 'rxjs';
/**
* Method that returns the setting of the user regarding animations.
* This setting is generally set in the Operating System settings, and it is used by browsers.
* Refer to: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
*/
function prefersReducedMotion() {
const mediaQueryList = window.matchMedia('(prefers-reduced-motion)');
return mediaQueryList.matches;
}
/**
* Determine if the given message is a Application message
* @param message message to check
*/
const isApplicationMessage = (message) => {
return message && (message.dataType === 'toggleVisualTesting'
|| message.dataType === 'stateSelection'
|| message.dataType === 'applicationInformation'
|| message.dataType === 'unselectState'
|| message.dataType === 'requestMessages'
|| message.dataType === 'connect');
};
const OTTER_APPLICATION_DEVTOOLS_DEFAULT_OPTIONS = {
isActivatedOnBootstrap: false
};
const OTTER_APPLICATION_DEVTOOLS_OPTIONS = new InjectionToken('Otter Application Devtools options');
class OtterApplicationDevtools {
constructor() {
this.options = inject(OTTER_APPLICATION_DEVTOOLS_OPTIONS, { optional: true });
this.document = inject(DOCUMENT, { optional: true });
this.env = inject(ENVIRONMENT_CONFIG_TOKEN, { optional: true });
}
getApplicationInformation() {
return {
appName: this.options?.appName || 'unknown',
appVersion: this.env?.APP_VERSION || 'unknown',
isProduction: isProductionEnvironment(this.document?.body.dataset)
};
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: OtterApplicationDevtools, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: OtterApplicationDevtools, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: OtterApplicationDevtools, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
/* eslint-disable no-console -- purpose of the service is to log in the console */
class ApplicationDevtoolsConsoleService {
/** Name of the Window property to access to the devtools */
static { this.windowModuleName = 'application'; }
constructor() {
this.applicationDevtools = inject(OtterApplicationDevtools);
const options = inject(OTTER_APPLICATION_DEVTOOLS_OPTIONS, { optional: true });
this.options = { ...OTTER_APPLICATION_DEVTOOLS_DEFAULT_OPTIONS, ...options };
if (this.options.isActivatedOnBootstrap) {
this.activate();
}
}
/** @inheritDoc */
activate() {
const windowWithDevtools = window;
windowWithDevtools._OTTER_DEVTOOLS_ ||= {};
windowWithDevtools._OTTER_DEVTOOLS_[ApplicationDevtoolsConsoleService.windowModuleName] = this;
console.info(`Otter Application Devtools is now accessible via the _OTTER_DEVTOOLS_.${ApplicationDevtoolsConsoleService.windowModuleName} variable`);
}
/** Display the information relative to the running application */
displayApplicationInfo() {
console.info('Application info', this.applicationDevtools.getApplicationInformation());
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsConsoleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsConsoleService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsConsoleService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [] });
const OTTER_STATE_RIBBON_ID = 'otter-devtools-state-ribbon';
class ApplicationDevtoolsMessageService {
constructor() {
this.document = inject(DOCUMENT);
this.sendMessage = (sendOtterMessage);
this.destroyRef = inject(DestroyRef);
this.logger = inject(LoggerService);
this.applicationDevtools = inject(OtterApplicationDevtools);
this.options = {
...OTTER_APPLICATION_DEVTOOLS_DEFAULT_OPTIONS,
...inject(OTTER_APPLICATION_DEVTOOLS_OPTIONS, { optional: true })
};
if (this.options.isActivatedOnBootstrap) {
this.activate();
}
}
sendApplicationInformation() {
this.sendMessage('applicationInformation', this.applicationDevtools.getApplicationInformation());
}
/**
* Function to connect the plugin to the Otter DevTools extension
*/
connectPlugin() {
this.logger.debug('Otter DevTools is plugged to application service of the application');
void this.sendApplicationInformation();
}
/**
* Function to trigger a re-send a requested messages to the Otter Chrome DevTools extension
* @param only restricted list of messages to re-send
*/
handleReEmitRequest(only) {
if (!only || only.includes('applicationInformation')) {
this.sendApplicationInformation();
}
}
/**
* Function to handle the incoming messages from Otter Chrome DevTools extension
* @param message
*/
async handleEvents(message) {
this.logger.debug('Message handling by the application service', message);
switch (message.dataType) {
case 'connect': {
this.connectPlugin();
break;
}
case 'requestMessages': {
this.handleReEmitRequest(message.only);
break;
}
case 'toggleVisualTesting': {
await this.toggleVisualTestingRender(message.toggle);
break;
}
case 'stateSelection': {
this.onStateSelection(message);
break;
}
case 'unselectState': {
this.unselectState();
break;
}
default: {
this.logger.warn('Message ignored by the application service', message);
}
}
}
unselectState() {
const ribbonElement = this.document.body.querySelector(`#${OTTER_STATE_RIBBON_ID}`);
if (ribbonElement) {
ribbonElement.remove();
}
}
onStateSelection(message) {
let ribbonElement = this.document.body.querySelector(`#${OTTER_STATE_RIBBON_ID}`);
if (!ribbonElement) {
ribbonElement = this.document.createElement('div');
ribbonElement.id = OTTER_STATE_RIBBON_ID;
this.document.body.append(ribbonElement);
}
if (message.stateName) {
ribbonElement.innerHTML = message.stateName;
ribbonElement.style.background = message.stateColor;
ribbonElement.style.color = message.stateColorContrast;
ribbonElement.style.position = 'fixed';
ribbonElement.style.bottom = '0';
ribbonElement.style.right = '0';
ribbonElement.style.transform = 'translate(calc(100% * (1 - cos(45deg)))) rotate(-45deg)';
ribbonElement.style.transformOrigin = 'bottom left';
ribbonElement.style.clipPath = 'inset(0 -100%)';
ribbonElement.style.boxShadow = `0px 0px 0px 999px ${message.stateColor}`;
}
else {
ribbonElement.style.display = 'none';
}
}
/**
* Toggle visual testing rendering
* @param enabled activate or deactivate the visual testing mode
*/
async toggleVisualTestingRender(enabled) {
try {
const visualTestUtils = await import('@o3r/testing/visual-test/utils');
const isEnabled = enabled ?? visualTestUtils.isVisualTestingEnabled();
visualTestUtils.toggleVisualTestingRender(isEnabled);
}
catch (err) {
this.logger.warn('Visual testing utilities are not available:', err);
}
}
/** @inheritDoc */
activate() {
fromEvent(window, 'message').pipe(takeUntilDestroyed(this.destroyRef), filterMessageContent(isApplicationMessage)).subscribe((e) => this.handleEvents(e));
import('@o3r/testing/visual-test/utils')
.then((visualTestUtils) => visualTestUtils.prepareVisualTesting(this.options.e2eIgnoreClass))
.catch((err) => this.logger.warn('Visual testing utilities are not available:', err));
this.sendApplicationInformation();
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsMessageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsMessageService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsMessageService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [] });
class ApplicationDevtoolsModule {
/**
* Initialize Otter Devtools
* @param options
*/
static instrument(options) {
return {
ngModule: ApplicationDevtoolsModule,
providers: [
{ provide: OTTER_APPLICATION_DEVTOOLS_OPTIONS, useValue: { ...OTTER_APPLICATION_DEVTOOLS_DEFAULT_OPTIONS, ...options }, multi: false },
ApplicationDevtoolsMessageService,
ApplicationDevtoolsConsoleService,
OtterApplicationDevtools
]
};
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsModule }); }
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsModule, providers: [
{ provide: OTTER_APPLICATION_DEVTOOLS_OPTIONS, useValue: OTTER_APPLICATION_DEVTOOLS_DEFAULT_OPTIONS },
ApplicationDevtoolsMessageService,
ApplicationDevtoolsConsoleService,
OtterApplicationDevtools
] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: ApplicationDevtoolsModule, decorators: [{
type: NgModule,
args: [{
providers: [
{ provide: OTTER_APPLICATION_DEVTOOLS_OPTIONS, useValue: OTTER_APPLICATION_DEVTOOLS_DEFAULT_OPTIONS },
ApplicationDevtoolsMessageService,
ApplicationDevtoolsConsoleService,
OtterApplicationDevtools
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { ApplicationDevtoolsConsoleService, ApplicationDevtoolsMessageService, ApplicationDevtoolsModule, OTTER_APPLICATION_DEVTOOLS_DEFAULT_OPTIONS, OTTER_APPLICATION_DEVTOOLS_OPTIONS, OtterApplicationDevtools, isApplicationMessage, prefersReducedMotion };
//# sourceMappingURL=o3r-application.mjs.map