MOBILE-2652 glossary: Clean up edit form

main
Noel De Martin 2023-03-22 15:41:10 +01:00
parent 5de4cfbbd2
commit 39a6d67c25
8 changed files with 132 additions and 141 deletions

View File

@ -259,7 +259,7 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource<
const entries: AddonModGlossaryEntryItem[] = []; const entries: AddonModGlossaryEntryItem[] = [];
if (page === 0) { if (page === 0) {
const offlineEntries = await AddonModGlossaryOffline.getGlossaryNewEntries(glossary.id); const offlineEntries = await AddonModGlossaryOffline.getGlossaryOfflineEntries(glossary.id);
offlineEntries.sort((a, b) => a.concept.localeCompare(b.concept)); offlineEntries.sort((a, b) => a.concept.localeCompare(b.concept));

View File

@ -16,7 +16,7 @@
<form #editFormEl *ngIf="glossary"> <form #editFormEl *ngIf="glossary">
<ion-item> <ion-item>
<ion-label position="stacked">{{ 'addon.mod_glossary.concept' | translate }}</ion-label> <ion-label position="stacked">{{ 'addon.mod_glossary.concept' | translate }}</ion-label>
<ion-input type="text" [placeholder]="'addon.mod_glossary.concept' | translate" [(ngModel)]="entry.concept" name="concept"> <ion-input type="text" [placeholder]="'addon.mod_glossary.concept' | translate" [(ngModel)]="data.concept" name="concept">
</ion-input> </ion-input>
</ion-item> </ion-item>
<ion-item> <ion-item>
@ -31,7 +31,7 @@
<ion-label position="stacked"> <ion-label position="stacked">
{{ 'addon.mod_glossary.categories' | translate }} {{ 'addon.mod_glossary.categories' | translate }}
</ion-label> </ion-label>
<ion-select [(ngModel)]="options.categories" multiple="true" interface="action-sheet" <ion-select [(ngModel)]="data.categories" multiple="true" interface="action-sheet"
[placeholder]="'addon.mod_glossary.categories' | translate" name="categories" [placeholder]="'addon.mod_glossary.categories' | translate" name="categories"
[interfaceOptions]="{header: 'addon.mod_glossary.categories' | translate}"> [interfaceOptions]="{header: 'addon.mod_glossary.categories' | translate}">
<ion-select-option *ngFor="let category of categories" [value]="category.id"> <ion-select-option *ngFor="let category of categories" [value]="category.id">
@ -43,7 +43,7 @@
<ion-label position="stacked"> <ion-label position="stacked">
{{ 'addon.mod_glossary.aliases' | translate }} {{ 'addon.mod_glossary.aliases' | translate }}
</ion-label> </ion-label>
<ion-textarea [(ngModel)]="options.aliases" rows="1" [core-auto-rows]="options.aliases" name="aliases"> <ion-textarea [(ngModel)]="data.aliases" rows="1" [core-auto-rows]="data.aliases" name="aliases">
</ion-textarea> </ion-textarea>
</ion-item> </ion-item>
<ion-item-divider> <ion-item-divider>
@ -51,7 +51,7 @@
<h2>{{ 'addon.mod_glossary.attachment' | translate }}</h2> <h2>{{ 'addon.mod_glossary.attachment' | translate }}</h2>
</ion-label> </ion-label>
</ion-item-divider> </ion-item-divider>
<core-attachments [files]="attachments" [component]="component" [componentId]="glossary.coursemodule" [allowOffline]="true" <core-attachments [files]="data.attachments" [component]="component" [componentId]="glossary.coursemodule" [allowOffline]="true"
[courseId]="courseId"> [courseId]="courseId">
</core-attachments> </core-attachments>
<ng-container *ngIf="glossary.usedynalink"> <ng-container *ngIf="glossary.usedynalink">
@ -62,19 +62,19 @@
</ion-item-divider> </ion-item-divider>
<ion-item class="ion-text-wrap"> <ion-item class="ion-text-wrap">
<ion-label>{{ 'addon.mod_glossary.entryusedynalink' | translate }}</ion-label> <ion-label>{{ 'addon.mod_glossary.entryusedynalink' | translate }}</ion-label>
<ion-toggle [(ngModel)]="options.usedynalink" name="usedynalink"></ion-toggle> <ion-toggle [(ngModel)]="data.usedynalink" name="usedynalink"></ion-toggle>
</ion-item> </ion-item>
<ion-item class="ion-text-wrap"> <ion-item class="ion-text-wrap">
<ion-label>{{ 'addon.mod_glossary.casesensitive' | translate }}</ion-label> <ion-label>{{ 'addon.mod_glossary.casesensitive' | translate }}</ion-label>
<ion-toggle [disabled]="!options.usedynalink" [(ngModel)]="options.casesensitive" name="casesensitive"> <ion-toggle [disabled]="!data.usedynalink" [(ngModel)]="data.casesensitive" name="casesensitive">
</ion-toggle> </ion-toggle>
</ion-item> </ion-item>
<ion-item class="ion-text-wrap"> <ion-item class="ion-text-wrap">
<ion-label>{{ 'addon.mod_glossary.fullmatch' | translate }}</ion-label> <ion-label>{{ 'addon.mod_glossary.fullmatch' | translate }}</ion-label>
<ion-toggle [disabled]="!options.usedynalink" [(ngModel)]="options.fullmatch" name="fullmatch"></ion-toggle> <ion-toggle [disabled]="!data.usedynalink" [(ngModel)]="data.fullmatch" name="fullmatch"></ion-toggle>
</ion-item> </ion-item>
</ng-container> </ng-container>
<ion-button class="ion-margin" expand="block" [disabled]="!entry.concept || !entry.definition" (click)="save()"> <ion-button class="ion-margin" expand="block" [disabled]="!data.concept || !data.definition" (click)="save()">
{{ 'core.save' | translate }} {{ 'core.save' | translate }}
</ion-button> </ion-button>
</form> </form>

View File

@ -20,7 +20,7 @@ import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/
import { CoreSplitViewComponent } from '@components/split-view/split-view'; import { CoreSplitViewComponent } from '@components/split-view/split-view';
import { CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fileuploader/services/fileuploader'; import { CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fileuploader/services/fileuploader';
import { CanLeave } from '@guards/can-leave'; import { CanLeave } from '@guards/can-leave';
import { FileEntry } from '@ionic-native/file/ngx'; import { CoreFileEntry } from '@services/file-helper';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
@ -36,8 +36,6 @@ import {
AddonModGlossaryCategory, AddonModGlossaryCategory,
AddonModGlossaryEntryOption, AddonModGlossaryEntryOption,
AddonModGlossaryGlossary, AddonModGlossaryGlossary,
AddonModGlossaryNewEntry,
AddonModGlossaryNewEntryWithFiles,
AddonModGlossaryProvider, AddonModGlossaryProvider,
} from '../../services/glossary'; } from '../../services/glossary';
import { AddonModGlossaryHelper } from '../../services/glossary-helper'; import { AddonModGlossaryHelper } from '../../services/glossary-helper';
@ -59,32 +57,29 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
courseId!: number; courseId!: number;
loaded = false; loaded = false;
glossary?: AddonModGlossaryGlossary; glossary?: AddonModGlossaryGlossary;
attachments: FileEntry[] = [];
definitionControl = new FormControl(); definitionControl = new FormControl();
categories: AddonModGlossaryCategory[] = []; categories: AddonModGlossaryCategory[] = [];
editorExtraParams: Record<string, unknown> = {}; editorExtraParams: Record<string, unknown> = {};
entry: AddonModGlossaryNewEntry = { data: AddonModGlossaryFormData = {
concept: '', concept: '',
definition: '', definition: '',
timecreated: 0, timecreated: 0,
}; attachments: [],
categories: [],
entries?: AddonModGlossaryEditEntriesSwipeManager;
options = {
categories: <string[]> [],
aliases: '', aliases: '',
usedynalink: false, usedynalink: false,
casesensitive: false, casesensitive: false,
fullmatch: false, fullmatch: false,
}; };
entries?: AddonModGlossaryEditEntriesSwipeManager;
protected timecreated!: number; protected timecreated!: number;
protected concept = ''; protected concept = '';
protected syncId?: string; protected syncId?: string;
protected syncObserver?: CoreEventObserver; protected syncObserver?: CoreEventObserver;
protected isDestroyed = false; protected isDestroyed = false;
protected originalData?: AddonModGlossaryNewEntryWithFiles; protected originalData?: AddonModGlossaryFormData;
protected saved = false; protected saved = false;
constructor(protected route: ActivatedRoute, @Optional() protected splitView: CoreSplitViewComponent) {} constructor(protected route: ActivatedRoute, @Optional() protected splitView: CoreSplitViewComponent) {}
@ -164,54 +159,64 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
return; return;
} }
const entry = await AddonModGlossaryOffline.getNewEntry(this.glossary.id, this.concept, this.timecreated); const entry = await AddonModGlossaryOffline.getOfflineEntry(this.glossary.id, this.concept, this.timecreated);
this.entry.concept = entry.concept || ''; this.data.concept = entry.concept || '';
this.entry.definition = entry.definition || ''; this.data.definition = entry.definition || '';
this.entry.timecreated = entry.timecreated; this.data.timecreated = entry.timecreated;
this.originalData = { this.originalData = {
concept: this.entry.concept, concept: this.data.concept,
definition: this.entry.definition, definition: this.data.definition,
files: [], attachments: this.data.attachments.slice(),
timecreated: entry.timecreated, timecreated: entry.timecreated,
categories: this.data.categories.slice(),
aliases: this.data.aliases,
usedynalink: this.data.usedynalink,
casesensitive: this.data.casesensitive,
fullmatch: this.data.fullmatch,
}; };
if (entry.options) { if (entry.options) {
this.options.categories = (entry.options.categories && (<string> entry.options.categories).split(',')) || []; this.data.categories = (entry.options.categories && (<string> entry.options.categories).split(',')) || [];
this.options.aliases = <string> entry.options.aliases || ''; this.data.aliases = <string> entry.options.aliases || '';
this.options.usedynalink = !!entry.options.usedynalink; this.data.usedynalink = !!entry.options.usedynalink;
if (this.options.usedynalink) {
this.options.casesensitive = !!entry.options.casesensitive; if (this.data.usedynalink) {
this.options.fullmatch = !!entry.options.fullmatch; this.data.casesensitive = !!entry.options.casesensitive;
this.data.fullmatch = !!entry.options.fullmatch;
} }
} }
// Treat offline attachments if any. // Treat offline attachments if any.
if (entry.attachments?.offline) { if (entry.attachments?.offline) {
this.attachments = await AddonModGlossaryHelper.getStoredFiles(this.glossary.id, entry.concept, entry.timecreated); this.data.attachments = await AddonModGlossaryHelper.getStoredFiles(
this.glossary.id,
entry.concept,
entry.timecreated,
);
this.originalData.files = this.attachments.slice(); this.originalData.attachments = this.data.attachments.slice();
} }
this.definitionControl.setValue(this.entry.definition); this.definitionControl.setValue(this.data.definition);
} }
/** /**
* Reset the form data. * Reset the form data.
*/ */
protected resetForm(): void { protected resetForm(): void {
this.entry.concept = '';
this.entry.definition = '';
this.entry.timecreated = 0;
this.originalData = undefined; this.originalData = undefined;
this.options.categories = []; this.data.concept = '';
this.options.aliases = ''; this.data.definition = '';
this.options.usedynalink = false; this.data.timecreated = 0;
this.options.casesensitive = false; this.data.categories = [];
this.options.fullmatch = false; this.data.aliases = '';
this.attachments.length = 0; // Empty the array. this.data.usedynalink = false;
this.data.casesensitive = false;
this.data.fullmatch = false;
this.data.attachments.length = 0; // Empty the array.
this.definitionControl.setValue(''); this.definitionControl.setValue('');
} }
@ -222,7 +227,7 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
* @param text The new text. * @param text The new text.
*/ */
onDefinitionChange(text: string): void { onDefinitionChange(text: string): void {
this.entry.definition = text; this.data.definition = text;
} }
/** /**
@ -235,13 +240,13 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
return true; return true;
} }
if (AddonModGlossaryHelper.hasEntryDataChanged(this.entry, this.attachments, this.originalData)) { if (this.hasDataChanged()) {
// Show confirmation if some data has been modified. // Show confirmation if some data has been modified.
await CoreDomUtils.showConfirm(Translate.instant('core.confirmcanceledit')); await CoreDomUtils.showConfirm(Translate.instant('core.confirmcanceledit'));
} }
// Delete the local files from the tmp folder. // Delete the local files from the tmp folder.
CoreFileUploader.clearTmpFiles(this.attachments); CoreFileUploader.clearTmpFiles(this.data.attachments);
CoreForms.triggerFormCancelledEvent(this.formElement, CoreSites.getCurrentSiteId()); CoreForms.triggerFormCancelledEvent(this.formElement, CoreSites.getCurrentSiteId());
@ -252,11 +257,11 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
* Save the entry. * Save the entry.
*/ */
async save(): Promise<void> { async save(): Promise<void> {
let definition = this.entry.definition; let definition = this.data.definition;
let entryId: number | undefined; let entryId: number | undefined;
const timecreated = this.entry.timecreated || Date.now(); const timecreated = this.data.timecreated || Date.now();
if (!this.entry.concept || !definition) { if (!this.data.concept || !definition) {
CoreDomUtils.showErrorModal('addon.mod_glossary.fillfields', true); CoreDomUtils.showErrorModal('addon.mod_glossary.fillfields', true);
return; return;
@ -274,23 +279,23 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
const { saveOffline, attachmentsResult } = await this.uploadAttachments(timecreated); const { saveOffline, attachmentsResult } = await this.uploadAttachments(timecreated);
const options: Record<string, AddonModGlossaryEntryOption> = { const options: Record<string, AddonModGlossaryEntryOption> = {
aliases: this.options.aliases, aliases: this.data.aliases,
categories: this.options.categories.join(','), categories: this.data.categories.join(','),
}; };
if (this.glossary.usedynalink) { if (this.glossary.usedynalink) {
options.usedynalink = this.options.usedynalink ? 1 : 0; options.usedynalink = this.data.usedynalink ? 1 : 0;
if (this.options.usedynalink) { if (this.data.usedynalink) {
options.casesensitive = this.options.casesensitive ? 1 : 0; options.casesensitive = this.data.casesensitive ? 1 : 0;
options.fullmatch = this.options.fullmatch ? 1 : 0; options.fullmatch = this.data.fullmatch ? 1 : 0;
} }
} }
if (saveOffline) { if (saveOffline) {
if (this.entry && !this.glossary.allowduplicatedentries) { if (this.data && !this.glossary.allowduplicatedentries) {
// Check if the entry is duplicated in online or offline mode. // Check if the entry is duplicated in online or offline mode.
const isUsed = await AddonModGlossary.isConceptUsed(this.glossary.id, this.entry.concept, { const isUsed = await AddonModGlossary.isConceptUsed(this.glossary.id, this.data.concept, {
timeCreated: this.entry.timecreated, timeCreated: this.data.timecreated,
cmId: this.cmId, cmId: this.cmId,
}); });
@ -301,9 +306,9 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
} }
// Save entry in offline. // Save entry in offline.
await AddonModGlossaryOffline.addNewEntry( await AddonModGlossaryOffline.addOfflineEntry(
this.glossary.id, this.glossary.id,
this.entry.concept, this.data.concept,
definition, definition,
this.courseId, this.courseId,
options, options,
@ -311,33 +316,33 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
timecreated, timecreated,
undefined, undefined,
undefined, undefined,
this.entry, this.data,
); );
} else { } else {
// Try to send it to server. // Try to send it to server.
// Don't allow offline if there are attachments since they were uploaded fine. // Don't allow offline if there are attachments since they were uploaded fine.
await AddonModGlossary.addEntry( await AddonModGlossary.addEntry(
this.glossary.id, this.glossary.id,
this.entry.concept, this.data.concept,
definition, definition,
this.courseId, this.courseId,
options, options,
attachmentsResult, attachmentsResult,
{ {
timeCreated: timecreated, timeCreated: timecreated,
discardEntry: this.entry, discardEntry: this.data,
allowOffline: !this.attachments.length, allowOffline: !this.data.attachments.length,
checkDuplicates: !this.glossary.allowduplicatedentries, checkDuplicates: !this.glossary.allowduplicatedentries,
}, },
); );
} }
// Delete the local files from the tmp folder. // Delete the local files from the tmp folder.
CoreFileUploader.clearTmpFiles(this.attachments); CoreFileUploader.clearTmpFiles(this.data.attachments);
if (entryId) { if (entryId) {
// Data sent to server, delete stored files (if any). // Data sent to server, delete stored files (if any).
AddonModGlossaryHelper.deleteStoredFiles(this.glossary.id, this.entry.concept, timecreated); AddonModGlossaryHelper.deleteStoredFiles(this.glossary.id, this.data.concept, timecreated);
CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'glossary' }); CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'glossary' });
} }
@ -367,6 +372,24 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
} }
} }
/**
* Check if the form data has changed.
*
* @returns True if data has changed, false otherwise.
*/
protected hasDataChanged(): boolean {
if (!this.originalData || this.originalData.concept === undefined) {
// There is no original data.
return !!(this.data.definition || this.data.concept || this.data.attachments.length > 0);
}
if (this.originalData.definition != this.data.definition || this.originalData.concept != this.data.concept) {
return true;
}
return CoreFileUploader.areFileListDifferent(this.data.attachments, this.originalData.attachments);
}
/** /**
* Upload entry attachments if any. * Upload entry attachments if any.
* *
@ -376,7 +399,7 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
protected async uploadAttachments( protected async uploadAttachments(
timecreated: number, timecreated: number,
): Promise<{saveOffline: boolean; attachmentsResult?: number | CoreFileUploaderStoreFilesResult}> { ): Promise<{saveOffline: boolean; attachmentsResult?: number | CoreFileUploaderStoreFilesResult}> {
if (!this.attachments.length || !this.glossary) { if (!this.data.attachments.length || !this.glossary) {
return { return {
saveOffline: false, saveOffline: false,
}; };
@ -384,7 +407,7 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
try { try {
const attachmentsResult = await CoreFileUploader.uploadOrReuploadFiles( const attachmentsResult = await CoreFileUploader.uploadOrReuploadFiles(
this.attachments, this.data.attachments,
AddonModGlossaryProvider.COMPONENT, AddonModGlossaryProvider.COMPONENT,
this.glossary.id, this.glossary.id,
); );
@ -401,9 +424,9 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
const attachmentsResult = await AddonModGlossaryHelper.storeFiles( const attachmentsResult = await AddonModGlossaryHelper.storeFiles(
this.glossary.id, this.glossary.id,
this.entry.concept, this.data.concept,
timecreated, timecreated,
this.attachments, this.data.attachments,
); );
return { return {
@ -439,3 +462,18 @@ class AddonModGlossaryEditEntriesSwipeManager extends AddonModGlossaryEntriesSwi
} }
} }
/**
* Form data.
*/
type AddonModGlossaryFormData = {
concept: string;
definition: string;
timecreated: number;
attachments: CoreFileEntry[];
categories: string[];
aliases: string;
usedynalink: boolean;
casesensitive: boolean;
fullmatch: boolean;
};

