UNPKG

ionic-logging-viewer

Version:

Viewer component for logs written by ionic-logging-service

402 lines (393 loc) 27.1 kB
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: * * &lt;ionic-logging-viewer>&lt;/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: * * &lt;ionic-logging-viewer-levels>&lt;/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: * * &lt;ionic-logging-viewer-search placeholder="Search">&lt;/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