MOBILE-3947 core: Move from ViewEngine to Ivy and fix plugins
parent
22dbd6ad99
commit
4053e2d741
|
@ -12,7 +12,7 @@
|
||||||
// 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 { APP_INITIALIZER, COMPILER_OPTIONS, NgModule } from '@angular/core';
|
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouteReuseStrategy } from '@angular/router';
|
import { RouteReuseStrategy } from '@angular/router';
|
||||||
|
@ -28,7 +28,7 @@ import { AddonsModule } from '@addons/addons.module';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';
|
|
||||||
import { CoreCronDelegate } from '@services/cron';
|
import { CoreCronDelegate } from '@services/cron';
|
||||||
import { CoreSiteInfoCronHandler } from '@services/handlers/site-info-cron';
|
import { CoreSiteInfoCronHandler } from '@services/handlers/site-info-cron';
|
||||||
import { moodleTransitionAnimation } from '@classes/page-transition';
|
import { moodleTransitionAnimation } from '@classes/page-transition';
|
||||||
|
@ -71,8 +71,6 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
|
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
|
||||||
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
|
|
||||||
{ provide: JitCompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
|
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
multi: true,
|
multi: true,
|
||||||
|
|
|
@ -69,7 +69,8 @@ export class CoreDynamicComponent<ComponentClass> implements OnChanges, DoCheck
|
||||||
@Input() data?: Record<string | number, unknown>;
|
@Input() data?: Record<string | number, unknown>;
|
||||||
|
|
||||||
// Get the container where to put the dynamic component.
|
// Get the container where to put the dynamic component.
|
||||||
@ViewChild('dynamicComponent', { read: ViewContainerRef }) set dynamicComponent(el: ViewContainerRef) {
|
@ViewChild('dynamicComponent', { read: ViewContainerRef })
|
||||||
|
set dynamicComponent(el: ViewContainerRef) {
|
||||||
this.container = el;
|
this.container = el;
|
||||||
|
|
||||||
// Use a timeout to avoid ExpressionChangedAfterItHasBeenCheckedError.
|
// Use a timeout to avoid ExpressionChangedAfterItHasBeenCheckedError.
|
||||||
|
@ -94,7 +95,7 @@ export class CoreDynamicComponent<ComponentClass> implements OnChanges, DoCheck
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect changes on input properties.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
|
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
|
||||||
if (changes.component && !this.component) {
|
if (changes.component && !this.component) {
|
||||||
|
@ -108,7 +109,7 @@ export class CoreDynamicComponent<ComponentClass> implements OnChanges, DoCheck
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect and act upon changes that Angular can’t or won’t detect on its own (objects and arrays).
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngDoCheck(): void {
|
ngDoCheck(): void {
|
||||||
if (this.instance) {
|
if (this.instance) {
|
||||||
|
|
|
@ -56,7 +56,7 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'core-compile-html',
|
selector: 'core-compile-html',
|
||||||
template: '<core-loading [hideUntil]="loaded"><ng-container #dynamicComponent></ng-container></core-loading>',
|
template: '<core-loading [hideUntil]="loaded"><ng-container #dynamicComponent /></core-loading>',
|
||||||
styles: [':host { display: contents; }'],
|
styles: [':host { display: contents; }'],
|
||||||
})
|
})
|
||||||
export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
|
@ -66,16 +66,16 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
@Input() jsData?: Record<string, unknown>; // Data to pass to the fake component.
|
@Input() jsData?: Record<string, unknown>; // Data to pass to the fake component.
|
||||||
@Input() extraImports: unknown[] = []; // Extra import modules.
|
@Input() extraImports: unknown[] = []; // Extra import modules.
|
||||||
@Input() extraProviders: Type<unknown>[] = []; // Extra providers.
|
@Input() extraProviders: Type<unknown>[] = []; // Extra providers.
|
||||||
@Input() forceCompile?: boolean; // Set it to true to force compile even if the text/javascript hasn't changed.
|
@Input() forceCompile = false; // Set it to true to force compile even if the text/javascript hasn't changed.
|
||||||
@Output() created = new EventEmitter<unknown>(); // Will emit an event when the component is instantiated.
|
@Output() created = new EventEmitter<unknown>(); // Will emit an event when the component is instantiated.
|
||||||
@Output() compiling = new EventEmitter<boolean>(); // Event that indicates whether the template is being compiled.
|
@Output() compiling = new EventEmitter<boolean>(); // Event that indicates whether the template is being compiled.
|
||||||
|
|
||||||
|
loaded = false;
|
||||||
|
componentInstance?: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
// Get the container where to put the content.
|
// Get the container where to put the content.
|
||||||
@ViewChild('dynamicComponent', { read: ViewContainerRef }) container?: ViewContainerRef;
|
@ViewChild('dynamicComponent', { read: ViewContainerRef }) container?: ViewContainerRef;
|
||||||
|
|
||||||
loaded?: boolean;
|
|
||||||
componentInstance?: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
||||||
|
|
||||||
protected componentRef?: ComponentRef<unknown>;
|
protected componentRef?: ComponentRef<unknown>;
|
||||||
protected element: HTMLElement;
|
protected element: HTMLElement;
|
||||||
protected differ: KeyValueDiffer<unknown, unknown>; // To detect changes in the jsData input.
|
protected differ: KeyValueDiffer<unknown, unknown>; // To detect changes in the jsData input.
|
||||||
|
@ -114,6 +114,10 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async ngOnChanges(changes: Record<string, SimpleChange>): Promise<void> {
|
async ngOnChanges(changes: Record<string, SimpleChange>): Promise<void> {
|
||||||
|
if (!this.container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Only compile if text/javascript has changed or the forceCompile flag has been set to true.
|
// Only compile if text/javascript has changed or the forceCompile flag has been set to true.
|
||||||
if (this.text !== undefined && (changes.text || changes.javascript ||
|
if (this.text !== undefined && (changes.text || changes.javascript ||
|
||||||
(changes.forceCompile && CoreUtils.isTrueOrOne(this.forceCompile)))) {
|
(changes.forceCompile && CoreUtils.isTrueOrOne(this.forceCompile)))) {
|
||||||
|
@ -124,16 +128,18 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const componentClass = await this.getComponentClass();
|
const componentClass = await this.getComponentClass();
|
||||||
const factory = await CoreCompile.createAndCompileComponent(this.text, componentClass, this.extraImports);
|
|
||||||
|
|
||||||
// Destroy previous components.
|
// Destroy previous components.
|
||||||
this.componentRef?.destroy();
|
this.componentRef?.destroy();
|
||||||
|
|
||||||
if (factory) {
|
// Create the component.
|
||||||
// Create the component.
|
this.componentRef = await CoreCompile.createAndCompileComponent(
|
||||||
this.componentRef = this.container?.createComponent(factory);
|
this.text,
|
||||||
this.componentRef && this.created.emit(this.componentRef.instance);
|
componentClass,
|
||||||
}
|
this.container,
|
||||||
|
this.extraImports,
|
||||||
|
);
|
||||||
|
this.componentRef && this.created.emit(this.componentRef.instance);
|
||||||
|
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -192,7 +198,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component being initialized.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// If there is some javascript to run, do it now.
|
// If there is some javascript to run, do it now.
|
||||||
|
@ -204,7 +210,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
for (const name in compileInstance.pendingCalls) {
|
for (const name in compileInstance.pendingCalls) {
|
||||||
const pendingCall = compileInstance.pendingCalls[name];
|
const pendingCall = compileInstance.pendingCalls[name];
|
||||||
|
|
||||||
if (typeof this[name] == 'function') {
|
if (typeof this[name] === 'function') {
|
||||||
// Call the function.
|
// Call the function.
|
||||||
Promise.resolve(this[name].apply(this, pendingCall.params)).then(pendingCall.defer.resolve)
|
Promise.resolve(this[name].apply(this, pendingCall.params)).then(pendingCall.defer.resolve)
|
||||||
.catch(pendingCall.defer.reject);
|
.catch(pendingCall.defer.reject);
|
||||||
|
@ -218,21 +224,21 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Content has been initialized.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngAfterContentInit(): void {
|
ngAfterContentInit(): void {
|
||||||
this.callLifecycleHookOverride('ngAfterContentInit');
|
this.callLifecycleHookOverride('ngAfterContentInit');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View has been initialized.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
this.callLifecycleHookOverride('ngAfterViewInit');
|
this.callLifecycleHookOverride('ngAfterViewInit');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component destroyed.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.callLifecycleHookOverride('ngOnDestroy');
|
this.callLifecycleHookOverride('ngOnDestroy');
|
||||||
|
@ -283,9 +289,9 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||||
* once the component has been created.
|
* once the component has been created.
|
||||||
* @returns Result of the call. Undefined if no component instance or the function doesn't exist.
|
* @returns Result of the call. Undefined if no component instance or the function doesn't exist.
|
||||||
*/
|
*/
|
||||||
callComponentFunction(name: string, params?: unknown[], callWhenCreated: boolean = true): unknown {
|
callComponentFunction(name: string, params?: unknown[], callWhenCreated = true): unknown {
|
||||||
if (this.componentInstance) {
|
if (this.componentInstance) {
|
||||||
if (typeof this.componentInstance[name] == 'function') {
|
if (typeof this.componentInstance[name] === 'function') {
|
||||||
return this.componentInstance[name].apply(this.componentInstance, params);
|
return this.componentInstance[name].apply(this.componentInstance, params);
|
||||||
}
|
}
|
||||||
} else if (callWhenCreated) {
|
} else if (callWhenCreated) {
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Injectable, Pipe } from '@angular/core';
|
||||||
|
import { TranslatePipe } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy of translate pipe to use when compiling a dynamic component.
|
||||||
|
* For some reason, when compiling a dynamic component the original translate pipe isn't found so we use this copy instead.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
@Pipe({
|
||||||
|
name: 'translate',
|
||||||
|
pure: false, // required to update the value when the promise is resolved
|
||||||
|
standalone: true,
|
||||||
|
})
|
||||||
|
export class TranslatePipeForCompile extends TranslatePipe {}
|
|
@ -17,14 +17,13 @@ import {
|
||||||
Injector,
|
Injector,
|
||||||
Component,
|
Component,
|
||||||
NgModule,
|
NgModule,
|
||||||
Compiler,
|
|
||||||
ComponentFactory,
|
|
||||||
ComponentRef,
|
ComponentRef,
|
||||||
NgModuleRef,
|
|
||||||
NO_ERRORS_SCHEMA,
|
NO_ERRORS_SCHEMA,
|
||||||
Type,
|
Type,
|
||||||
|
Provider,
|
||||||
|
createNgModule,
|
||||||
|
ViewContainerRef,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';
|
|
||||||
import {
|
import {
|
||||||
ActionSheetController,
|
ActionSheetController,
|
||||||
AlertController,
|
AlertController,
|
||||||
|
@ -34,6 +33,7 @@ import {
|
||||||
ToastController,
|
ToastController,
|
||||||
} from '@ionic/angular';
|
} from '@ionic/angular';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { TranslatePipeForCompile } from '../pipes/translate';
|
||||||
|
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreEvents } from '@singletons/events';
|
import { CoreEvents } from '@singletons/events';
|
||||||
|
@ -160,6 +160,8 @@ import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { CoreAutoLogoutService } from '@features/autologout/services/autologout';
|
import { CoreAutoLogoutService } from '@features/autologout/services/autologout';
|
||||||
|
|
||||||
|
import '@angular/compiler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to provide functionalities regarding compiling dynamic HTML and Javascript.
|
* Service to provide functionalities regarding compiling dynamic HTML and Javascript.
|
||||||
*/
|
*/
|
||||||
|
@ -167,7 +169,6 @@ import { CoreAutoLogoutService } from '@features/autologout/services/autologout'
|
||||||
export class CoreCompileProvider {
|
export class CoreCompileProvider {
|
||||||
|
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
protected compiler: Compiler;
|
|
||||||
|
|
||||||
// Other Ionic/Angular providers that don't depend on where they are injected.
|
// Other Ionic/Angular providers that don't depend on where they are injected.
|
||||||
protected readonly OTHER_SERVICES: unknown[] = [
|
protected readonly OTHER_SERVICES: unknown[] = [
|
||||||
|
@ -186,10 +187,8 @@ export class CoreCompileProvider {
|
||||||
getWorkshopComponentModules,
|
getWorkshopComponentModules,
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(protected injector: Injector, compilerFactory: JitCompilerFactory) {
|
constructor(protected injector: Injector) {
|
||||||
this.logger = CoreLogger.getInstance('CoreCompileProvider');
|
this.logger = CoreLogger.getInstance('CoreCompileProvider');
|
||||||
|
|
||||||
this.compiler = compilerFactory.createCompiler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,14 +196,17 @@ export class CoreCompileProvider {
|
||||||
*
|
*
|
||||||
* @param template The template of the component.
|
* @param template The template of the component.
|
||||||
* @param componentClass The JS class of the component.
|
* @param componentClass The JS class of the component.
|
||||||
|
* @param viewContainerRef View container reference to inject the component.
|
||||||
* @param extraImports Extra imported modules if needed and not imported by this class.
|
* @param extraImports Extra imported modules if needed and not imported by this class.
|
||||||
* @returns Promise resolved with the factory to instantiate the component.
|
* @returns Promise resolved with the component reference.
|
||||||
*/
|
*/
|
||||||
async createAndCompileComponent<T = unknown>(
|
async createAndCompileComponent<T = unknown>(
|
||||||
template: string,
|
template: string,
|
||||||
componentClass: Type<T>,
|
componentClass: Type<T>,
|
||||||
|
viewContainerRef: ViewContainerRef,
|
||||||
extraImports: any[] = [], // eslint-disable-line @typescript-eslint/no-explicit-any
|
extraImports: any[] = [], // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
): Promise<ComponentFactory<T> | undefined> {
|
): Promise<ComponentRef<T> | undefined> {
|
||||||
|
|
||||||
// Create the component using the template and the class.
|
// Create the component using the template and the class.
|
||||||
const component = Component({ template })(componentClass);
|
const component = Component({ template })(componentClass);
|
||||||
|
|
||||||
|
@ -213,17 +215,24 @@ export class CoreCompileProvider {
|
||||||
...CoreArray.flatten(lazyImports),
|
...CoreArray.flatten(lazyImports),
|
||||||
...this.IMPORTS,
|
...this.IMPORTS,
|
||||||
...extraImports,
|
...extraImports,
|
||||||
|
TranslatePipeForCompile,
|
||||||
];
|
];
|
||||||
|
|
||||||
// Now create the module containing the component.
|
|
||||||
const module = NgModule({ imports, declarations: [component], schemas: [NO_ERRORS_SCHEMA] })(class {});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Compile the module and the component.
|
viewContainerRef.clear();
|
||||||
const factories = await this.compiler.compileModuleAndAllComponentsAsync(module);
|
|
||||||
|
|
||||||
// Search and return the factory of the component we just created.
|
// Now create the module containing the component.
|
||||||
return factories.componentFactories.find(factory => factory.componentType == component);
|
const ngModuleRef = createNgModule(
|
||||||
|
NgModule({ imports, declarations: [component], schemas: [NO_ERRORS_SCHEMA] })(class {}),
|
||||||
|
this.injector,
|
||||||
|
);
|
||||||
|
|
||||||
|
return viewContainerRef.createComponent(
|
||||||
|
component,
|
||||||
|
{
|
||||||
|
environmentInjector: ngModuleRef,
|
||||||
|
},
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('Error compiling template', template);
|
this.logger.error('Error compiling template', template);
|
||||||
this.logger.error(error);
|
this.logger.error(error);
|
||||||
|
@ -331,10 +340,10 @@ export class CoreCompileProvider {
|
||||||
// We cannot inject anything to this constructor. Use the Injector to inject all the providers into the instance.
|
// We cannot inject anything to this constructor. Use the Injector to inject all the providers into the instance.
|
||||||
for (const i in providers) {
|
for (const i in providers) {
|
||||||
const providerDef = providers[i];
|
const providerDef = providers[i];
|
||||||
if (typeof providerDef == 'function' && providerDef.name) {
|
if (typeof providerDef === 'function' && providerDef.name) {
|
||||||
try {
|
try {
|
||||||
// Inject the provider to the instance. We use the class name as the property name.
|
// Inject the provider to the instance. We use the class name as the property name.
|
||||||
instance[providerDef.name.replace(/DelegateService$/, 'Delegate')] = this.injector.get(providerDef);
|
instance[providerDef.name.replace(/DelegateService$/, 'Delegate')] = this.injector.get<Provider>(providerDef);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
this.logger.error('Error injecting provider', providerDef.name, ex);
|
this.logger.error('Error injecting provider', providerDef.name, ex);
|
||||||
}
|
}
|
||||||
|
@ -407,29 +416,6 @@ export class CoreCompileProvider {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate a dynamic component.
|
|
||||||
*
|
|
||||||
* @param template The template of the component.
|
|
||||||
* @param componentClass The JS class of the component.
|
|
||||||
* @param injector The injector to use. It's recommended to pass it so NavController and similar can be injected.
|
|
||||||
* @returns Promise resolved with the component instance.
|
|
||||||
*/
|
|
||||||
async instantiateDynamicComponent<T = unknown>(
|
|
||||||
template: string,
|
|
||||||
componentClass: Type<T>,
|
|
||||||
injector?: Injector,
|
|
||||||
): Promise<ComponentRef<T> | undefined> {
|
|
||||||
injector = injector || this.injector;
|
|
||||||
|
|
||||||
const factory = await this.createAndCompileComponent(template, componentClass);
|
|
||||||
|
|
||||||
if (factory) {
|
|
||||||
// Create and return the component.
|
|
||||||
return factory.create(injector, undefined, undefined, injector.get(NgModuleRef));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CoreCompile = makeSingleton(CoreCompileProvider);
|
export const CoreCompile = makeSingleton(CoreCompileProvider);
|
||||||
|
|
|
@ -48,18 +48,18 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
||||||
// Get the compile element. Don't set the right type to prevent circular dependencies.
|
// Get the compile element. Don't set the right type to prevent circular dependencies.
|
||||||
@ViewChild('compile') compileComponent?: CoreCompileHtmlComponent;
|
@ViewChild('compile') compileComponent?: CoreCompileHtmlComponent;
|
||||||
|
|
||||||
@HostBinding('class') @Input() component!: string;
|
@HostBinding('class') @Input() component = '';
|
||||||
@Input() method!: string;
|
@Input() method!: string;
|
||||||
@Input() args?: Record<string, unknown>;
|
@Input() args?: Record<string, unknown>;
|
||||||
@Input() initResult?: CoreSitePluginsContent | null; // Result of the init WS call of the handler.
|
@Input() initResult?: CoreSitePluginsContent | null; // Result of the init WS call of the handler.
|
||||||
@Input() data?: Record<string, unknown>; // Data to pass to the component.
|
@Input() data: Record<string, unknown> = {}; // Data to pass to the component.
|
||||||
@Input() preSets?: CoreSiteWSPreSets; // The preSets for the WS call.
|
@Input() preSets?: CoreSiteWSPreSets; // The preSets for the WS call.
|
||||||
@Input() pageTitle?: string; // Current page title. It can be used by the "new-content" directives.
|
@Input() pageTitle?: string; // Current page title. It can be used by the "new-content" directives.
|
||||||
@Output() onContentLoaded = new EventEmitter<CoreSitePluginsPluginContentLoadedData>(); // Emits event when content is loaded.
|
@Output() onContentLoaded = new EventEmitter<CoreSitePluginsPluginContentLoadedData>(); // Emits event when content is loaded.
|
||||||
@Output() onLoadingContent = new EventEmitter<boolean>(); // Emits an event when starts to load the content.
|
@Output() onLoadingContent = new EventEmitter<boolean>(); // Emits an event when starts to load the content.
|
||||||
|
|
||||||
content?: string; // Content.
|
content = ''; // Content.
|
||||||
javascript?: string; // Javascript to execute.
|
javascript = ''; // Javascript to execute.
|
||||||
otherData?: Record<string, unknown>; // Other data of the content.
|
otherData?: Record<string, unknown>; // Other data of the content.
|
||||||
dataLoaded = false;
|
dataLoaded = false;
|
||||||
invalidateObservable = new Subject<void>(); // An observable to notify observers when to invalidate data.
|
invalidateObservable = new Subject<void>(); // An observable to notify observers when to invalidate data.
|
||||||
|
@ -120,13 +120,27 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
||||||
this.jsData = Object.assign(this.data, CoreSitePlugins.createDataForJS(this.initResult, result));
|
this.jsData = Object.assign(this.data, CoreSitePlugins.createDataForJS(this.initResult, result));
|
||||||
|
|
||||||
// Pass some methods as jsData so they can be called from the template too.
|
// Pass some methods as jsData so they can be called from the template too.
|
||||||
this.jsData.fetchContent = refresh => this.fetchContent(refresh);
|
this.jsData.fetchContent = (refresh?: boolean) => this.fetchContent(refresh);
|
||||||
this.jsData.openContent = (title, args, component, method, jsData, preSets, ptrEnabled) =>
|
this.jsData.openContent = (
|
||||||
this.openContent(title, args, component, method, jsData, preSets, ptrEnabled);
|
title: string,
|
||||||
this.jsData.refreshContent = showSpinner => this.refreshContent(showSpinner);
|
args?: Record<string, unknown>,
|
||||||
this.jsData.updateContent = (args, component, method, jsData, preSets) =>
|
component?: string,
|
||||||
this.updateContent(args, component, method, jsData, preSets);
|
method?: string,
|
||||||
this.jsData.updateModuleCourseContent = (cmId, alreadyFetched) => this.updateModuleCourseContent(cmId, alreadyFetched);
|
jsData?: Record<string, unknown> | boolean,
|
||||||
|
preSets?: CoreSiteWSPreSets,
|
||||||
|
ptrEnabled?: boolean,
|
||||||
|
) => this.openContent(title, args, component, method, jsData, preSets, ptrEnabled);
|
||||||
|
this.jsData.refreshContent = (showSpinner?: boolean) => this.refreshContent(showSpinner);
|
||||||
|
this.jsData.updateContent = (
|
||||||
|
args?: Record<string, unknown>,
|
||||||
|
component?: string,
|
||||||
|
method?: string,
|
||||||
|
jsData?: Record<string, unknown>,
|
||||||
|
preSets?: CoreSiteWSPreSets,
|
||||||
|
) => this.updateContent(args, component, method, jsData, preSets);
|
||||||
|
this.jsData.updateModuleCourseContent = (cmId: number, alreadyFetched?: boolean) =>
|
||||||
|
this.updateModuleCourseContent(cmId, alreadyFetched);
|
||||||
|
this.jsData.updateCachedContent = () => this.updateCachedContent();
|
||||||
|
|
||||||
this.onContentLoaded.emit({ refresh: !!refresh, success: true });
|
this.onContentLoaded.emit({ refresh: !!refresh, success: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -154,7 +168,7 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
||||||
*/
|
*/
|
||||||
openContent(
|
openContent(
|
||||||
title: string,
|
title: string,
|
||||||
args?: Record<string, unknown>,
|
args: Record<string, unknown> = {},
|
||||||
component?: string,
|
component?: string,
|
||||||
method?: string,
|
method?: string,
|
||||||
jsData?: Record<string, unknown> | boolean,
|
jsData?: Record<string, unknown> | boolean,
|
||||||
|
@ -167,7 +181,6 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
||||||
|
|
||||||
component = component || this.component;
|
component = component || this.component;
|
||||||
method = method || this.method;
|
method = method || this.method;
|
||||||
args = args || {};
|
|
||||||
const hash = <string> Md5.hashAsciiStr(JSON.stringify(args));
|
const hash = <string> Md5.hashAsciiStr(JSON.stringify(args));
|
||||||
|
|
||||||
CoreNavigator.navigateToSitePath(`siteplugins/content/${component}/${method}/${hash}`, {
|
CoreNavigator.navigateToSitePath(`siteplugins/content/${component}/${method}/${hash}`, {
|
||||||
|
@ -187,7 +200,7 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
||||||
*
|
*
|
||||||
* @param showSpinner Whether to show spinner while refreshing.
|
* @param showSpinner Whether to show spinner while refreshing.
|
||||||
*/
|
*/
|
||||||
async refreshContent(showSpinner: boolean = true): Promise<void> {
|
async refreshContent(showSpinner = true): Promise<void> {
|
||||||
if (showSpinner) {
|
if (showSpinner) {
|
||||||
this.dataLoaded = false;
|
this.dataLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,6 @@ export const Translate: Omit<CoreSingletonProxy<TranslateService>, 'instant'> &
|
||||||
// Async singletons.
|
// Async singletons.
|
||||||
export const AngularFrameworkDelegate = asyncInstance(async () => {
|
export const AngularFrameworkDelegate = asyncInstance(async () => {
|
||||||
const injector = await singletonsInjector;
|
const injector = await singletonsInjector;
|
||||||
const environmentInjector = await injector.get(EnvironmentInjector);
|
|
||||||
|
|
||||||
return AngularDelegate.create(environmentInjector, injector);
|
return AngularDelegate.create(injector.get(EnvironmentInjector), injector);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue