commit
7cce817d12
|
@ -71,7 +71,7 @@ export class AddonModDataSearchComponent implements OnInit {
|
|||
this.search.advanced?.forEach((field) => {
|
||||
if (typeof field != 'undefined') {
|
||||
this.advancedIndexed[field.name] = field.value
|
||||
? CoreTextUtils.parseJSON(field.value)
|
||||
? CoreTextUtils.parseJSON(field.value, '')
|
||||
: '';
|
||||
}
|
||||
});
|
||||
|
|
|
@ -112,7 +112,8 @@ export class AddonModDataFieldFileHandlerService implements AddonModDataFieldHan
|
|||
offlineContent: CoreFormFields,
|
||||
offlineFiles?: FileEntry[],
|
||||
): AddonModDataEntryField {
|
||||
const uploadedFilesResult: CoreFileUploaderStoreFilesResult = <CoreFileUploaderStoreFilesResult>offlineContent?.file;
|
||||
const uploadedFilesResult: CoreFileUploaderStoreFilesResult | undefined =
|
||||
<CoreFileUploaderStoreFilesResult | undefined> offlineContent?.file;
|
||||
|
||||
if (uploadedFilesResult && uploadedFilesResult.offline > 0 && offlineFiles && offlineFiles?.length > 0) {
|
||||
originalContent.content = offlineFiles[0].name;
|
||||
|
|
|
@ -121,8 +121,8 @@ export class AddonModDataFieldLatlongHandlerService implements AddonModDataField
|
|||
* @inheritdoc
|
||||
*/
|
||||
overrideData(originalContent: AddonModDataEntryField, offlineContent: CoreFormFields<string>): AddonModDataEntryField {
|
||||
originalContent.content = offlineContent[0] || '';
|
||||
originalContent.content1 = offlineContent[1] || '';
|
||||
originalContent.content = offlineContent['0'] || '';
|
||||
originalContent.content1 = offlineContent['1'] || '';
|
||||
|
||||
return originalContent;
|
||||
}
|
||||
|
|
|
@ -155,7 +155,8 @@ export class AddonModDataFieldPictureHandlerService implements AddonModDataField
|
|||
offlineContent: CoreFormFields,
|
||||
offlineFiles?: FileEntry[],
|
||||
): AddonModDataEntryField {
|
||||
const uploadedFilesResult: CoreFileUploaderStoreFilesResult = <CoreFileUploaderStoreFilesResult>offlineContent?.file;
|
||||
const uploadedFilesResult: CoreFileUploaderStoreFilesResult | undefined =
|
||||
<CoreFileUploaderStoreFilesResult | undefined> offlineContent?.file;
|
||||
|
||||
if (uploadedFilesResult && uploadedFilesResult.offline > 0 && offlineFiles && offlineFiles?.length > 0) {
|
||||
originalContent.content = offlineFiles[0].name;
|
||||
|
@ -165,7 +166,7 @@ export class AddonModDataFieldPictureHandlerService implements AddonModDataField
|
|||
originalContent.files = [uploadedFilesResult.online[0]];
|
||||
}
|
||||
|
||||
originalContent.content1 = <string>offlineContent.alttext || '';
|
||||
originalContent.content1 = <string> offlineContent.alttext || '';
|
||||
|
||||
return originalContent;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { AddonModDataField, AddonModDataSubfieldData } from '@addons/mod/data/services/data';
|
||||
import { AddonModDataEntryField, AddonModDataField, AddonModDataSubfieldData } from '@addons/mod/data/services/data';
|
||||
import { Injectable, Type } from '@angular/core';
|
||||
import { CoreFormFields } from '@singletons/form';
|
||||
import { Translate, makeSingleton } from '@singletons';
|
||||
|
@ -59,5 +59,14 @@ export class AddonModDataFieldUrlHandlerService extends AddonModDataFieldTextHan
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
overrideData(originalContent: AddonModDataEntryField, offlineContent: CoreFormFields<string>): AddonModDataEntryField {
|
||||
originalContent.content = offlineContent['0'] || '';
|
||||
|
||||
return originalContent;
|
||||
}
|
||||
|
||||
}
|
||||
export const AddonModDataFieldUrlHandler = makeSingleton(AddonModDataFieldUrlHandlerService);
|
||||
|
|
|
@ -92,9 +92,9 @@ export class AddonModDataHelperProvider {
|
|||
|
||||
if (offlineContent.subfield) {
|
||||
offlineContents[offlineContent.fieldid][offlineContent.subfield] =
|
||||
CoreTextUtils.parseJSON(offlineContent.value);
|
||||
CoreTextUtils.parseJSON(offlineContent.value, '');
|
||||
} else {
|
||||
offlineContents[offlineContent.fieldid][''] = CoreTextUtils.parseJSON(offlineContent.value);
|
||||
offlineContents[offlineContent.fieldid][''] = CoreTextUtils.parseJSON(offlineContent.value, '');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -632,7 +632,7 @@ export class AddonModDataHelperProvider {
|
|||
const folderPath = await AddonModDataOffline.getEntryFieldFolder(dataId, entryId, fieldId, siteId);
|
||||
|
||||
try {
|
||||
return CoreFileUploader.getStoredFiles(folderPath);
|
||||
return await CoreFileUploader.getStoredFiles(folderPath);
|
||||
} catch {
|
||||
// Ignore not found files.
|
||||
return [];
|
||||
|
|
|
@ -88,9 +88,9 @@ export class AddonModDataOfflineProvider {
|
|||
const promises: Promise<void>[] = [];
|
||||
|
||||
entry.fields.forEach((field) => {
|
||||
const value = CoreTextUtils.parseJSON<CoreFileUploaderStoreFilesResult>(field.value);
|
||||
const value = CoreTextUtils.parseJSON<CoreFileUploaderStoreFilesResult | null>(field.value, null);
|
||||
|
||||
if (!value.offline) {
|
||||
if (!value || !value.offline) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -345,8 +345,8 @@ export class AddonModDataSyncProvider extends CoreCourseActivitySyncBaseProvider
|
|||
try {
|
||||
await Promise.all(editAction.fields.map(async (field) => {
|
||||
// Upload Files if asked.
|
||||
const value = CoreTextUtils.parseJSON<CoreFileUploaderStoreFilesResult>(field.value || '');
|
||||
if (value.online || value.offline) {
|
||||
const value = CoreTextUtils.parseJSON<CoreFileUploaderStoreFilesResult | null>(field.value || '', null);
|
||||
if (value && (value.online || value.offline)) {
|
||||
let files: CoreFileEntry[] = value.online || [];
|
||||
|
||||
const offlineFiles = value.offline
|
||||
|
|
|
@ -155,7 +155,7 @@
|
|||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
<ion-card *ngIf="completed">
|
||||
<ion-card *ngIf="completed && (access!.canviewanalysis || hasNextPage)">
|
||||
<ion-grid>
|
||||
<ion-row class="ion-align-items-center">
|
||||
<ion-col *ngIf="access!.canviewanalysis">
|
||||
|
|
|
@ -98,7 +98,8 @@
|
|||
</ng-container>
|
||||
</ion-list>
|
||||
|
||||
<core-empty-box *ngIf="entries.empty" icon="fas-list" [message]="'addon.mod_glossary.noentriesfound' | translate">
|
||||
<core-empty-box *ngIf="entries.empty && (!isSearch || hasSearched)" icon="fas-list"
|
||||
[message]="'addon.mod_glossary.noentriesfound' | translate">
|
||||
</core-empty-box>
|
||||
|
||||
<core-infinite-loading [enabled]="!entries.completed" [error]="loadMoreError" (action)="loadMoreEntries($event)">
|
||||
|
|
|
@ -64,6 +64,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
|||
moduleName = 'glossary';
|
||||
|
||||
isSearch = false;
|
||||
hasSearched = false;
|
||||
canAdd = false;
|
||||
loadMoreError = false;
|
||||
loadingMessage?: string;
|
||||
|
@ -429,6 +430,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
|||
toggleSearch(): void {
|
||||
if (this.isSearch) {
|
||||
this.isSearch = false;
|
||||
this.hasSearched = false;
|
||||
this.entries.setOnlineEntries(this.fetchedEntries, this.fetchedEntriesCanLoadMore);
|
||||
this.switchMode(this.fetchMode!);
|
||||
} else {
|
||||
|
@ -488,6 +490,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
|||
'ASC',
|
||||
);
|
||||
this.loaded = false;
|
||||
this.hasSearched = true;
|
||||
this.loadContent();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import { CoreSupressEventsDirective } from './supress-events';
|
|||
import { CoreUserLinkDirective } from './user-link';
|
||||
import { CoreAriaButtonClickDirective } from './aria-button';
|
||||
import { CoreOnResizeDirective } from './on-resize';
|
||||
import { CoreDownloadFileDirective } from './download-file';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -41,6 +42,7 @@ import { CoreOnResizeDirective } from './on-resize';
|
|||
CoreUserLinkDirective,
|
||||
CoreAriaButtonClickDirective,
|
||||
CoreOnResizeDirective,
|
||||
CoreDownloadFileDirective,
|
||||
],
|
||||
exports: [
|
||||
CoreAutoFocusDirective,
|
||||
|
@ -55,6 +57,7 @@ import { CoreOnResizeDirective } from './on-resize';
|
|||
CoreUserLinkDirective,
|
||||
CoreAriaButtonClickDirective,
|
||||
CoreOnResizeDirective,
|
||||
CoreDownloadFileDirective,
|
||||
],
|
||||
})
|
||||
export class CoreDirectivesModule {}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
// (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 { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||
import { CoreFileHelper } from '@services/file-helper';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreWSFile } from '@services/ws';
|
||||
|
||||
/**
|
||||
* Directive to allow downloading and open a file. When the item with this directive is clicked, the file will be
|
||||
* downloaded (if needed) and opened.
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[core-download-file]',
|
||||
})
|
||||
export class CoreDownloadFileDirective implements OnInit {
|
||||
|
||||
@Input('core-download-file') file?: CoreWSFile; // The file to download.
|
||||
@Input() component?: string; // Component to link the file to.
|
||||
@Input() componentId?: string | number; // Component ID to use in conjunction with the component.
|
||||
|
||||
protected element: HTMLElement;
|
||||
|
||||
constructor(element: ElementRef) {
|
||||
this.element = element.nativeElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.element.addEventListener('click', async (ev: Event) => {
|
||||
if (!this.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
const modal = await CoreDomUtils.showModalLoading();
|
||||
|
||||
try {
|
||||
await CoreFileHelper.downloadAndOpenFile(this.file, this.component, this.componentId);
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -277,7 +277,10 @@ export class CoreUtilsProvider {
|
|||
return source;
|
||||
}
|
||||
|
||||
if (Array.isArray(source)) {
|
||||
if (this.valueIsFileEntry(source)) {
|
||||
// Don't clone FileEntry. It has a lot of depth and they shouldn't be modified.
|
||||
return source;
|
||||
} else if (Array.isArray(source)) {
|
||||
// Clone the array and all the entries.
|
||||
const newArray = [] as unknown as T;
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
|
@ -750,6 +753,18 @@ export class CoreUtilsProvider {
|
|||
return 'isFile' in file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an unknown value is a FileEntry.
|
||||
*
|
||||
* @param value Value to check.
|
||||
* @return Type guard indicating if the file is a FileEntry.
|
||||
*/
|
||||
valueIsFileEntry(file: unknown): file is FileEntry {
|
||||
// We cannot use instanceof because FileEntry is a type. Check some of the properties.
|
||||
return !!(file && typeof file == 'object' && 'isFile' in file && 'filesystem' in file &&
|
||||
'toInternalURL' in file && 'copyTo' in file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a value is an object.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue