diff --git a/scripts/langindex.json b/scripts/langindex.json index 71c85af4c..373656b89 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1760,7 +1760,6 @@ "core.login.visitchangepassword": "local_moodlemobileapp", "core.login.webservicesnotenabled": "local_moodlemobileapp", "core.lostconnection": "local_moodlemobileapp", - "core.mainmenu.appsettings": "local_moodlemobileapp", "core.mainmenu.changesite": "local_moodlemobileapp", "core.mainmenu.help": "moodle", "core.mainmenu.logout": "moodle", @@ -1891,6 +1890,7 @@ "core.sending": "chat", "core.serverconnection": "error", "core.settings.about": "local_moodlemobileapp", + "core.settings.appsettings": "local_moodlemobileapp", "core.settings.appversion": "local_moodlemobileapp", "core.settings.cannotsyncoffline": "local_moodlemobileapp", "core.settings.cannotsyncwithoutwifi": "local_moodlemobileapp", @@ -1941,6 +1941,7 @@ "core.settings.navigatoruseragent": "local_moodlemobileapp", "core.settings.networkstatus": "local_moodlemobileapp", "core.settings.opensourcelicenses": "local_moodlemobileapp", + "core.settings.preferences": "moodle", "core.settings.privacypolicy": "local_moodlemobileapp", "core.settings.publisher": "local_moodlemobileapp", "core.settings.pushid": "local_moodlemobileapp", @@ -1951,8 +1952,10 @@ "core.settings.siteinfo": "local_moodlemobileapp", "core.settings.sites": "moodle", "core.settings.spaceusage": "local_moodlemobileapp", + "core.settings.spaceusagehelp": "local_moodlemobileapp", "core.settings.synchronization": "local_moodlemobileapp", "core.settings.synchronizenow": "local_moodlemobileapp", + "core.settings.synchronizenowhelp": "local_moodlemobileapp", "core.settings.syncsettings": "local_moodlemobileapp", "core.settings.total": "moodle", "core.settings.wificonnection": "local_moodlemobileapp", diff --git a/src/addon/block/activitymodules/components/activitymodules/addon-block-activitymodules.html b/src/addon/block/activitymodules/components/activitymodules/addon-block-activitymodules.html index 342e38924..fc407eb4b 100644 --- a/src/addon/block/activitymodules/components/activitymodules/addon-block-activitymodules.html +++ b/src/addon/block/activitymodules/components/activitymodules/addon-block-activitymodules.html @@ -2,7 +2,7 @@

{{ 'addon.block_activitymodules.pluginname' | translate }}

- + {{ entry.name }} diff --git a/src/addon/files/pages/list/list.html b/src/addon/files/pages/list/list.html index b119855ca..3b9207168 100644 --- a/src/addon/files/pages/list/list.html +++ b/src/addon/files/pages/list/list.html @@ -23,7 +23,7 @@ - +

{{file.filename}}

diff --git a/src/addon/messages/pages/settings/settings.html b/src/addon/messages/pages/settings/settings.html index 0172888d9..c955efb2e 100644 --- a/src/addon/messages/pages/settings/settings.html +++ b/src/addon/messages/pages/settings/settings.html @@ -1,6 +1,6 @@ - {{ 'addon.messages.messagepreferences' | translate }} + {{ 'addon.messages.messages' | translate }} diff --git a/src/addon/messages/providers/settings-handler.ts b/src/addon/messages/providers/settings-handler.ts index 6c4d35447..b3a4b62df 100644 --- a/src/addon/messages/providers/settings-handler.ts +++ b/src/addon/messages/providers/settings-handler.ts @@ -44,9 +44,9 @@ export class AddonMessagesSettingsHandler implements CoreSettingsHandler { getDisplayData(): CoreSettingsHandlerData { return { icon: 'chatbubbles', - title: 'addon.messages.messagepreferences', + title: 'addon.messages.messages', page: 'AddonMessagesSettingsPage', - class: 'addon-messages-settings-handler' + class: 'addon-messages-settings-handler', }; } diff --git a/src/addon/mod/folder/components/index/addon-mod-folder-index.html b/src/addon/mod/folder/components/index/addon-mod-folder-index.html index 0015e5120..03eb3838a 100644 --- a/src/addon/mod/folder/components/index/addon-mod-folder-index.html +++ b/src/addon/mod/folder/components/index/addon-mod-folder-index.html @@ -17,7 +17,7 @@ - +

{{file.name}}

diff --git a/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html b/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html index 2bf84b83a..440d7f383 100644 --- a/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html +++ b/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html @@ -244,7 +244,7 @@ {{ 'addon.mod_lesson.overview' | translate }} - +

{{ student.fullname }}

diff --git a/src/addon/mod/quiz/components/index/addon-mod-quiz-index.html b/src/addon/mod/quiz/components/index/addon-mod-quiz-index.html index a522eae7b..88de59576 100644 --- a/src/addon/mod/quiz/components/index/addon-mod-quiz-index.html +++ b/src/addon/mod/quiz/components/index/addon-mod-quiz-index.html @@ -52,7 +52,7 @@ -
+ {{ 'addon.mod_quiz.preview' | translate }} {{ attempt.attempt }} diff --git a/src/addon/mod/quiz/pages/attempt/attempt.html b/src/addon/mod/quiz/pages/attempt/attempt.html index 2998605d7..791991ada 100644 --- a/src/addon/mod/quiz/pages/attempt/attempt.html +++ b/src/addon/mod/quiz/pages/attempt/attempt.html @@ -31,7 +31,7 @@

- diff --git a/src/addon/notifications/pages/settings/settings.html b/src/addon/notifications/pages/settings/settings.html index b6502c2c0..66c94edf3 100644 --- a/src/addon/notifications/pages/settings/settings.html +++ b/src/addon/notifications/pages/settings/settings.html @@ -1,6 +1,6 @@ - {{ 'addon.notifications.notificationpreferences' | translate }} + {{ 'addon.notifications.notifications' | translate }} diff --git a/src/addon/notifications/providers/settings-handler.ts b/src/addon/notifications/providers/settings-handler.ts index 95036ef59..08339302a 100644 --- a/src/addon/notifications/providers/settings-handler.ts +++ b/src/addon/notifications/providers/settings-handler.ts @@ -49,9 +49,9 @@ export class AddonNotificationsSettingsHandler implements CoreSettingsHandler { getDisplayData(): CoreSettingsHandlerData { return { icon: 'notifications', - title: 'addon.notifications.notificationpreferences', + title: 'addon.notifications.notifications', page: 'AddonNotificationsSettingsPage', - class: 'addon-notifications-settings-handler' + class: 'addon-notifications-settings-handler', }; } } diff --git a/src/app/app.scss b/src/app/app.scss index b8d54baf3..ffd022894 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -106,6 +106,9 @@ ion-app.app-root { .item h2 { text-overflow: inherit; overflow: inherit; + ion-icon, core-icon { + vertical-align: bottom; + } } .core-nav-item-selected, .item.core-nav-item-selected { diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 215946d1a..769a0c480 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1760,7 +1760,6 @@ "core.login.visitchangepassword": "Do you want to visit the site to change the password?", "core.login.webservicesnotenabled": "Web services are not enabled in your site. Please contact your site administrator if you think they should be enabled.", "core.lostconnection": "Your authentication token is invalid or has expired. You will have to reconnect to the site.", - "core.mainmenu.appsettings": "App settings", "core.mainmenu.changesite": "Change site", "core.mainmenu.help": "Help", "core.mainmenu.logout": "Log out", @@ -1891,6 +1890,7 @@ "core.sending": "Sending", "core.serverconnection": "Error connecting to the server", "core.settings.about": "About", + "core.settings.appsettings": "App settings", "core.settings.appversion": "App version", "core.settings.cannotsyncoffline": "Cannot synchronise offline.", "core.settings.cannotsyncwithoutwifi": "Cannot synchronise because the current settings only allow to synchronise when connected to Wi-Fi. Please connect to a Wi-Fi network.", @@ -1941,6 +1941,7 @@ "core.settings.navigatoruseragent": "Navigator userAgent", "core.settings.networkstatus": "Internet connection status", "core.settings.opensourcelicenses": "Open Source Licences", + "core.settings.preferences": "Preferences", "core.settings.privacypolicy": "Privacy policy", "core.settings.publisher": "Publisher", "core.settings.pushid": "Push notifications ID", @@ -1951,8 +1952,10 @@ "core.settings.siteinfo": "Site info", "core.settings.sites": "Sites", "core.settings.spaceusage": "Space usage", + "core.settings.spaceusagehelp": "Deleting the stored information of the site will remove all the site offline data. This information allows you to use the app when offline. ", "core.settings.synchronization": "Synchronisation", "core.settings.synchronizenow": "Synchronise now", + "core.settings.synchronizenowhelp": "Synchronising a site will send pending changes and all offline activity stored in the device and will synchronise some data like messages and notifications.", "core.settings.syncsettings": "Synchronisation settings", "core.settings.total": "Total", "core.settings.wificonnection": "Wi-Fi connection", diff --git a/src/core/login/pages/credentials/credentials.html b/src/core/login/pages/credentials/credentials.html index 467bb49dd..a1b2f1069 100644 --- a/src/core/login/pages/credentials/credentials.html +++ b/src/core/login/pages/credentials/credentials.html @@ -3,8 +3,8 @@ {{ 'core.login.login' | translate }} - diff --git a/src/core/login/pages/site/site.html b/src/core/login/pages/site/site.html index 9503d5335..6a4b40f36 100644 --- a/src/core/login/pages/site/site.html +++ b/src/core/login/pages/site/site.html @@ -3,8 +3,8 @@ {{ 'core.login.connecttomoodle' | translate }} -
+ + +

{{ 'core.settings.synchronizenow' | translate }}

+ + +
+ +
+
+ + diff --git a/src/core/settings/pages/site/site.module.ts b/src/core/settings/pages/site/site.module.ts new file mode 100644 index 000000000..d7e2a43c3 --- /dev/null +++ b/src/core/settings/pages/site/site.module.ts @@ -0,0 +1,35 @@ +// (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 { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { CoreSitePreferencesPage } from './site'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; +import { CorePipesModule } from '@pipes/pipes.module'; + +@NgModule({ + declarations: [ + CoreSitePreferencesPage, + ], + imports: [ + CoreComponentsModule, + CoreDirectivesModule, + CorePipesModule, + IonicPageModule.forChild(CoreSitePreferencesPage), + TranslateModule.forChild(), + ], +}) +export class CoreSitePreferencesPageModule {} diff --git a/src/core/settings/pages/site/site.ts b/src/core/settings/pages/site/site.ts new file mode 100644 index 000000000..4f35c7feb --- /dev/null +++ b/src/core/settings/pages/site/site.ts @@ -0,0 +1,198 @@ +// (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 { Component, ViewChild } from '@angular/core'; +import { IonicPage, NavParams, Platform } from 'ionic-angular'; +import { TranslateService } from '@ngx-translate/core'; +import { CoreSettingsDelegate, CoreSettingsHandlerData } from '../../providers/delegate'; +import { CoreEventsProvider } from '@providers/events'; +import { CoreSitesProvider, CoreSiteBasicInfo } from '@providers/sites'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreSplitViewComponent } from '@components/split-view/split-view'; +import { CoreSharedFilesProvider } from '@core/sharedfiles/providers/sharedfiles'; +import { CoreSettingsHelper, CoreSiteSpaceUsage } from '../../providers/helper'; + +/** + * Page that displays the list of site settings pages. + */ +@IonicPage({segment: 'core-site-preferences'}) +@Component({ + selector: 'page-core-site-preferences', + templateUrl: 'site.html', +}) +export class CoreSitePreferencesPage { + @ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent; + + handlers: CoreSettingsHandlerData[]; + isIOS: boolean; + selectedPage: string; + siteId: string; + siteInfo: CoreSiteBasicInfo[] = []; + siteName: string; + siteUrl: string; + spaceUsage: CoreSiteSpaceUsage = { + cacheEntries: 0, + spaceUsage: 0 + }; + loaded = false; + iosSharedFiles: number; + protected sitesObserver: any; + protected isDestroyed = false; + + constructor(protected settingsDelegate: CoreSettingsDelegate, + protected settingsHelper: CoreSettingsHelper, + protected sitesProvider: CoreSitesProvider, + protected domUtils: CoreDomUtilsProvider, + protected eventsProvider: CoreEventsProvider, + protected sharedFilesProvider: CoreSharedFilesProvider, + protected translate: TranslateService, + platorm: Platform, + navParams: NavParams, + ) { + + this.isIOS = platorm.is('ios'); + + this.selectedPage = navParams.get('page') || false; + + this.sitesObserver = this.eventsProvider.on(CoreEventsProvider.SITE_UPDATED, (data) => { + if (data.siteId == this.siteId) { + this.refreshData(); + } + }); + } + + /** + * View loaded. + */ + ionViewDidLoad(): void { + this.fetchData().finally(() => { + this.loaded = true; + + if (this.selectedPage) { + this.openHandler(this.selectedPage); + } else if (this.splitviewCtrl.isOn()) { + if (this.isIOS) { + this.openHandler('CoreSharedFilesListPage', {manage: true, siteId: this.siteId, hideSitePicker: true}); + } else if (this.handlers.length > 0) { + this.openHandler(this.handlers[0].page, this.handlers[0].params); + } + } + }); + } + + /** + * Fetch Data. + */ + protected async fetchData(): Promise { + this.handlers = this.settingsDelegate.getHandlers(); + const currentSite = this.sitesProvider.getCurrentSite(); + this.siteId = currentSite.id; + this.siteInfo = currentSite.getInfo(); + this.siteName = currentSite.getSiteName(); + this.siteUrl = currentSite.getURL(); + + const promises = []; + + promises.push(this.settingsHelper.getSiteSpaceUsage(this.siteId).then((spaceUsage) => this.spaceUsage = spaceUsage)); + + if (this.isIOS) { + promises.push(this.sharedFilesProvider.getSiteSharedFiles(this.siteId).then((files) => + this.iosSharedFiles = files.length + )); + } + + await Promise.all(promises); + } + + /** + * Syncrhonizes the site. + */ + synchronize(siteId: string): void { + // Using syncOnlyOnWifi false to force manual sync. + this.settingsHelper.synchronizeSite(false, this.siteId).catch((error) => { + if (this.isDestroyed) { + return; + } + this.domUtils.showErrorModalDefault(error, 'core.settings.errorsyncsite', true); + }); + } + + /** + * Returns true if site is beeing synchronized. + * + * @return True if site is beeing synchronized, false otherwise. + */ + isSynchronizing(): boolean { + return this.siteId && !!this.settingsHelper.getSiteSyncPromise(this.siteId); + } + + /** + * Refresh the data. + * + * @param refresher Refresher. + */ + refreshData(refresher?: any): void { + this.fetchData().finally(() => { + refresher && refresher.complete(); + }); + } + + /** + * Deletes files of a site and the tables that can be cleared. + * + * @param siteData Site object with space usage. + */ + deleteSiteStorage(): void { + this.settingsHelper.deleteSiteStorage(this.siteName, this.siteId).then((newInfo) => { + this.spaceUsage = newInfo; + }).catch(() => { + // Ignore cancelled confirmation modal. + }); + } + + /** + * Open a handler. + * + * @param page Page to open. + * @param params Params of the page to open. + */ + openHandler(page: string, params?: any): void { + this.selectedPage = page; + this.splitviewCtrl.push(page, params); + } + + /** + * Show information about space usage actions. + */ + showSpaceInfo(): void { + this.domUtils.showAlert(this.translate.instant('core.help'), + this.translate.instant('core.settings.spaceusagehelp')); + } + + /** + * Show information about sync actions. + */ + showSyncInfo(): void { + this.domUtils.showAlert(this.translate.instant('core.help'), + this.translate.instant('core.settings.synchronizenowhelp')); + } + + /** + * Page destroyed. + */ + ngOnDestroy(): void { + this.isDestroyed = true; + this.sitesObserver && this.sitesObserver.off(); + } +} diff --git a/src/core/settings/pages/space-usage/space-usage.html b/src/core/settings/pages/space-usage/space-usage.html index f4d247a89..29dac4705 100644 --- a/src/core/settings/pages/space-usage/space-usage.html +++ b/src/core/settings/pages/space-usage/space-usage.html @@ -1,13 +1,20 @@ {{ 'core.settings.spaceusage' | translate }} + + + + + - + - +

{{ site.fullName }}

@@ -19,11 +26,11 @@
- -

{{ 'core.settings.total' | translate }}

+ +

{{ 'core.settings.total' | translate }}

-

{{ totalUsage | coreBytesToSize }}

-

{{ 'core.settings.entriesincache' | translate: { $a: totalEntries } }}

+

{{ totals.spaceUsage | coreBytesToSize }}

+

{{ 'core.settings.entriesincache' | translate: { $a: totals.cacheEntries } }}

diff --git a/src/core/settings/pages/space-usage/space-usage.ts b/src/core/settings/pages/space-usage/space-usage.ts index 8b8254837..35a49c323 100644 --- a/src/core/settings/pages/space-usage/space-usage.ts +++ b/src/core/settings/pages/space-usage/space-usage.ts @@ -15,14 +15,9 @@ import { Component, } from '@angular/core'; import { IonicPage } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; -import { CoreAppProvider } from '@providers/app'; -import { CoreEventsProvider } from '@providers/events'; -import { CoreFilepoolProvider } from '@providers/filepool'; -import { CoreSitesProvider } from '@providers/sites'; +import { CoreSitesProvider, CoreSiteBasicInfo } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; -import { CoreCourseProvider } from '@core/course/providers/course'; -import { CoreFilterProvider } from '@core/filter/providers/filter'; -import { CoreSite } from '@classes/site'; +import { CoreSettingsHelper, CoreSiteSpaceUsage } from '../../providers/helper'; /** * Page that displays the space usage settings. @@ -34,20 +29,19 @@ import { CoreSite } from '@classes/site'; }) export class CoreSettingsSpaceUsagePage { - usageLoaded = false; + loaded = false; sites = []; currentSiteId = ''; - totalUsage = 0; - totalEntries = 0; + totals: CoreSiteSpaceUsage = { + cacheEntries: 0, + spaceUsage: 0 + }; - constructor(private filePoolProvider: CoreFilepoolProvider, - private eventsProvider: CoreEventsProvider, - private sitesProvider: CoreSitesProvider, - private filterProvider: CoreFilterProvider, - private translate: TranslateService, - private domUtils: CoreDomUtilsProvider, - appProvider: CoreAppProvider, - private courseProvider: CoreCourseProvider) { + constructor(protected sitesProvider: CoreSitesProvider, + protected settingsHelper: CoreSettingsHelper, + protected domUtils: CoreDomUtilsProvider, + protected translate: TranslateService, + ) { this.currentSiteId = this.sitesProvider.getCurrentSiteId(); } @@ -55,66 +49,36 @@ export class CoreSettingsSpaceUsagePage { * View loaded. */ ionViewDidLoad(): void { - this.fetchData().finally(() => { - this.usageLoaded = true; + this.loadSiteData().finally(() => { + this.loaded = true; }); } /** - * Convenience function to calculate each site's usage, and the total usage. + * Convenience function to load site data/usage and calculate the totals. * * @return Resolved when done. */ - protected calculateSizeUsage(): Promise { - return this.sitesProvider.getSortedSites().then((sites) => { - this.sites = sites; + protected async loadSiteData(): Promise { + // Calculate total usage. + let totalSize = 0; + let totalEntries = 0; - // Get space usage. - const promises = this.sites.map((siteEntry) => { - return this.sitesProvider.getSite(siteEntry.id).then((site) => { - const proms2 = []; + this.sites = await this.sitesProvider.getSortedSites(); - proms2.push(this.calcSiteClearRows(site).then((rows) => { - siteEntry.cacheEntries = rows; - })); + // Get space usage. + await Promise.all(this.sites.map(async (site) => { + const siteInfo = await this.settingsHelper.getSiteSpaceUsage(site.id); - proms2.push(site.getSpaceUsage().then((size) => { - siteEntry.spaceUsage = size; - })); + site.cacheEntries = siteInfo.cacheEntries; + site.spaceUsage = siteInfo.spaceUsage; - return Promise.all(proms2); - }); - }); - - return Promise.all(promises); - }); - } - - /** - * Convenience function to calculate total usage. - */ - protected calculateTotalUsage(): void { - let totalSize = 0, - totalEntries = 0; - this.sites.forEach((site) => { totalSize += (site.spaceUsage ? parseInt(site.spaceUsage, 10) : 0); totalEntries += (site.cacheEntries ? parseInt(site.cacheEntries, 10) : 0); - }); - this.totalUsage = totalSize; - this.totalEntries = totalEntries; - } + })); - /** - * Convenience function to calculate space usage. - * - * @return Resolved when done. - */ - protected fetchData(): Promise { - const promises = [ - this.calculateSizeUsage().then(() => this.calculateTotalUsage()), - ]; - - return Promise.all(promises); + this.totals.spaceUsage = totalSize; + this.totals.cacheEntries = totalEntries; } /** @@ -123,96 +87,40 @@ export class CoreSettingsSpaceUsagePage { * @param refresher Refresher. */ refreshData(refresher: any): void { - this.fetchData().finally(() => { + this.loadSiteData().finally(() => { refresher.complete(); }); } - /** - * Convenience function to update site size, along with total usage. - * - * @param site Site object with space usage. - * @param newUsage New space usage of the site in bytes. - */ - protected updateSiteUsage(site: any, newUsage: number): void { - const oldUsage = site.spaceUsage; - site.spaceUsage = newUsage; - this.totalUsage -= oldUsage - newUsage; - } - - /** - * Calculate the number of rows to be deleted on a site. - * - * @param site Site object. - * @return If there are rows to delete or not. - */ - protected calcSiteClearRows(site: CoreSite): Promise { - const clearTables = this.sitesProvider.getSiteTableSchemasToClear(site); - - let totalEntries = 0; - - const promises = clearTables.map((name) => { - return site.getDb().countRecords(name).then((rows) => { - totalEntries += rows; - }); - }); - - return Promise.all(promises).then(() => { - return totalEntries; - }); - } - /** * Deletes files of a site and the tables that can be cleared. * * @param siteData Site object with space usage. */ - deleteSiteStorage(siteData: any): void { - this.filterProvider.formatText(siteData.siteName, {clean: true, singleLine: true, filter: false}, [], siteData.id) - .then((siteName) => { - - const title = this.translate.instant('core.settings.deletesitefilestitle'); - const message = this.translate.instant('core.settings.deletesitefiles', {sitename: siteName}); - - this.domUtils.showConfirm(message, title).then(() => { - return this.sitesProvider.getSite(siteData.id); - }).then((site) => { - - // Clear cache tables. - const cleanSchemas = this.sitesProvider.getSiteTableSchemasToClear(site); - const promises = cleanSchemas.map((name) => { - return site.getDb().deleteRecords(name); - }); - - promises.push(site.deleteFolder().then(() => { - this.filePoolProvider.clearAllPackagesStatus(site.id); - this.filePoolProvider.clearFilepool(site.id); - this.updateSiteUsage(siteData, 0); - this.courseProvider.clearAllCoursesStatus(site.id); - }).catch((error) => { - if (error && error.code === FileError.NOT_FOUND_ERR) { - // Not found, set size 0. - this.filePoolProvider.clearAllPackagesStatus(site.id); - this.updateSiteUsage(siteData, 0); - } else { - // Error, recalculate the site usage. - this.domUtils.showErrorModal('core.settings.errordeletesitefiles', true); - site.getSpaceUsage().then((size) => { - this.updateSiteUsage(siteData, size); - }); - } - }).finally(() => { - this.eventsProvider.trigger(CoreEventsProvider.SITE_STORAGE_DELETED, {}, site.getId()); - - this.calcSiteClearRows(site).then((rows) => { - siteData.cacheEntries = rows; - }); - })); - - return Promise.all(promises); - }).catch(() => { - // Ignore cancelled confirmation modal. - }); + deleteSiteStorage(siteData: CoreSiteBasicInfoWithUsage): void { + this.settingsHelper.deleteSiteStorage(siteData.siteName, siteData.id).then((newInfo) => { + this.totals.spaceUsage -= siteData.spaceUsage - newInfo.spaceUsage; + this.totals.spaceUsage -= siteData.cacheEntries - newInfo.cacheEntries; + siteData.spaceUsage = newInfo.spaceUsage; + siteData.cacheEntries = newInfo.cacheEntries; + }).catch(() => { + // Ignore cancelled confirmation modal. }); } + + /** + * Show information about space usage actions. + */ + showInfo(): void { + this.domUtils.showAlert(this.translate.instant('core.help'), + this.translate.instant('core.settings.spaceusagehelp')); + } +} + +/** + * Basic site info with space usage and cache entries that can be erased. + */ +export interface CoreSiteBasicInfoWithUsage extends CoreSiteBasicInfo { + cacheEntries?: number; // Number of cached entries that can be cleared. + spaceUsage?: number; // Space used in this site. } diff --git a/src/core/settings/pages/synchronization/synchronization.html b/src/core/settings/pages/synchronization/synchronization.html index 3f7a6a2a1..bb5b62e0f 100644 --- a/src/core/settings/pages/synchronization/synchronization.html +++ b/src/core/settings/pages/synchronization/synchronization.html @@ -1,12 +1,19 @@ {{ 'core.settings.synchronization' | translate }} + + + + + -

{{ 'core.settings.syncsettings' | translate }}

+

{{ 'core.settings.syncsettings' | translate }}

{{ 'core.settings.enablesyncwifi' | translate }} @@ -14,7 +21,7 @@ -

{{ 'core.settings.sites' | translate }}

+

{{ 'core.settings.sites' | translate }}

diff --git a/src/core/settings/pages/synchronization/synchronization.ts b/src/core/settings/pages/synchronization/synchronization.ts index c478c4ad8..77a7eddf5 100644 --- a/src/core/settings/pages/synchronization/synchronization.ts +++ b/src/core/settings/pages/synchronization/synchronization.ts @@ -14,6 +14,7 @@ import { Component, OnDestroy } from '@angular/core'; import { IonicPage } from 'ionic-angular'; +import { TranslateService } from '@ngx-translate/core'; import { CoreConstants } from '@core/constants'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider, CoreSiteBasicInfo } from '@providers/sites'; @@ -36,11 +37,15 @@ export class CoreSettingsSynchronizationPage implements OnDestroy { sitesObserver: any; currentSiteId = ''; syncOnlyOnWifi = false; - isDestroyed = false; + protected isDestroyed = false; - constructor(private configProvider: CoreConfigProvider, private eventsProvider: CoreEventsProvider, - private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider, - private settingsHelper: CoreSettingsHelper) { + constructor(protected configProvider: CoreConfigProvider, + protected eventsProvider: CoreEventsProvider, + protected sitesProvider: CoreSitesProvider, + protected domUtils: CoreDomUtilsProvider, + protected settingsHelper: CoreSettingsHelper, + protected translate: TranslateService, + ) { this.currentSiteId = this.sitesProvider.getCurrentSiteId(); @@ -85,7 +90,8 @@ export class CoreSettingsSynchronizationPage implements OnDestroy { * @param siteId Site ID. */ synchronize(siteId: string): void { - this.settingsHelper.synchronizeSite(this.syncOnlyOnWifi, siteId).catch((error) => { + // Using syncOnlyOnWifi false to force manual sync. + this.settingsHelper.synchronizeSite(false, siteId).catch((error) => { if (this.isDestroyed) { return; } @@ -103,6 +109,14 @@ export class CoreSettingsSynchronizationPage implements OnDestroy { return !!this.settingsHelper.getSiteSyncPromise(siteId); } + /** + * Show information about sync actions. + */ + showInfo(): void { + this.domUtils.showAlert(this.translate.instant('core.help'), + this.translate.instant('core.settings.synchronizenowhelp')); + } + /** * Page destroyed. */ diff --git a/src/core/settings/providers/helper.ts b/src/core/settings/providers/helper.ts index 41b5ddd4d..b61b0a79d 100644 --- a/src/core/settings/providers/helper.ts +++ b/src/core/settings/providers/helper.ts @@ -18,13 +18,24 @@ import { CoreCronDelegate } from '@providers/cron'; import { CoreEventsProvider } from '@providers/events'; import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreLoggerProvider } from '@providers/logger'; +import { CoreSite } from '@classes/site'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreConstants } from '@core/constants'; import { CoreConfigProvider } from '@providers/config'; +import { CoreFilterProvider } from '@core/filter/providers/filter'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreConfigConstants } from '../../../configconstants'; import { TranslateService } from '@ngx-translate/core'; -import { CoreSite } from '@classes/site'; + +/** + * Object with space usage and cache entries that can be erased. + */ +export interface CoreSiteSpaceUsage { + cacheEntries?: number; // Number of cached entries that can be cleared. + spaceUsage?: number; // Space used in this site. +} /** * Settings helper service. @@ -34,10 +45,19 @@ export class CoreSettingsHelper { protected logger; protected syncPromises = {}; - constructor(loggerProvider: CoreLoggerProvider, private appProvider: CoreAppProvider, private cronDelegate: CoreCronDelegate, - private eventsProvider: CoreEventsProvider, private filePoolProvider: CoreFilepoolProvider, - private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private translate: TranslateService, - private configProvider: CoreConfigProvider) { + constructor(loggerProvider: CoreLoggerProvider, + protected appProvider: CoreAppProvider, + protected cronDelegate: CoreCronDelegate, + protected domUtils: CoreDomUtilsProvider, + protected eventsProvider: CoreEventsProvider, + protected filePoolProvider: CoreFilepoolProvider, + protected sitesProvider: CoreSitesProvider, + protected utils: CoreUtilsProvider, + protected translate: TranslateService, + protected configProvider: CoreConfigProvider, + protected filterProvider: CoreFilterProvider, + protected courseProvider: CoreCourseProvider, + ) { this.logger = loggerProvider.getInstance('CoreSettingsHelper'); if (!CoreConfigConstants.forceColorScheme) { @@ -63,6 +83,101 @@ export class CoreSettingsHelper { } } + /** + * Deletes files of a site and the tables that can be cleared. + * + * @param siteName Site Name. + * @param siteId: Site ID. + * @return Resolved with detailed new info when done. + */ + async deleteSiteStorage(siteName: string, siteId: string): Promise { + const siteInfo: CoreSiteSpaceUsage = { + cacheEntries: 0, + spaceUsage: 0 + }; + + siteName = await this.filterProvider.formatText(siteName, {clean: true, singleLine: true, filter: false}, [], siteId); + + const title = this.translate.instant('core.settings.deletesitefilestitle'); + const message = this.translate.instant('core.settings.deletesitefiles', {sitename: siteName}); + + await this.domUtils.showConfirm(message, title); + + const site = await this.sitesProvider.getSite(siteId); + + // Clear cache tables. + const cleanSchemas = this.sitesProvider.getSiteTableSchemasToClear(site); + const promises = cleanSchemas.map((name) => site.getDb().deleteRecords(name)); + + promises.push(site.deleteFolder().then(() => { + this.filePoolProvider.clearAllPackagesStatus(site.id); + this.filePoolProvider.clearFilepool(site.id); + this.courseProvider.clearAllCoursesStatus(site.id); + + siteInfo.spaceUsage = 0; + }).catch(async (error) => { + if (error && error.code === FileError.NOT_FOUND_ERR) { + // Not found, set size 0. + this.filePoolProvider.clearAllPackagesStatus(site.id); + siteInfo.spaceUsage = 0; + } else { + // Error, recalculate the site usage. + this.domUtils.showErrorModal('core.settings.errordeletesitefiles', true); + + siteInfo.spaceUsage = await site.getSpaceUsage(); + } + }).then(async () => { + this.eventsProvider.trigger(CoreEventsProvider.SITE_STORAGE_DELETED, {}, site.getId()); + + siteInfo.cacheEntries = await this.calcSiteClearRows(site); + })); + + await Promise.all(promises); + + return siteInfo; + } + + /** + * Calculates each site's usage, and the total usage. + * + * @param siteId ID of the site. Current site if undefined. + * @return Resolved with detailed info when done. + */ + async getSiteSpaceUsage(siteId?: string): Promise { + const site = await this.sitesProvider.getSite(siteId); + + // Get space usage. + const siteInfo: CoreSiteSpaceUsage = { + cacheEntries: 0, + spaceUsage: 0, + }; + + await Promise.all([ + this.calcSiteClearRows(site).then((rows) => siteInfo.cacheEntries = rows), + site.getSpaceUsage().then((size) => siteInfo.spaceUsage = size), + ]); + + return siteInfo; + } + + /** + * Calculate the number of rows to be deleted on a site. + * + * @param site Site object. + * @return If there are rows to delete or not. + */ + protected async calcSiteClearRows(site: CoreSite): Promise { + const clearTables = this.sitesProvider.getSiteTableSchemasToClear(site); + + let totalEntries = 0; + + await Promise.all(clearTables.map(async (name) => + totalEntries += await site.getDb().countRecords(name) + )); + + return totalEntries; + } + /** * Get a certain processor from a list of processors. * diff --git a/src/core/sharedfiles/pages/list/list.html b/src/core/sharedfiles/pages/list/list.html index 5f210c99a..06bbf5228 100644 --- a/src/core/sharedfiles/pages/list/list.html +++ b/src/core/sharedfiles/pages/list/list.html @@ -14,7 +14,7 @@
- + diff --git a/src/core/sharedfiles/pages/list/list.ts b/src/core/sharedfiles/pages/list/list.ts index ec408963c..66c8b199c 100644 --- a/src/core/sharedfiles/pages/list/list.ts +++ b/src/core/sharedfiles/pages/list/list.ts @@ -35,6 +35,7 @@ export class CoreSharedFilesListPage implements OnInit, OnDestroy { isModal: boolean; manage: boolean; pick: boolean; // To pick a file you MUST use a modal. + showSitePicker: boolean; path = ''; title: string; filesLoaded: boolean; @@ -52,6 +53,7 @@ export class CoreSharedFilesListPage implements OnInit, OnDestroy { this.manage = !!navParams.get('manage'); this.pick = !!navParams.get('pick'); this.path = navParams.get('path') || ''; + this.showSitePicker = !navParams.get('hideSitePicker'); } /** diff --git a/src/core/sitehome/components/all-course-list/core-sitehome-all-course-list.html b/src/core/sitehome/components/all-course-list/core-sitehome-all-course-list.html index 4ae3a0095..615f2251c 100644 --- a/src/core/sitehome/components/all-course-list/core-sitehome-all-course-list.html +++ b/src/core/sitehome/components/all-course-list/core-sitehome-all-course-list.html @@ -1,4 +1,4 @@ - +

{{ 'core.courses.availablecourses' | translate}}

diff --git a/src/core/sitehome/components/categories/core-sitehome-categories.html b/src/core/sitehome/components/categories/core-sitehome-categories.html index 9ecbba6da..24f9365a8 100644 --- a/src/core/sitehome/components/categories/core-sitehome-categories.html +++ b/src/core/sitehome/components/categories/core-sitehome-categories.html @@ -1,4 +1,4 @@ - +

{{ 'core.courses.categories' | translate}}

diff --git a/src/core/sitehome/components/course-search/core-sitehome-course-search.html b/src/core/sitehome/components/course-search/core-sitehome-course-search.html index e67ae19ee..c420ae151 100644 --- a/src/core/sitehome/components/course-search/core-sitehome-course-search.html +++ b/src/core/sitehome/components/course-search/core-sitehome-course-search.html @@ -1,4 +1,4 @@ - +

{{ 'core.courses.searchcourses' | translate}}

diff --git a/src/core/sitehome/components/enrolled-course-list/core-sitehome-enrolled-course-list.html b/src/core/sitehome/components/enrolled-course-list/core-sitehome-enrolled-course-list.html index 9de854ec5..0d917350a 100644 --- a/src/core/sitehome/components/enrolled-course-list/core-sitehome-enrolled-course-list.html +++ b/src/core/sitehome/components/enrolled-course-list/core-sitehome-enrolled-course-list.html @@ -1,4 +1,4 @@ - +

{{ 'core.courses.mycourses' | translate}}