View File

@ -18,7 +18,6 @@ import { CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fi
import { CoreFile } from '@services/file'; import { CoreFile } from '@services/file';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { AddonModGlossaryOffline } from './glossary-offline'; import { AddonModGlossaryOffline } from './glossary-offline';
import { AddonModGlossaryNewEntry, AddonModGlossaryNewEntryWithFiles } from './glossary';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { CoreFileEntry } from '@services/file-helper'; import { CoreFileEntry } from '@services/file-helper';
@ -58,31 +57,6 @@ export class AddonModGlossaryHelperProvider {
return CoreFileUploader.getStoredFiles(folderPath); return CoreFileUploader.getStoredFiles(folderPath);
} }
/**
* Check if the data of an entry has changed.
*
* @param entry Current data.
* @param files Files attached.
* @param original Original content.
* @returns True if data has changed, false otherwise.
*/
hasEntryDataChanged(
entry: AddonModGlossaryNewEntry,
files: CoreFileEntry[],
original?: AddonModGlossaryNewEntryWithFiles,
): boolean {
if (!original || original.concept === undefined) {
// There is no original data.
return !!(entry.definition || entry.concept || files.length > 0);
}
if (original.definition != entry.definition || original.concept != entry.concept) {
return true;
}
return CoreFileUploader.areFileListDifferent(files, original.files);
}
/** /**
* Given a list of files (either online files or local files), store the local files in a local folder * Given a list of files (either online files or local files), store the local files in a local folder
* to be submitted later. * to be submitted later.

View File

@ -31,7 +31,7 @@ import { AddonModGlossaryEntryOption, GLOSSARY_ENTRY_ADDED } from './glossary';
export class AddonModGlossaryOfflineProvider { export class AddonModGlossaryOfflineProvider {
/** /**
* Delete a new entry. * Delete an offline entry.
* *
* @param glossaryId Glossary ID. * @param glossaryId Glossary ID.
* @param concept Glossary entry concept. * @param concept Glossary entry concept.
@ -39,7 +39,7 @@ export class AddonModGlossaryOfflineProvider {
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
* @returns Promise resolved if deleted, rejected if failure. * @returns Promise resolved if deleted, rejected if failure.
*/ */
async deleteNewEntry(glossaryId: number, concept: string, timeCreated: number, siteId?: string): Promise<void> { async deleteOfflineEntry(glossaryId: number, concept: string, timeCreated: number, siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId); const site = await CoreSites.getSite(siteId);
const conditions: Partial<AddonModGlossaryOfflineEntryDBRecord> = { const conditions: Partial<AddonModGlossaryOfflineEntryDBRecord> = {
@ -52,12 +52,12 @@ export class AddonModGlossaryOfflineProvider {
} }
/** /**
* Get all the stored new entries from all the glossaries. * Get all the stored offline entries from all the glossaries.
* *
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
* @returns Promise resolved with entries. * @returns Promise resolved with entries.
*/ */
async getAllNewEntries(siteId?: string): Promise<AddonModGlossaryOfflineEntry[]> { async getAllOfflineEntries(siteId?: string): Promise<AddonModGlossaryOfflineEntry[]> {
const site = await CoreSites.getSite(siteId); const site = await CoreSites.getSite(siteId);
const records = await site.getDb().getRecords<AddonModGlossaryOfflineEntryDBRecord>(OFFLINE_ENTRIES_TABLE_NAME); const records = await site.getDb().getRecords<AddonModGlossaryOfflineEntryDBRecord>(OFFLINE_ENTRIES_TABLE_NAME);
@ -66,7 +66,7 @@ export class AddonModGlossaryOfflineProvider {
} }
/** /**
* Get a stored new entry. * Get a stored offline entry.
* *
* @param glossaryId Glossary ID. * @param glossaryId Glossary ID.
* @param concept Glossary entry concept. * @param concept Glossary entry concept.
@ -74,7 +74,7 @@ export class AddonModGlossaryOfflineProvider {
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
* @returns Promise resolved with entry. * @returns Promise resolved with entry.
*/ */
async getNewEntry( async getOfflineEntry(
glossaryId: number, glossaryId: number,
concept: string, concept: string,
timeCreated: number, timeCreated: number,
@ -101,7 +101,7 @@ export class AddonModGlossaryOfflineProvider {
* @param userId User the entries belong to. If not defined, current user in site. * @param userId User the entries belong to. If not defined, current user in site.
* @returns Promise resolved with entries. * @returns Promise resolved with entries.
*/ */
async getGlossaryNewEntries(glossaryId: number, siteId?: string, userId?: number): Promise<AddonModGlossaryOfflineEntry[]> { async getGlossaryOfflineEntries(glossaryId: number, siteId?: string, userId?: number): Promise<AddonModGlossaryOfflineEntry[]> {
const site = await CoreSites.getSite(siteId); const site = await CoreSites.getSite(siteId);
const conditions: Partial<AddonModGlossaryOfflineEntryDBRecord> = { const conditions: Partial<AddonModGlossaryOfflineEntryDBRecord> = {
@ -144,7 +144,7 @@ export class AddonModGlossaryOfflineProvider {
} }
// If there's only one entry, check that is not the one we are editing. // If there's only one entry, check that is not the one we are editing.
return CoreUtils.promiseFails(this.getNewEntry(glossaryId, concept, timeCreated, siteId)); return CoreUtils.promiseFails(this.getOfflineEntry(glossaryId, concept, timeCreated, siteId));
} catch { } catch {
// No offline data found, return false. // No offline data found, return false.
return false; return false;
@ -152,7 +152,7 @@ export class AddonModGlossaryOfflineProvider {
} }
/** /**
* Save a new entry to be sent later. * Save an offline entry to be sent later.
* *
* @param glossaryId Glossary ID. * @param glossaryId Glossary ID.
* @param concept Glossary entry concept. * @param concept Glossary entry concept.
@ -166,7 +166,7 @@ export class AddonModGlossaryOfflineProvider {
* @param discardEntry The entry provided will be discarded if found. * @param discardEntry The entry provided will be discarded if found.
* @returns Promise resolved if stored, rejected if failure. * @returns Promise resolved if stored, rejected if failure.
*/ */
async addNewEntry( async addOfflineEntry(
glossaryId: number, glossaryId: number,
concept: string, concept: string,
definition: string, definition: string,
@ -195,7 +195,7 @@ export class AddonModGlossaryOfflineProvider {
// If editing an offline entry, delete previous first. // If editing an offline entry, delete previous first.
if (discardEntry) { if (discardEntry) {
await this.deleteNewEntry(glossaryId, discardEntry.concept, discardEntry.timecreated, site.getId()); await this.deleteOfflineEntry(glossaryId, discardEntry.concept, discardEntry.timecreated, site.getId());
} }
await site.getDb().insertRecord(OFFLINE_ENTRIES_TABLE_NAME, entry); await site.getDb().insertRecord(OFFLINE_ENTRIES_TABLE_NAME, entry);
@ -222,7 +222,7 @@ export class AddonModGlossaryOfflineProvider {
} }
/** /**
* Get the path to the folder where to store files for a new offline entry. * Get the path to the folder where to store files for an offline entry.
* *
* @param glossaryId Glossary ID. * @param glossaryId Glossary ID.
* @param concept The name of the entry. * @param concept The name of the entry.

View File

@ -50,10 +50,9 @@ export class AddonModGlossarySyncProvider extends CoreCourseActivitySyncBaseProv
* *
* @param siteId Site ID to sync. If not defined, sync all sites. * @param siteId Site ID to sync. If not defined, sync all sites.
* @param force Wether to force sync not depending on last execution. * @param force Wether to force sync not depending on last execution.
* @returns Promise resolved if sync is successful, rejected if sync fails.
*/ */
syncAllGlossaries(siteId?: string, force?: boolean): Promise<void> { async syncAllGlossaries(siteId?: string, force?: boolean): Promise<void> {
return this.syncOnSites('all glossaries', (siteId) => this.syncAllGlossariesFunc(!!force, siteId), siteId); await this.syncOnSites('all glossaries', (siteId) => this.syncAllGlossariesFunc(!!force, siteId), siteId);
} }
/** /**
@ -61,7 +60,6 @@ export class AddonModGlossarySyncProvider extends CoreCourseActivitySyncBaseProv
* *
* @param force Wether to force sync not depending on last execution. * @param force Wether to force sync not depending on last execution.
* @param siteId Site ID to sync. * @param siteId Site ID to sync.
* @returns Promise resolved if sync is successful, rejected if sync fails.
*/ */
protected async syncAllGlossariesFunc(force: boolean, siteId: string): Promise<void> { protected async syncAllGlossariesFunc(force: boolean, siteId: string): Promise<void> {
siteId = siteId || CoreSites.getCurrentSiteId(); siteId = siteId || CoreSites.getCurrentSiteId();
@ -73,14 +71,13 @@ export class AddonModGlossarySyncProvider extends CoreCourseActivitySyncBaseProv
} }
/** /**
* Sync entried of all glossaries on a site. * Sync entries of all glossaries on a site.
* *
* @param force Wether to force sync not depending on last execution. * @param force Wether to force sync not depending on last execution.
* @param siteId Site ID to sync. * @param siteId Site ID to sync.
* @returns Promise resolved if sync is successful, rejected if sync fails.
*/ */
protected async syncAllGlossariesEntries(force: boolean, siteId: string): Promise<void> { protected async syncAllGlossariesEntries(force: boolean, siteId: string): Promise<void> {
const entries = await AddonModGlossaryOffline.getAllNewEntries(siteId); const entries = await AddonModGlossaryOffline.getAllOfflineEntries(siteId);
// Do not sync same glossary twice. // Do not sync same glossary twice.
const treated: Record<number, boolean> = {}; const treated: Record<number, boolean> = {};
@ -180,7 +177,7 @@ export class AddonModGlossarySyncProvider extends CoreCourseActivitySyncBaseProv
// Get offline responses to be sent. // Get offline responses to be sent.
const entries = await CoreUtils.ignoreErrors( const entries = await CoreUtils.ignoreErrors(
AddonModGlossaryOffline.getGlossaryNewEntries(glossaryId, siteId, userId), AddonModGlossaryOffline.getGlossaryOfflineEntries(glossaryId, siteId, userId),
<AddonModGlossaryOfflineEntry[]> [], <AddonModGlossaryOfflineEntry[]> [],
); );
@ -285,11 +282,10 @@ export class AddonModGlossarySyncProvider extends CoreCourseActivitySyncBaseProv
* @param concept Glossary entry concept. * @param concept Glossary entry concept.
* @param timeCreated Time to allow duplicated entries. * @param timeCreated Time to allow duplicated entries.
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when deleted.
*/ */
protected async deleteAddEntry(glossaryId: number, concept: string, timeCreated: number, siteId?: string): Promise<void> { protected async deleteAddEntry(glossaryId: number, concept: string, timeCreated: number, siteId?: string): Promise<void> {
await Promise.all([ await Promise.all([
AddonModGlossaryOffline.deleteNewEntry(glossaryId, concept, timeCreated, siteId), AddonModGlossaryOffline.deleteOfflineEntry(glossaryId, concept, timeCreated, siteId),
AddonModGlossaryHelper.deleteStoredFiles(glossaryId, concept, timeCreated, siteId), AddonModGlossaryHelper.deleteStoredFiles(glossaryId, concept, timeCreated, siteId),
]); ]);
} }

View File

@ -28,7 +28,6 @@ import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { AddonModGlossaryEntryDBRecord, ENTRIES_TABLE_NAME } from './database/glossary'; import { AddonModGlossaryEntryDBRecord, ENTRIES_TABLE_NAME } from './database/glossary';
import { AddonModGlossaryOffline } from './glossary-offline'; import { AddonModGlossaryOffline } from './glossary-offline';
import { CoreFileEntry } from '@services/file-helper';
export const GLOSSARY_ENTRY_ADDED = 'addon_mod_glossary_entry_added'; export const GLOSSARY_ENTRY_ADDED = 'addon_mod_glossary_entry_added';
export const GLOSSARY_ENTRY_DELETED = 'addon_mod_glossary_entry_deleted'; export const GLOSSARY_ENTRY_DELETED = 'addon_mod_glossary_entry_deleted';
@ -827,7 +826,7 @@ export class AddonModGlossaryProvider {
throw new CoreError('Error adding entry.'); throw new CoreError('Error adding entry.');
} }
await AddonModGlossaryOffline.addNewEntry( await AddonModGlossaryOffline.addOfflineEntry(
glossaryId, glossaryId,
concept, concept,
definition, definition,
@ -850,7 +849,7 @@ export class AddonModGlossaryProvider {
// If we are editing an offline entry, discard previous first. // If we are editing an offline entry, discard previous first.
if (otherOptions.discardEntry) { if (otherOptions.discardEntry) {
await AddonModGlossaryOffline.deleteNewEntry( await AddonModGlossaryOffline.deleteOfflineEntry(
glossaryId, glossaryId,
otherOptions.discardEntry.concept, otherOptions.discardEntry.concept,
otherOptions.discardEntry.timecreated, otherOptions.discardEntry.timecreated,
@ -1377,22 +1376,6 @@ export type AddonModGlossaryDiscardedEntry = {
timecreated: number; timecreated: number;
}; };
/**
* Entry to be added.
*/
export type AddonModGlossaryNewEntry = {
concept: string;
definition: string;
timecreated: number;
};
/**
* Entry to be added, including attachments.
*/
export type AddonModGlossaryNewEntryWithFiles = AddonModGlossaryNewEntry & {
files: CoreFileEntry[];
};
/** /**
* Options to pass to the different get entries functions. * Options to pass to the different get entries functions.
*/ */

View File

@ -6,7 +6,7 @@ information provided here is intended especially for developers.
- CoreIconComponent has been removed after deprecation period: Use CoreFaIconDirective instead. - CoreIconComponent has been removed after deprecation period: Use CoreFaIconDirective instead.
- The courseSummaryComponent property has been removed from the CoreCourseFormatComponent component, and the getCourseSummaryComponent method from the CoreCourseFormatHandler interface. - The courseSummaryComponent property has been removed from the CoreCourseFormatComponent component, and the getCourseSummaryComponent method from the CoreCourseFormatHandler interface.
- Font Awesome icon library has been updated to 6.3.0. - Font Awesome icon library has been updated to 6.3.0.
- Some methods in AddonModGlossaryProvider have changed their signatures to remove unused parameters. - Some methods in glossary addon services have changed.
=== 4.1.0 === === 4.1.0 ===