2
0
Fork 0

MOBILE-4268 core: Refactor error accordion into service

main
Noel De Martin 2024-03-19 10:57:46 +01:00
parent 6b461b035e
commit dcf9439eb7
6 changed files with 26 additions and 56 deletions

View File

@ -1,6 +0,0 @@
<!--
The markup for this component is rendered dynamically using the static render() method
instead of using Angular's engine. The reason for using this approach is that this
allows injecting this component into HTML directly, rather than requiring Angular
to control its lifecycle. This is necessary, for example, to render within alerts.
-->

View File

@ -40,7 +40,7 @@ import { CoreForms } from '@singletons/form';
import { AlertButton } from '@ionic/core'; import { AlertButton } from '@ionic/core';
import { CoreSiteError, CoreSiteErrorDebug } from '@classes/errors/siteerror'; import { CoreSiteError, CoreSiteErrorDebug } from '@classes/errors/siteerror';
import { CoreUserSupport } from '@features/user/services/support'; import { CoreUserSupport } from '@features/user/services/support';
import { CoreErrorAccordionComponent } from '@components/error-accordion/error-accordion'; import { CoreErrorAccordion } from '@services/error-accordion';
import { CoreUserSupportConfig } from '@features/user/classes/support/support-config'; import { CoreUserSupportConfig } from '@features/user/classes/support/support-config';
import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config'; import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config';
import { CoreLoginError } from '@classes/errors/loginerror'; import { CoreLoginError } from '@classes/errors/loginerror';
@ -460,7 +460,7 @@ export class CoreLoginSitePage implements OnInit {
const containerElement = alertElement.querySelector('.core-error-accordion-container'); const containerElement = alertElement.querySelector('.core-error-accordion-container');
if (containerElement) { if (containerElement) {
await CoreErrorAccordionComponent.render(containerElement, debug.code, debug.details); await CoreErrorAccordion.render(containerElement, debug.code, debug.details);
} }
} }
} }

View File

