diff --git a/src/addons/mod/glossary/pages/entry/entry.ts b/src/addons/mod/glossary/pages/entry/entry.ts index 7c6e6076d..bc3d5b022 100644 --- a/src/addons/mod/glossary/pages/entry/entry.ts +++ b/src/addons/mod/glossary/pages/entry/entry.ts @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { AddonModGlossaryHelper } from '@addons/mod/glossary/services/glossary-helper'; import { AddonModGlossaryOffline, AddonModGlossaryOfflineEntry } from '@addons/mod/glossary/services/glossary-offline'; import { Component, OnDestroy, OnInit, Optional, ViewChild } from '@angular/core'; import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'; @@ -138,31 +139,38 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy { * Delete entry. */ async deleteEntry(): Promise { - if (!this.onlineEntry) { - return; - } - - const entryId = this.onlineEntry.id; const glossaryId = this.glossary?.id; const cancelled = await CoreUtils.promiseFails( CoreDomUtils.showConfirm(Translate.instant('addon.mod_glossary.areyousuredelete')), ); - if (!entryId || !glossaryId || cancelled) { + if (!glossaryId || cancelled) { return; } const modal = await CoreDomUtils.showModalLoading(); try { - await AddonModGlossary.deleteEntry(glossaryId, entryId); - await CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntry(entryId)); - await CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByLetter(glossaryId)); - await CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByAuthor(glossaryId)); - await CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByCategory(glossaryId)); - await CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByDate(glossaryId, 'CREATION')); - await CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByDate(glossaryId, 'UPDATE')); - await CoreUtils.ignoreErrors(this.entries.getSource().invalidateCache(false)); + if (this.onlineEntry) { + const entryId = this.onlineEntry.id; + + await AddonModGlossary.deleteEntry(glossaryId, entryId); + await Promise.all([ + CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntry(entryId)), + CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByLetter(glossaryId)), + CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByAuthor(glossaryId)), + CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByCategory(glossaryId)), + CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByDate(glossaryId, 'CREATION')), + CoreUtils.ignoreErrors(AddonModGlossary.invalidateEntriesByDate(glossaryId, 'UPDATE')), + CoreUtils.ignoreErrors(this.entries.getSource().invalidateCache(false)), + ]); + } else if (this.offlineEntry) { + const concept = this.offlineEntry.concept; + const timecreated = this.offlineEntry.timecreated; + + await AddonModGlossaryOffline.deleteOfflineEntry(glossaryId, concept, timecreated); + await AddonModGlossaryHelper.deleteStoredFiles(glossaryId, concept, timecreated); + } CoreDomUtils.showToast('addon.mod_glossary.entrydeleted', true, ToastDuration.LONG); @@ -234,6 +242,7 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy { const glossary = await this.loadGlossary(); this.offlineEntry = await AddonModGlossaryOffline.getOfflineEntry(glossary.id, concept, timecreated); + this.canDelete = true; } catch (error) { CoreDomUtils.showErrorModalDefault(error, 'addon.mod_glossary.errorloadingentry', true); } diff --git a/src/addons/mod/glossary/services/glossary-offline.ts b/src/addons/mod/glossary/services/glossary-offline.ts index 3c748248f..784b1ea8c 100644 --- a/src/addons/mod/glossary/services/glossary-offline.ts +++ b/src/addons/mod/glossary/services/glossary-offline.ts @@ -17,12 +17,11 @@ import { CoreFileUploaderStoreFilesResult } from '@features/fileuploader/service import { CoreFile } from '@services/file'; import { CoreSites } from '@services/sites'; import { CoreTextUtils } from '@services/utils/text'; -import { CoreUtils } from '@services/utils/utils'; import { makeSingleton } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { CorePath } from '@singletons/path'; import { AddonModGlossaryOfflineEntryDBRecord, OFFLINE_ENTRIES_TABLE_NAME } from './database/glossary'; -import { AddonModGlossaryEntryOption, GLOSSARY_ENTRY_ADDED } from './glossary'; +import { AddonModGlossaryEntryOption, GLOSSARY_ENTRY_ADDED, GLOSSARY_ENTRY_DELETED } from './glossary'; /** * Service to handle offline glossary. @@ -35,20 +34,22 @@ export class AddonModGlossaryOfflineProvider { * * @param glossaryId Glossary ID. * @param concept Glossary entry concept. - * @param timeCreated The time the entry was created. + * @param timecreated The time the entry was created. * @param siteId Site ID. If not defined, current site. * @returns Promise resolved if deleted, rejected if failure. */ - async deleteOfflineEntry(glossaryId: number, concept: string, timeCreated: number, siteId?: string): Promise { + async deleteOfflineEntry(glossaryId: number, concept: string, timecreated: number, siteId?: string): Promise { const site = await CoreSites.getSite(siteId); const conditions: Partial = { glossaryid: glossaryId, concept: concept, - timecreated: timeCreated, + timecreated, }; await site.getDb().deleteRecords(OFFLINE_ENTRIES_TABLE_NAME, conditions); + + CoreEvents.trigger(GLOSSARY_ENTRY_DELETED, { glossaryId, timecreated }); } /** diff --git a/src/addons/mod/glossary/tests/behat/basic_usage.feature b/src/addons/mod/glossary/tests/behat/basic_usage.feature index 48bea05b8..f9b898bd8 100644 --- a/src/addons/mod/glossary/tests/behat/basic_usage.feature +++ b/src/addons/mod/glossary/tests/behat/basic_usage.feature @@ -195,6 +195,7 @@ Feature: Test basic usage of glossary in app Scenario: Delete entries Given I entered the glossary activity "Test glossary" on course "Course 1" as "student1" in the app + # Online When I press "Cucumber" in the app And I press "Delete entry" in the app And I press "OK" near "Are you sure you want to delete this entry?" in the app @@ -202,6 +203,25 @@ Feature: Test basic usage of glossary in app And I should find "Potato" in the app But I should not find "Cucumber" in the app + # Offline + When I press "Add a new entry" in the app + And I switch network connection to offline + And I set the following fields to these values in the app: + | Concept | Broccoli | + | Definition | Brassica oleracea var. italica | + And I press "Save" in the app + Then I should find "Potato" in the app + And I should find "Broccoli" in the app + + When I press "Broccoli" in the app + Then I should find "Brassica oleracea var. italica" in the app + + When I press "Delete entry" in the app + And I press "OK" near "Are you sure you want to delete this entry?" in the app + Then I should find "Entry deleted" in the app + And I should find "Potato" in the app + But I should not find "Broccoli" in the app + Scenario: Sync Given I entered the glossary activity "Test glossary" on course "Course 1" as "student1" in the app And I press "Add a new entry" in the app @@ -240,8 +260,8 @@ Feature: Test basic usage of glossary in app And I should find "Broccoli" in the app And I should find "Cabbage" in the app And I should find "Garlic" in the app - But I should not see "Entries to be synced" - And I should not see "This Glossary has offline data to be synchronised." + But I should not find "Entries to be synced" in the app + And I should not find "This Glossary has offline data to be synchronised." in the app When I press "Garlic" in the app Then I should find "Garlic" in the app