forked from CIT/Vmeda.Online
		
	
						commit
						134e2d7203
					
				@ -44,12 +44,6 @@ export class AddonModAssignSubmissionFileComponent extends AddonModAssignSubmiss
 | 
			
		||||
     * Component being initialized.
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        // Get the offline data.
 | 
			
		||||
        const filesData = await CoreUtils.ignoreErrors(
 | 
			
		||||
            AddonModAssignOffline.getSubmission(this.assign.id),
 | 
			
		||||
            undefined,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        this.acceptedTypes = this.configs?.filetypeslist;
 | 
			
		||||
        this.maxSize = this.configs?.maxsubmissionsizebytes
 | 
			
		||||
            ? parseInt(this.configs.maxsubmissionsizebytes, 10)
 | 
			
		||||
@ -58,6 +52,12 @@ export class AddonModAssignSubmissionFileComponent extends AddonModAssignSubmiss
 | 
			
		||||
            ? parseInt(this.configs.maxfilesubmissions, 10)
 | 
			
		||||
            : undefined;
 | 
			
		||||
 | 
			
		||||
        // Get the offline data.
 | 
			
		||||
        const filesData = await CoreUtils.ignoreErrors(
 | 
			
		||||
            AddonModAssignOffline.getSubmission(this.assign.id),
 | 
			
		||||
            undefined,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            if (filesData && filesData.plugindata && filesData.plugindata.files_filemanager) {
 | 
			
		||||
                const offlineDataFiles = <CoreFileUploaderStoreFilesResult>filesData.plugindata.files_filemanager;
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,7 @@
 | 
			
		||||
                <ion-label position="stacked" id="addon-mod-glossary-aliases-label">
 | 
			
		||||
                    {{ 'addon.mod_glossary.aliases' | translate }}
 | 
			
		||||
                </ion-label>
 | 
			
		||||
                <ion-textarea [(ngModel)]="options.aliases" rows="1" core-auto-rows
 | 
			
		||||
                <ion-textarea [(ngModel)]="options.aliases" rows="1" [core-auto-rows]="options.aliases"
 | 
			
		||||
                    aria-labelledby="addon-mod-glossary-aliases-label" name="aliases">
 | 
			
		||||
                </ion-textarea>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ import { CoreCourseContentsPage } from '@features/course/pages/contents/contents
 | 
			
		||||
import { CoreCourse } from '@features/course/services/course';
 | 
			
		||||
import { IonContent } from '@ionic/angular';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreSync } from '@services/sync';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { Translate } from '@singletons';
 | 
			
		||||
@ -584,9 +585,17 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
 | 
			
		||||
    /**
 | 
			
		||||
     * Performs the sync of the activity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param retries Number of retries done.
 | 
			
		||||
     * @return Promise resolved when done.
 | 
			
		||||
     */
 | 
			
		||||
    protected async sync(): Promise<AddonModScormSyncResult> {
 | 
			
		||||
    protected async sync(retries = 0): Promise<AddonModScormSyncResult> {
 | 
			
		||||
        if (CoreSync.isBlocked(AddonModScormProvider.COMPONENT, this.scorm!.id) && retries < 5) {
 | 
			
		||||
            // Sync is currently blocked, this can happen when SCORM player is left. Retry in a bit.
 | 
			
		||||
            await CoreUtils.wait(400);
 | 
			
		||||
 | 
			
		||||
            return this.sync(retries + 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const result = await AddonModScormSync.syncScorm(this.scorm!);
 | 
			
		||||
 | 
			
		||||
        if (!result.updated && this.dataSent) {
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler';
 | 
			
		||||
import { CoreCourseAnyModuleData, CoreCourseCommonModWSOptions } from '@features/course/services/course';
 | 
			
		||||
import { CoreCourse, CoreCourseAnyModuleData, CoreCourseCommonModWSOptions } from '@features/course/services/course';
 | 
			
		||||
import { CoreApp } from '@services/app';
 | 
			
		||||
import { CoreFile } from '@services/file';
 | 
			
		||||
import { CoreFilepool } from '@services/filepool';
 | 
			
		||||
@ -316,8 +316,13 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe
 | 
			
		||||
     * @param siteId Site ID.
 | 
			
		||||
     * @returns Promise resolved with the SCORM.
 | 
			
		||||
     */
 | 
			
		||||
    protected getScorm(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise<AddonModScormScorm> {
 | 
			
		||||
        const moduleUrl = 'url' in module ? module.url : undefined;
 | 
			
		||||
    protected async getScorm(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise<AddonModScormScorm> {
 | 
			
		||||
        let moduleUrl = 'url' in module ? module.url : undefined;
 | 
			
		||||
        if (!moduleUrl) {
 | 
			
		||||
            module = await CoreCourse.getModule(module.id, module.course, undefined, true, false, siteId);
 | 
			
		||||
 | 
			
		||||
            moduleUrl = module.url;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return AddonModScorm.getScorm(courseId, module.id, { moduleUrl, siteId });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -198,7 +198,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide
 | 
			
		||||
        if (updated) {
 | 
			
		||||
            try {
 | 
			
		||||
                // Update downloaded data.
 | 
			
		||||
                const module = await CoreCourse.getModuleBasicInfoByInstance(scorm.id, 'scorm', siteId);
 | 
			
		||||
                const module = await CoreCourse.getModule(scorm.coursemodule, scorm.course, undefined, false, false, siteId);
 | 
			
		||||
 | 
			
		||||
                await this.prefetchAfterUpdate(AddonModScormPrefetchHandler.instance, module, scorm.course, undefined, siteId);
 | 
			
		||||
            } catch {
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,8 @@
 | 
			
		||||
            <ion-label position="stacked">
 | 
			
		||||
                {{ 'addon.mod_workshop_assessment_accumulative.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
 | 
			
		||||
            </ion-label>
 | 
			
		||||
            <ion-textarea [(ngModel)]="selectedValues[n].peercomment" core-auto-rows></ion-textarea>
 | 
			
		||||
            <ion-textarea [(ngModel)]="selectedValues[n].peercomment" [core-auto-rows]="selectedValues[n].peercomment">
 | 
			
		||||
            </ion-textarea>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
        <ion-item *ngIf="!edit" class="ion-text-wrap">
 | 
			
		||||
            <ion-label>
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,8 @@
 | 
			
		||||
                    {{ 'addon.mod_workshop_assessment_comments.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
 | 
			
		||||
                </span>
 | 
			
		||||
            </ion-label>
 | 
			
		||||
            <ion-textarea [(ngModel)]="selectedValues[n].peercomment" core-auto-rows></ion-textarea>
 | 
			
		||||
            <ion-textarea [(ngModel)]="selectedValues[n].peercomment" [core-auto-rows]="selectedValues[n].peercomment">
 | 
			
		||||
            </ion-textarea>
 | 
			
		||||
            <core-input-errors *ngIf="fieldErrors['peercomment_' + n]" [errorText]="fieldErrors['peercomment_' + n]">
 | 
			
		||||
            </core-input-errors>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@
 | 
			
		||||
                {{ 'addon.mod_workshop_assessment_numerrors.dimensioncommentfor' | translate : {'$a': field.dimtitle } }}
 | 
			
		||||
            </ion-label>
 | 
			
		||||
            <ion-textarea [(ngModel)]="selectedValues[n].peercomment" [name]="'peercomment_' + n"
 | 
			
		||||
                core-auto-rows>
 | 
			
		||||
                [core-auto-rows]="selectedValues[n].peercomment">
 | 
			
		||||
            </ion-textarea>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
        <ion-item *ngIf="!edit" class="ion-text-wrap">
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
    </iframe>
 | 
			
		||||
 | 
			
		||||
    <ion-button
 | 
			
		||||
        *ngIf="!loading"
 | 
			
		||||
        *ngIf="!loading && displayHelp"
 | 
			
		||||
        color="dark" expand="block" fill="clear"
 | 
			
		||||
        (click)="openIframeHelpModal()"
 | 
			
		||||
        aria-haspopup="dialog"
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
        [core-auto-focus]="showKeyboard"
 | 
			
		||||
        [placeholder]="placeholder"
 | 
			
		||||
        rows="1"
 | 
			
		||||
        core-auto-rows
 | 
			
		||||
        [core-auto-rows]="message"
 | 
			
		||||
        [(ngModel)]="message"
 | 
			
		||||
        name="message"
 | 
			
		||||
        (onResize)="textareaResized()"
 | 
			
		||||
 | 
			
		||||
@ -12,41 +12,31 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Directive, ElementRef, HostListener, Output, EventEmitter, AfterViewInit } from '@angular/core';
 | 
			
		||||
import { Directive, ElementRef, Output, EventEmitter, AfterViewInit, Input, OnChanges } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Directive to adapt a textarea rows depending on the input text. It's based on Moodle's data-auto-rows.
 | 
			
		||||
 *
 | 
			
		||||
 * @description
 | 
			
		||||
 * Usage:
 | 
			
		||||
 * <textarea class="core-textarea" [(ngModel)]="message" rows="1" core-auto-rows></textarea>
 | 
			
		||||
 * <textarea class="core-textarea" [(ngModel)]="message" rows="1" [core-auto-rows]="message"></textarea>
 | 
			
		||||
 */
 | 
			
		||||
@Directive({
 | 
			
		||||
    selector: 'textarea[core-auto-rows], ion-textarea[core-auto-rows]',
 | 
			
		||||
})
 | 
			
		||||
export class CoreAutoRowsDirective implements AfterViewInit {
 | 
			
		||||
export class CoreAutoRowsDirective implements AfterViewInit, OnChanges {
 | 
			
		||||
 | 
			
		||||
    protected height = 0;
 | 
			
		||||
 | 
			
		||||
    @Input('core-auto-rows') value?: string; // eslint-disable-line @angular-eslint/no-input-rename
 | 
			
		||||
    @Output() onResize: EventEmitter<void>; // Emit when resizing the textarea.
 | 
			
		||||
 | 
			
		||||
    constructor(protected element: ElementRef) {
 | 
			
		||||
        this.onResize = new EventEmitter();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @HostListener('input') onInput(): void {
 | 
			
		||||
        this.resize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @HostListener('change') onChange(): void {
 | 
			
		||||
        // Fired on reset. Wait to the change to be finished.
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
            this.resize();
 | 
			
		||||
        }, 300);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Resize after content.
 | 
			
		||||
     * Resize after initialized.
 | 
			
		||||
     */
 | 
			
		||||
    ngAfterViewInit(): void {
 | 
			
		||||
        // Wait for rendering of child views.
 | 
			
		||||
@ -55,6 +45,18 @@ export class CoreAutoRowsDirective implements AfterViewInit {
 | 
			
		||||
        }, 300);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Resize when content changes.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnChanges(): void {
 | 
			
		||||
        this.resize();
 | 
			
		||||
 | 
			
		||||
        if (this.value === '') {
 | 
			
		||||
            // Maybe the form was resetted. In that case it takes a bit to update the height.
 | 
			
		||||
            setTimeout(() => this.resize(), 300);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Resize the textarea.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -206,7 +206,7 @@ export class CoreCoursesMyCoursesPage implements OnInit, OnDestroy {
 | 
			
		||||
     * Go to search courses.
 | 
			
		||||
     */
 | 
			
		||||
    openSearch(): void {
 | 
			
		||||
        CoreNavigator.navigate('courses/search');
 | 
			
		||||
        CoreNavigator.navigateToSitePath('courses/search');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ import { LangChangeEvent } from '@ngx-translate/core';
 | 
			
		||||
import { CoreAppProvider } from '@services/app';
 | 
			
		||||
import { CoreConfig } from '@services/config';
 | 
			
		||||
import { CoreSubscriptions } from '@singletons/subscriptions';
 | 
			
		||||
import { makeSingleton, Translate, Platform } from '@singletons';
 | 
			
		||||
import { makeSingleton, Translate, Platform, Http } from '@singletons';
 | 
			
		||||
 | 
			
		||||
import * as moment from 'moment';
 | 
			
		||||
import { CoreSite } from '../classes/site';
 | 
			
		||||
@ -142,24 +142,24 @@ export class CoreLangProvider {
 | 
			
		||||
 | 
			
		||||
        // Change the language, resolving the promise when we receive the first value.
 | 
			
		||||
        promises.push(new Promise((resolve, reject) => {
 | 
			
		||||
            CoreSubscriptions.once(Translate.use(language), data => {
 | 
			
		||||
                // It's a language override, load the original one first.
 | 
			
		||||
            CoreSubscriptions.once(Translate.use(language), async data => {
 | 
			
		||||
                // Check if it has a parent language.
 | 
			
		||||
                const fallbackLang = this.getParentLanguage(language);
 | 
			
		||||
 | 
			
		||||
                if (fallbackLang) {
 | 
			
		||||
                    CoreSubscriptions.once(
 | 
			
		||||
                        Translate.use(fallbackLang),
 | 
			
		||||
                        fallbackData => {
 | 
			
		||||
                            data = Object.assign(fallbackData, data);
 | 
			
		||||
                    try {
 | 
			
		||||
                        // Merge parent translations with the child ones.
 | 
			
		||||
                        const parentTranslations = Translate.translations[fallbackLang] ?? await this.readLangFile(fallbackLang);
 | 
			
		||||
 | 
			
		||||
                            resolve(data);
 | 
			
		||||
                        },
 | 
			
		||||
                        // Resolve with the original language.
 | 
			
		||||
                        () => resolve(data),
 | 
			
		||||
                    );
 | 
			
		||||
                } else {
 | 
			
		||||
                    resolve(data);
 | 
			
		||||
                        const mergedData = Object.assign(parentTranslations, data);
 | 
			
		||||
 | 
			
		||||
                        Object.assign(data, mergedData);
 | 
			
		||||
                    } catch {
 | 
			
		||||
                        // Ignore errors.
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                resolve(data);
 | 
			
		||||
            }, reject);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
@ -474,6 +474,20 @@ export class CoreLangProvider {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Read a language file.
 | 
			
		||||
     *
 | 
			
		||||
     * @param lang Language code.
 | 
			
		||||
     * @return Promise resolved with the file contents.
 | 
			
		||||
     */
 | 
			
		||||
    async readLangFile(lang: string): Promise<Record<string, string>> {
 | 
			
		||||
        const observable = Http.get(`assets/lang/${lang}.json`, {
 | 
			
		||||
            responseType: 'json',
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return <Record<string, string>> await observable.toPromise();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Unload custom or site plugin strings, removing them from the translations table.
 | 
			
		||||
     *
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user