@ -12,27 +12,27 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { Component, ElementRef, Input, OnChanges, OnInit } from '@angular/core'; import { Injectable } from '@angular/core';
import { Translate } from '@singletons'; import { Translate, makeSingleton } from '@singletons';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { CoreDom } from '@singletons/dom'; import { CoreDom } from '@singletons/dom';
import { CoreForms } from '@singletons/form'; import { CoreForms } from '@singletons/form';
import { CoreLogger } from '@singletons/logger'; import { CoreLogger } from '@singletons/logger';
const logger = CoreLogger.getInstance('CoreErrorAccordionComponent');
/** /**
* Component to show error details. * Service used to render an Error Accordion component.
* *
* Given that this component has to be injected dynamically in some situations (for example, error alerts), * This is declared as a service instead of an Angular Component because the HTML
* it can be rendered using the static render() method to get the raw HTML. * has to be injected dynamically in alerts (only HTML and Ionic components work).
*/ */
@Component({ @Injectable({ providedIn: 'root' })
selector: 'core-error-accordion', export class CoreErrorAccordionService {
templateUrl: 'core-error-accordion.html',
styleUrls: ['error-accordion.scss'], private logger: CoreLogger;
})
export class CoreErrorAccordionComponent implements OnInit, OnChanges { constructor() {
this.logger = CoreLogger.getInstance('CoreErrorAccordion');
}
/** /**
* Render an instance of the component into an HTML string. * Render an instance of the component into an HTML string.
@ -41,7 +41,7 @@ export class CoreErrorAccordionComponent implements OnInit, OnChanges {
* @param errorCode Error code. * @param errorCode Error code.
* @param errorDetails Error details. * @param errorDetails Error details.
*/ */
static async render(element: Element, errorCode: string, errorDetails: string): Promise<void> { async render(element: Element, errorCode: string, errorDetails: string): Promise<void> {
const html = this.html(errorCode, errorDetails); const html = this.html(errorCode, errorDetails);
element.innerHTML = html; element.innerHTML = html;
@ -56,7 +56,7 @@ export class CoreErrorAccordionComponent implements OnInit, OnChanges {
* @param errorDetails Error details. * @param errorDetails Error details.
* @returns HTML. * @returns HTML.
*/ */
static html(errorCode: string, errorDetails: string): string { private html(errorCode: string, errorDetails: string): string {
const contentId = CoreForms.uniqueId('error-accordion-content'); const contentId = CoreForms.uniqueId('error-accordion-content');
const errorCodeLabel = Translate.instant('core.errorcode', { errorCode }); const errorCodeLabel = Translate.instant('core.errorcode', { errorCode });
const hideDetailsLabel = Translate.instant('core.errordetailshide'); const hideDetailsLabel = Translate.instant('core.errordetailshide');
@ -88,14 +88,14 @@ export class CoreErrorAccordionComponent implements OnInit, OnChanges {
* *
* @param element Root element. * @param element Root element.
*/ */
static async hydrate(element: Element): Promise<void> { private async hydrate(element: Element): Promise<void> {
const wrapper = element.querySelector<HTMLDivElement>('.core-error-accordion'); const wrapper = element.querySelector<HTMLDivElement>('.core-error-accordion');
const description = element.querySelector<HTMLParagraphElement>('.core-error-accordion--details'); const description = element.querySelector<HTMLParagraphElement>('.core-error-accordion--details');
const button = element.querySelector<HTMLButtonElement>('.core-error-accordion--toggle'); const button = element.querySelector<HTMLButtonElement>('.core-error-accordion--toggle');
const hideText = element.querySelector<HTMLSpanElement>('.core-error-accordion--hide-details'); const hideText = element.querySelector<HTMLSpanElement>('.core-error-accordion--hide-details');
if (!wrapper || !description || !button || !hideText) { if (!wrapper || !description || !button || !hideText) {
logger.error('Couldn\'t render error-accordion, one of the child elements is missing'); this.logger.error('Couldn\'t render error-accordion, one of the child elements is missing');
return; return;
} }
@ -118,30 +118,6 @@ export class CoreErrorAccordionComponent implements OnInit, OnChanges {
hideText.style.display = 'revert'; hideText.style.display = 'revert';
} }
@Input() errorCode!: string;
@Input() errorDetails!: string;
constructor(private element: ElementRef<HTMLElement>) {}
/**
* @inheritdoc
*/
ngOnInit(): void {
this.render();
}
/**
* @inheritdoc
*/
ngOnChanges(): void {
this.render();
}
/**
* Render component html in the element created by Angular.
*/
private async render(): Promise<void> {
await CoreErrorAccordionComponent.render(this.element.nativeElement, this.errorCode, this.errorDetails);
}
} }
export const CoreErrorAccordion = makeSingleton(CoreErrorAccordionService);

View File

@ -52,7 +52,7 @@ import { Subscription } from 'rxjs';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreSiteError } from '@classes/errors/siteerror'; import { CoreSiteError } from '@classes/errors/siteerror';
import { CoreUserSupport } from '@features/user/services/support'; import { CoreUserSupport } from '@features/user/services/support';
import { CoreErrorAccordionComponent } from '@components/error-accordion/error-accordion'; import { CoreErrorAccordion } from '@services/error-accordion';
import { CorePlatform } from '@services/platform'; import { CorePlatform } from '@services/platform';
import { CoreCancellablePromise } from '@classes/cancellable-promise'; import { CoreCancellablePromise } from '@classes/cancellable-promise';
import { CoreLang } from '@services/lang'; import { CoreLang } from '@services/lang';
@ -1065,7 +1065,7 @@ export class CoreDomUtilsProvider {
const containerElement = alertElement.querySelector('.core-error-accordion-container'); const containerElement = alertElement.querySelector('.core-error-accordion-container');
if (containerElement) { if (containerElement) {
await CoreErrorAccordionComponent.render(containerElement, error.debug.code, error.debug.details); await CoreErrorAccordion.render(containerElement, error.debug.code, error.debug.details);
} }
} }

View File

@ -22,12 +22,12 @@
/* Components */ /* Components */
@import "components/collapsible-header.scss"; @import "components/collapsible-header.scss";
@import "components/collapsible-item.scss"; @import "components/collapsible-item.scss";
@import "components/error-accordion.scss";
@import "components/format-text.scss"; @import "components/format-text.scss";
@import "components/rubrics.scss";
@import "components/mod-label.scss";
@import "components/ion-icon.scss"; @import "components/ion-icon.scss";
@import "components/mod-label.scss";
@import "components/rubrics.scss";
@import "components/videojs.scss"; @import "components/videojs.scss";
@import "../core/components/error-accordion/error-accordion.scss";
/* Some styles from 3rd party libraries. */ /* Some styles from 3rd party libraries. */
@import "bootstrap.scss"; @import "bootstrap.scss";