ionic-logging-viewer
Version:
Viewer component for logs written by ionic-logging-service
402 lines (393 loc) • 27.1 kB
JavaScript
import * as i0 from '@angular/core';
import { inject, signal, Injectable, input, computed, effect, Component } from '@angular/core';
import { LoggingService, LogLevelConverter } from 'ionic-logging-service';
import * as i1 from '@ionic/angular';
import { IonicModule, Platform, AlertController, ModalController } from '@ionic/angular';
import { DatePipe } from '@angular/common';
import * as i2 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { addIcons } from 'ionicons';
import { trashOutline, closeCircle } from 'ionicons/icons';
/**
* Service for storing filter settings for logging viewer.
*/
class LoggingViewerFilterService {
/**
* Creates a new instance of the service.
*
* @param loggingService needed for internal logging.
*/
constructor() {
this.loggingService = inject(LoggingService);
/**
* Signal for the current log level.
*/
this.level = signal("DEBUG", /* @ts-ignore */
...(ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []));
/**
* Signal for the current search value.
*/
this.search = signal("", /* @ts-ignore */
...(ngDevMode ? [{ debugName: "search" }] : /* istanbul ignore next */ []));
this.logger = this.loggingService.getLogger("Ionic.Logging.Viewer.Filter.Service");
const methodName = "ctor";
this.logger.entry(methodName);
this.logger.exit(methodName);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerFilterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerFilterService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerFilterService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [] });
/**
* Component for displaying the current logs.
*
* The component can be embedded in any web page using:
*
* <ionic-logging-viewer></ionic-logging-viewer>
*/
class LoggingViewerComponent {
/**
* Creates a new instance of the component.
*/
constructor() {
this.loggingService = inject(LoggingService);
this.loggingViewerFilterService = inject(LoggingViewerFilterService);
/**
* Comma-separated list of localStorageKeys. If set, the logs get loaded from localStorage instead of memory.
*/
this.localStorageKeys = input(undefined, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "localStorageKeys" }] : /* istanbul ignore next */ []));
/**
* Log messages which fulfill the filter condition.
*/
this.logMessagesForDisplay = signal([], /* @ts-ignore */
...(ngDevMode ? [{ debugName: "logMessagesForDisplay" }] : /* istanbul ignore next */ []));
this.logMessages = computed(() => {
const localStorageKeys = this.localStorageKeys();
if (localStorageKeys) {
let messages = [];
for (const localStorageKey of localStorageKeys.split(",")) {
messages = messages.concat(this.loggingService.getLogMessagesFromLocalStorage(localStorageKey));
}
return messages.sort((a, b) => a.timeStamp.getTime() - b.timeStamp.getTime());
}
else {
return this.loggingService.getLogMessages()();
}
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "logMessages" }] : /* istanbul ignore next */ []));
this.logger = this.loggingService.getLogger("Ionic.Logging.Viewer.Component");
const methodName = "ctor";
this.logger.entry(methodName);
// refresh the messages, when messages or filter are modified
effect(() => {
const logMessages = this.logMessages();
const level = this.loggingViewerFilterService.level();
const search = this.loggingViewerFilterService.search();
this.filterLogMessages(logMessages, level, search);
});
this.logger.exit(methodName);
}
/**
* Filter the log messages.
*/
filterLogMessages(logMessages, level, search) {
this.logMessagesForDisplay.set(logMessages.filter((message) => this.filterLogMessagesByLevel(message, level) && this.filterLogMessagesBySearch(message, search)));
}
/**
* Check if the log message's level fulfills the level condition.
*
* @param message the log message to check
* @returns true if check was successful
*/
filterLogMessagesByLevel(message, level) {
return LogLevelConverter.levelFromString(message.level) >= LogLevelConverter.levelFromString(level);
}
/**
* Check if the log message fulfills the search condition.
*
* The search value gets searched in:
* - logger name
* - method name
* - message
*
* @param message the log message to check
* @returns true if check was successful
*/
filterLogMessagesBySearch(message, search) {
if (!message.logger || !message.methodName || !message.message) {
return false;
}
const searchRegex = new RegExp(search, "i");
return message.logger.search(searchRegex) >= 0 ||
message.methodName.search(searchRegex) >= 0 ||
message.message.join("|").search(searchRegex) >= 0;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: LoggingViewerComponent, isStandalone: true, selector: "ionic-logging-viewer", inputs: { localStorageKeys: { classPropertyName: "localStorageKeys", publicName: "localStorageKeys", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ion-list>\n @for (logMessage of logMessagesForDisplay(); track logMessage) {\n <ion-item>\n <ion-label>\n <p>{{ logMessage.timeStamp | date:'dd.MM.yyyy HH:mm:ss' }} {{ logMessage.level }}</p>\n <p>{{ logMessage.logger }}</p>\n <p>\n {{ logMessage.methodName }}\n @for (messagePart of logMessage.message; track messagePart) {\n <span> {{ messagePart }} </span>\n }\n </p>\n </ion-label>\n </ion-item>\n }\n</ion-list>", styles: [""], dependencies: [{ kind: "ngmodule", type: IonicModule }, { kind: "component", type: i1.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "pipe", type: DatePipe, name: "date" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerComponent, decorators: [{
type: Component,
args: [{ selector: "ionic-logging-viewer", imports: [IonicModule, DatePipe], template: "<ion-list>\n @for (logMessage of logMessagesForDisplay(); track logMessage) {\n <ion-item>\n <ion-label>\n <p>{{ logMessage.timeStamp | date:'dd.MM.yyyy HH:mm:ss' }} {{ logMessage.level }}</p>\n <p>{{ logMessage.logger }}</p>\n <p>\n {{ logMessage.methodName }}\n @for (messagePart of logMessage.message; track messagePart) {\n <span> {{ messagePart }} </span>\n }\n </p>\n </ion-label>\n </ion-item>\n }\n</ion-list>" }]
}], ctorParameters: () => [], propDecorators: { localStorageKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "localStorageKeys", required: false }] }] } });
/**
* Component for displaying the log levels for filtering the current logs.
*
* The component can be embedded in any web page using:
*
* <ionic-logging-viewer-levels></ionic-logging-viewer-levels>
*/
class LoggingViewerLevelsComponent {
/**
* Creates a new instance of the component.
*/
constructor() {
this.loggingService = inject(LoggingService);
this.loggingViewerFilterService = inject(LoggingViewerFilterService);
/**
* Selected level.
*/
this.selectedLevel = "";
this.logger = this.loggingService.getLogger("Ionic.Logging.Viewer.Levels.Component");
const methodName = "ctor";
this.logger.entry(methodName);
this.logLevels = [];
this.logLevels.push("DEBUG", "INFO", "WARN", "ERROR");
// handle signals of loggingViewerFilterService, to refresh,
// when someone else modifies the level
effect(() => {
const level = this.loggingViewerFilterService.level();
this.selectedLevel = level;
});
this.logger.exit(methodName);
}
/**
* Callback when the level was changed in the UI.
*/
onLevelChanged() {
const methodName = "onLevelChanged";
this.logger.entry(methodName, this.selectedLevel);
this.loggingViewerFilterService.level.set(this.selectedLevel);
this.logger.exit(methodName);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerLevelsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: LoggingViewerLevelsComponent, isStandalone: true, selector: "ionic-logging-viewer-levels", ngImport: i0, template: "<ion-segment [(ngModel)]=\"selectedLevel\" (ionChange)=\"onLevelChanged()\">\n @for (logLevel of logLevels; track logLevel) {\n <ion-segment-button [value]=\"logLevel\">\n <ion-label>{{ logLevel }}</ion-label>\n </ion-segment-button>\n }\n</ion-segment>", styles: [""], dependencies: [{ kind: "ngmodule", type: IonicModule }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i1.IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: i1.IonSegmentButton, selector: "ion-segment-button", inputs: ["contentId", "disabled", "layout", "mode", "type", "value"] }, { kind: "directive", type: i1.SelectValueAccessor, selector: "ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerLevelsComponent, decorators: [{
type: Component,
args: [{ selector: "ionic-logging-viewer-levels", imports: [IonicModule, FormsModule], template: "<ion-segment [(ngModel)]=\"selectedLevel\" (ionChange)=\"onLevelChanged()\">\n @for (logLevel of logLevels; track logLevel) {\n <ion-segment-button [value]=\"logLevel\">\n <ion-label>{{ logLevel }}</ion-label>\n </ion-segment-button>\n }\n</ion-segment>" }]
}], ctorParameters: () => [] });
/**
* Component for displaying the search bar for filtering the current logs.
*
* The component can be embedded in any web page using:
*
* <ionic-logging-viewer-search placeholder="Search"></ionic-logging-viewer-search>
*/
class LoggingViewerSearchComponent {
/**
* Creates a new instance of the component.
*/
constructor() {
this.loggingService = inject(LoggingService);
this.loggingViewerFilterService = inject(LoggingViewerFilterService);
/**
* Placeholder to be shown in the empty search bar.
*/
this.placeholder = input(undefined, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
/**
* Current search value.
*/
this.search = "";
this.logger = this.loggingService.getLogger("Ionic.Logging.Viewer.Search.Component");
const methodName = "ctor";
this.logger.entry(methodName);
// handle signals of loggingViewerFilterService, to refresh,
// when someone else modifies the search value
effect(() => {
const search = this.loggingViewerFilterService.search();
this.search = search;
});
this.logger.exit(methodName);
}
/**
* Callback when the search value was changed in the UI.
*/
onSearchChanged() {
const methodName = "onSearchChanged";
this.logger.entry(methodName, this.search);
this.loggingViewerFilterService.search.set(this.search);
this.logger.exit(methodName);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.0", type: LoggingViewerSearchComponent, isStandalone: true, selector: "ionic-logging-viewer-search", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ion-searchbar placeholder=\"{{placeholder() || 'Search'}}\" [(ngModel)]=\"search\" [debounce]=\"1000\"\n (ionInput)=\"onSearchChanged()\"></ion-searchbar>", styles: ["ion-searchbar{padding-top:3px;padding-bottom:0}\n"], dependencies: [{ kind: "ngmodule", type: IonicModule }, { kind: "component", type: i1.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocapitalize", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "maxlength", "minlength", "mode", "name", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }, { kind: "directive", type: i1.TextValueAccessor, selector: "ion-input:not([type=number]),ion-input-otp[type=text],ion-textarea,ion-searchbar" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerSearchComponent, decorators: [{
type: Component,
args: [{ selector: "ionic-logging-viewer-search", imports: [IonicModule, FormsModule], template: "<ion-searchbar placeholder=\"{{placeholder() || 'Search'}}\" [(ngModel)]=\"search\" [debounce]=\"1000\"\n (ionInput)=\"onSearchChanged()\"></ion-searchbar>", styles: ["ion-searchbar{padding-top:3px;padding-bottom:0}\n"] }]
}], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
/**
* Ionic modal containing [LoggingViewerComponent](LoggingViewerComponent.html),
* [LoggingViewerLevelsComponent](LoggingViewerLevelsComponent.html) and
* [LoggingViewerSearchComponent](LoggingViewerSearchComponent.html).
*/
class LoggingViewerModalComponent {
static { this.languageEn = "en"; }
static { this.languageDe = "de"; }
/**
* Creates a new instance of the component.
*/
constructor() {
this.platform = inject(Platform);
this.alertController = inject(AlertController);
this.modalController = inject(ModalController);
this.loggingService = inject(LoggingService);
/**
* Language to be used for the modal.
* Currently supported: en, de
*/
this.language = input(undefined, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "language" }] : /* istanbul ignore next */ []));
/**
* Translation to be used for the modal.
* If specified, the language is ignored.
*/
this.translation = input(undefined, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "translation" }] : /* istanbul ignore next */ []));
/**
* Comma-separated list of localStorageKeys. If set, the logs get loaded from localStorage instead of memory.
*/
this.localStorageKeys = input(undefined, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "localStorageKeys" }] : /* istanbul ignore next */ []));
/**
* Flag showing a delete button, which removes all existing log messages.
*/
this.allowClearLogs = input(true, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "allowClearLogs" }] : /* istanbul ignore next */ []));
this.translations = {};
this.logger = this.
loggingService.getLogger("Ionic.Logging.Viewer.Modal.Component");
const methodName = "ctor";
this.logger.entry(methodName);
this.isAndroid = this.platform.is("android");
addIcons({ closeCircle, trashOutline });
this.logger.exit(methodName);
}
/**
* Initializes the LoggingViewerModalComponent.
* It configures the supported translations.
*/
ngOnInit() {
// prepare translations
this.translations = {};
this.translations[LoggingViewerModalComponent.languageEn] = {
cancel: "Cancel",
confirmDelete: "Delete all log messages?",
ok: "Ok",
searchPlaceholder: "Search",
title: "Logging",
};
this.translations[LoggingViewerModalComponent.languageDe] = {
cancel: "Abbrechen",
confirmDelete: "Alle Logs löschen?",
ok: "Ok",
searchPlaceholder: "Suchen",
title: "Logging",
};
}
/**
* Eventhandler called by Ionic when the modal is opened.
*/
ionViewDidEnter() {
const methodName = "ionViewDidEnter";
this.logger.entry(methodName);
this.logger.exit(methodName);
}
/**
* Eventhandler called when the cancel button is clicked.
*/
async onClose() {
const methodName = "onClose";
this.logger.entry(methodName);
await this.modalController.dismiss();
this.logger.exit(methodName);
}
/**
* Eventhandler called when the clear button is clicked.
*/
async onClearLogs() {
const methodName = "onClearLogs";
this.logger.entry(methodName);
const alert = await this.alertController.create({
header: this.getTranslation().confirmDelete,
buttons: [
{
text: this.getTranslation().cancel,
role: "cancel",
cssClass: "secondary"
},
{
text: this.getTranslation().ok,
handler: () => {
this.clearLogs();
}
},
]
});
await alert.present();
this.logger.exit(methodName);
}
/**
* Clear logs.
*/
clearLogs() {
const localStorageKeys = this.localStorageKeys();
if (localStorageKeys) {
for (const localStorageKey of localStorageKeys.split(",")) {
this.loggingService.removeLogMessagesFromLocalStorage(localStorageKey);
}
}
else {
this.loggingService.removeLogMessages();
}
}
/**
* Helper method returning the current translation:
* - the property translation if defined
* - the translation according property language if valid
* - English translation, otherwise
*/
getTranslation() {
const language = this.language();
const translation = this.translation();
if (typeof translation !== "undefined") {
return translation;
}
else if (typeof language !== "undefined" && typeof this.translations[language] === "object") {
return this.translations[language];
}
else {
return this.translations[LoggingViewerModalComponent.languageEn];
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: LoggingViewerModalComponent, isStandalone: true, selector: "ionic-logging-viewer-modal", inputs: { language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, translation: { classPropertyName: "translation", publicName: "translation", isSignal: true, isRequired: false, transformFunction: null }, localStorageKeys: { classPropertyName: "localStorageKeys", publicName: "localStorageKeys", isSignal: true, isRequired: false, transformFunction: null }, allowClearLogs: { classPropertyName: "allowClearLogs", publicName: "allowClearLogs", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ion-header>\n <ion-toolbar color=primary>\n <ion-title>{{ getTranslation().title }}</ion-title>\n <ion-buttons slot=\"start\">\n @if (!isAndroid) {\n <ion-button (click)=\"onClose()\">\n {{ getTranslation().cancel }}\n </ion-button>\n } @else {\n <ion-button icon-only (click)=\"onClose()\">\n <ion-icon name=\"close-circle\"></ion-icon>\n </ion-button>\n }\n </ion-buttons>\n </ion-toolbar>\n <ion-toolbar>\n <ionic-logging-viewer-search [placeholder]=\"getTranslation().searchPlaceholder\"></ionic-logging-viewer-search>\n @if (allowClearLogs() !== false) {\n <ion-buttons slot=\"end\" class=\"clearLogs\">\n <ion-button (click)=\"onClearLogs()\">\n <ion-icon name=\"trash-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n }\n </ion-toolbar>\n <ion-toolbar>\n <ionic-logging-viewer-levels></ionic-logging-viewer-levels>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ionic-logging-viewer [localStorageKeys]=\"localStorageKeys()\"></ionic-logging-viewer>\n</ion-content>", styles: ["ionic-logging-viewer-levels{width:100%;padding-left:12px;padding-right:12px}.clearLogs{padding-top:3px}\n"], dependencies: [{ kind: "ngmodule", type: IonicModule }, { kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: LoggingViewerSearchComponent, selector: "ionic-logging-viewer-search", inputs: ["placeholder"] }, { kind: "component", type: LoggingViewerLevelsComponent, selector: "ionic-logging-viewer-levels" }, { kind: "component", type: LoggingViewerComponent, selector: "ionic-logging-viewer", inputs: ["localStorageKeys"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LoggingViewerModalComponent, decorators: [{
type: Component,
args: [{ selector: "ionic-logging-viewer-modal", imports: [IonicModule, LoggingViewerSearchComponent, LoggingViewerLevelsComponent, LoggingViewerComponent], template: "<ion-header>\n <ion-toolbar color=primary>\n <ion-title>{{ getTranslation().title }}</ion-title>\n <ion-buttons slot=\"start\">\n @if (!isAndroid) {\n <ion-button (click)=\"onClose()\">\n {{ getTranslation().cancel }}\n </ion-button>\n } @else {\n <ion-button icon-only (click)=\"onClose()\">\n <ion-icon name=\"close-circle\"></ion-icon>\n </ion-button>\n }\n </ion-buttons>\n </ion-toolbar>\n <ion-toolbar>\n <ionic-logging-viewer-search [placeholder]=\"getTranslation().searchPlaceholder\"></ionic-logging-viewer-search>\n @if (allowClearLogs() !== false) {\n <ion-buttons slot=\"end\" class=\"clearLogs\">\n <ion-button (click)=\"onClearLogs()\">\n <ion-icon name=\"trash-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n }\n </ion-toolbar>\n <ion-toolbar>\n <ionic-logging-viewer-levels></ionic-logging-viewer-levels>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ionic-logging-viewer [localStorageKeys]=\"localStorageKeys()\"></ionic-logging-viewer>\n</ion-content>", styles: ["ionic-logging-viewer-levels{width:100%;padding-left:12px;padding-right:12px}.clearLogs{padding-top:3px}\n"] }]
}], ctorParameters: () => [], propDecorators: { language: [{ type: i0.Input, args: [{ isSignal: true, alias: "language", required: false }] }], translation: [{ type: i0.Input, args: [{ isSignal: true, alias: "translation", required: false }] }], localStorageKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "localStorageKeys", required: false }] }], allowClearLogs: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowClearLogs", required: false }] }] } });
/*
* Public API Surface of ionic-logging-viewer
*/
/**
* Generated bundle index. Do not edit.
*/
export { LoggingViewerComponent, LoggingViewerLevelsComponent, LoggingViewerModalComponent, LoggingViewerSearchComponent };
//# sourceMappingURL=ionic-logging-viewer.mjs.map