forked from EVOgeek/Vmeda.Online
commit
76beb12d17
|
@ -428,19 +428,15 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait loadings to finish.
|
// Make sure elements have been added to the DOM.
|
||||||
await CoreDirectivesRegistry.waitDirectivesReady(this.page, 'core-loading', CoreLoadingComponent);
|
await CoreUtils.nextTick();
|
||||||
|
|
||||||
// Wait tabs to be ready.
|
// Wait all loadings and tabs to finish loading.
|
||||||
await CoreDirectivesRegistry.waitDirectivesReady(this.page, 'core-tabs', CoreTabsComponent);
|
await CoreDirectivesRegistry.waitMultipleDirectivesReady(this.page, [
|
||||||
await CoreDirectivesRegistry.waitDirectivesReady(this.page, 'core-tabs-outlet', CoreTabsOutletComponent);
|
{ selector: 'core-loading', class: CoreLoadingComponent },
|
||||||
|
{ selector: 'core-tabs', class: CoreTabsComponent },
|
||||||
// Wait loadings to finish, inside tabs (if any).
|
{ selector: 'core-tabs-outlet', class: CoreTabsOutletComponent },
|
||||||
await CoreDirectivesRegistry.waitDirectivesReady(
|
]);
|
||||||
this.page,
|
|
||||||
'core-tab core-loading, ion-router-outlet core-loading',
|
|
||||||
CoreLoadingComponent,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Activity info. -->
|
<!-- Activity info. -->
|
||||||
<core-course-module-info [module]="module" [courseId]="courseId" [component]="component" [componentId]="module.id" />
|
<core-course-module-info *ngIf="addDefaultModuleInfo" [module]="module" [courseId]="courseId" [component]="component"
|
||||||
|
[componentId]="module.id" />
|
||||||
|
|
||||||
<core-site-plugins-plugin-content *ngIf="component && method" [component]="component" [method]="method" [args]="args"
|
<core-site-plugins-plugin-content *ngIf="component && method" [component]="component" [method]="method" [args]="args"
|
||||||
[initResult]="initResult" [data]="jsData" [pageTitle]="pageTitle" [preSets]="preSets" (onContentLoaded)="contentLoaded($event)"
|
[initResult]="initResult" [data]="jsData" [pageTitle]="pageTitle" [preSets]="preSets" (onContentLoaded)="contentLoaded($event)"
|
||||||
|
|
|
@ -58,6 +58,7 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
collapsibleFooterAppearOnBottom = true;
|
collapsibleFooterAppearOnBottom = true;
|
||||||
|
addDefaultModuleInfo = false;
|
||||||
|
|
||||||
displayOpenInBrowser = true;
|
displayOpenInBrowser = true;
|
||||||
displayDescription = true;
|
displayDescription = true;
|
||||||
|
@ -133,6 +134,7 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
||||||
* Function called when the data of the site plugin content is loaded.
|
* Function called when the data of the site plugin content is loaded.
|
||||||
*/
|
*/
|
||||||
contentLoaded(data: CoreSitePluginsPluginContentLoadedData): void {
|
contentLoaded(data: CoreSitePluginsPluginContentLoadedData): void {
|
||||||
|
this.addDefaultModuleInfo = !data.content.includes('<core-course-module-info');
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
CoreCourse.storeModuleViewed(this.courseId, this.module.id, {
|
CoreCourse.storeModuleViewed(this.courseId, this.module.id, {
|
||||||
sectionId: this.module.section,
|
sectionId: this.module.section,
|
||||||
|
|
|
@ -142,11 +142,11 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
||||||
this.updateModuleCourseContent(cmId, alreadyFetched);
|
this.updateModuleCourseContent(cmId, alreadyFetched);
|
||||||
this.jsData.updateCachedContent = () => this.updateCachedContent();
|
this.jsData.updateCachedContent = () => this.updateCachedContent();
|
||||||
|
|
||||||
this.onContentLoaded.emit({ refresh: !!refresh, success: true });
|
this.onContentLoaded.emit({ refresh: !!refresh, success: true, content: this.content });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Make it think it's loaded - otherwise it sticks on 'loading' and stops navigation working.
|
// Make it think it's loaded - otherwise it sticks on 'loading' and stops navigation working.
|
||||||
this.content = '<div></div>';
|
this.content = '<div></div>';
|
||||||
this.onContentLoaded.emit({ refresh: !!refresh, success: false });
|
this.onContentLoaded.emit({ refresh: !!refresh, success: false, content: this.content });
|
||||||
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true);
|
CoreDomUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -282,4 +282,5 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
||||||
export type CoreSitePluginsPluginContentLoadedData = {
|
export type CoreSitePluginsPluginContentLoadedData = {
|
||||||
refresh: boolean;
|
refresh: boolean;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
|
content: string;
|
||||||
};
|
};
|
||||||
|
|
|
@ -114,15 +114,16 @@ export class CoreDirectivesRegistry {
|
||||||
selector?: string,
|
selector?: string,
|
||||||
directiveClass?: DirectiveConstructor<T>,
|
directiveClass?: DirectiveConstructor<T>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
let elements: Element[] = [];
|
const findElements = (): Element[] => {
|
||||||
|
if (!selector || element.matches(selector)) {
|
||||||
if (!selector || element.matches(selector)) {
|
// Element to wait is myself.
|
||||||
// Element to wait is myself.
|
return [element];
|
||||||
elements = [element];
|
} else {
|
||||||
} else {
|
return Array.from(element.querySelectorAll(selector));
|
||||||
elements = Array.from(element.querySelectorAll(selector));
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const elements = findElements();
|
||||||
if (!elements.length) {
|
if (!elements.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -135,6 +136,63 @@ export class CoreDirectivesRegistry {
|
||||||
|
|
||||||
// Wait for next tick to ensure directives are completely rendered.
|
// Wait for next tick to ensure directives are completely rendered.
|
||||||
await CoreUtils.nextTick();
|
await CoreUtils.nextTick();
|
||||||
|
|
||||||
|
// Check if there are new elements now that the found elements are ready (there could be nested elements).
|
||||||
|
if (elements.length !== findElements().length) {
|
||||||
|
await this.waitDirectivesReady(element, selector, directiveClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all directive instances (with multiple types) and wait for them to be ready.
|
||||||
|
*
|
||||||
|
* @param element Root element.
|
||||||
|
* @param directives Directives to wait.
|
||||||
|
* @returns Promise resolved when done.
|
||||||
|
*/
|
||||||
|
static async waitMultipleDirectivesReady(
|
||||||
|
element: Element,
|
||||||
|
directives: DirectiveData<AsyncDirective>[],
|
||||||
|
): Promise<void> {
|
||||||
|
const findElements = (selector?: string): Element[] => {
|
||||||
|
if (!selector || element.matches(selector)) {
|
||||||
|
// Element to wait is myself.
|
||||||
|
return [element];
|
||||||
|
} else {
|
||||||
|
return Array.from(element.querySelectorAll(selector));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let allElements: Element[] = [];
|
||||||
|
|
||||||
|
await Promise.all(directives.map(async directive => {
|
||||||
|
const elements = findElements(directive.selector);
|
||||||
|
if (!elements.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
allElements = allElements.concat(elements);
|
||||||
|
|
||||||
|
await Promise.all(elements.map(async element => {
|
||||||
|
const instances = this.resolveAll<AsyncDirective>(element, directive.class);
|
||||||
|
|
||||||
|
await Promise.all(instances.map(instance => instance.ready()));
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Wait for next tick to ensure directives are completely rendered.
|
||||||
|
await CoreUtils.nextTick();
|
||||||
|
|
||||||
|
// Check if there are new elements now that the found elements are ready (there could be nested elements).
|
||||||
|
const elementsAfterReady = directives.reduce((elements, directive) => {
|
||||||
|
elements = elements.concat(findElements(directive.selector));
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}, <Element[]> []);
|
||||||
|
|
||||||
|
if (allElements.length !== elementsAfterReady.length) {
|
||||||
|
await this.waitMultipleDirectivesReady(element, directives);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -144,3 +202,11 @@ export class CoreDirectivesRegistry {
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export type DirectiveConstructor<T = Directive> = { new(...args: any[]): T };
|
export type DirectiveConstructor<T = Directive> = { new(...args: any[]): T };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data to identify a directive when waiting for ready.
|
||||||
|
*/
|
||||||
|
type DirectiveData<T extends AsyncDirective> = {
|
||||||
|
selector?: string; // If defined, CSS Selector to wait for.
|
||||||
|
class?: DirectiveConstructor<T>; // Directive class.
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue