Vmeda.Online/src/core/features/block/classes/base-block-component.ts

176 lines
5.2 KiB
TypeScript

// (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 { OnInit, Input, Component, Optional, Inject, OnChanges, SimpleChanges } from '@angular/core';
import { CoreLogger } from '@singletons/logger';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreTextUtils } from '@services/utils/text';
import { CoreCourseBlock } from '../../course/services/course';
import { Params } from '@angular/router';
import { ContextLevel } from '@/core/constants';
import { CoreNavigationOptions } from '@services/navigator';
import { AsyncDirective } from '@classes/async-directive';
import { CorePromisedValue } from '@classes/promised-value';
/**
* Template class to easily create components for blocks.
*/
@Component({
template: '',
})
export abstract class CoreBlockBaseComponent implements OnInit, OnChanges, ICoreBlockComponent, AsyncDirective {
@Input() title!: string; // The block title.
@Input() block!: CoreCourseBlock; // The block to render.
@Input() contextLevel!: ContextLevel; // The context where the block will be used.
@Input() instanceId!: number; // The instance ID associated with the context level.
@Input() link?: string; // Link to go when clicked.
@Input() linkParams?: Params; // Link params to go when clicked.
@Input() navOptions?: CoreNavigationOptions; // Navigation options.
loaded = false; // If false, the UI should display a loading.
protected fetchContentDefaultError = ''; // Default error to show when loading contents.
protected onReadyPromise = new CorePromisedValue<void>();
protected logger: CoreLogger;
constructor(@Optional() @Inject('') loggerName: string = 'AddonBlockComponent') {
this.logger = CoreLogger.getInstance(loggerName);
}
/**
* @inheritdoc
*/
async ngOnInit(): Promise<void> {
await this.loadContent();
}
/**
* @inheritdoc
*/
ngOnChanges(changes: SimpleChanges): void {
if (changes.block) {
this.parseConfigs();
}
}
/**
* Parse configs if needed.
*/
protected parseConfigs(): void {
if (!this.block.configs?.length || this.block.configsRecord) {
return;
}
this.block.configs.forEach((config) => {
config.value = CoreTextUtils.parseJSON(config.value);
});
this.block.configsRecord = CoreUtils.arrayToObject(this.block.configs, 'name');
}
/**
* Perform the refresh content function.
*
* @param showLoading Whether to show loading.
* @returns Resolved when done.
*/
protected async refreshContent(showLoading?: boolean): Promise<void> {
if (showLoading) {
this.loaded = false;
}
// Wrap the call in a try/catch so the workflow isn't interrupted if an error occurs.
try {
await this.invalidateContent();
} catch (ex) {
// An error ocurred in the function, log the error and just resolve the promise so the workflow continues.
this.logger.error(ex);
}
await this.loadContent();
}
/**
* @inheritdoc
*/
async invalidateContent(): Promise<void> {
return;
}
/**
* Loads the component contents and shows the corresponding error.
*/
protected async loadContent(): Promise<void> {
// Wrap the call in a try/catch so the workflow isn't interrupted if an error occurs.
try {
await this.fetchContent();
} catch (error) {
// An error ocurred in the function, log the error and just resolve the promise so the workflow continues.
this.logger.error(error);
// Error getting data, fail.
CoreDomUtils.showErrorModalDefault(error, this.fetchContentDefaultError, true);
}
this.loaded = true;
this.onReadyPromise.resolve();
}
/**
* Download the component contents.
*
* @returns Promise resolved when done.
*/
protected async fetchContent(): Promise<void> {
return;
}
/**
* Reload content without invalidating data.
*
* @returns Promise resolved when done.
*/
async reloadContent(): Promise<void> {
if (!this.loaded) {
// Content being loaded, don't do anything.
return;
}
this.loaded = false;
await this.loadContent();
}
/**
* @inheritdoc
*/
async ready(): Promise<void> {
return await this.onReadyPromise;
}
}
/**
* Interface for block components.
*/
export interface ICoreBlockComponent {
/**
* Perform the invalidate content function.
*/
invalidateContent(): Promise<void>;
}