Merge pull request #2998 from dpalou/MOBILE-3902
MOBILE-3902 notifications: Warn admin if push are disabled
This commit is contained in:
		
						commit
						c5c662989b
					
				| @ -1063,6 +1063,7 @@ | ||||
|   "addon.notifications.notificationpreferences": "message", | ||||
|   "addon.notifications.notifications": "local_moodlemobileapp", | ||||
|   "addon.notifications.playsound": "local_moodlemobileapp", | ||||
|   "addon.notifications.pushdisabledwarning": "local_moodlemobileapp", | ||||
|   "addon.notifications.therearentnotificationsyet": "local_moodlemobileapp", | ||||
|   "addon.notifications.unreadnotification": "message", | ||||
|   "addon.privatefiles.couldnotloadfiles": "local_moodlemobileapp", | ||||
| @ -1667,6 +1668,7 @@ | ||||
|   "core.fulllistofcourses": "moodle", | ||||
|   "core.fullnameandsitename": "local_moodlemobileapp", | ||||
|   "core.fullscreen": "h5p", | ||||
|   "core.goto": "local_moodlemobileapp", | ||||
|   "core.grades.aggregatemean": "grades", | ||||
|   "core.grades.aggregatesum": "grades", | ||||
|   "core.grades.average": "grades", | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
|     "notificationpreferences": "Notification preferences", | ||||
|     "notifications": "Notifications", | ||||
|     "playsound": "Play sound", | ||||
|     "pushdisabledwarning": "Your users are not receiving any notification from this site on their mobile devices. Enable mobile notifications in the Notification settings page.", | ||||
|     "therearentnotificationsyet": "There are no notifications.", | ||||
|     "unreadnotification": "Unread notification: {{$a}}" | ||||
| } | ||||
|  | ||||
| @ -26,7 +26,7 @@ import { AddonNotificationsCronHandler } from './services/handlers/cron'; | ||||
| import { AddonNotificationsPushClickHandler } from './services/handlers/push-click'; | ||||
| import { AddonNotificationsSettingsHandler, AddonNotificationsSettingsHandlerService } from './services/handlers/settings'; | ||||
| import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing'; | ||||
| import { AddonNotificationsProvider } from './services/notifications'; | ||||
| import { AddonNotifications, AddonNotificationsProvider } from './services/notifications'; | ||||
| import { AddonNotificationsHelperProvider } from './services/notifications-helper'; | ||||
| 
 | ||||
| export const ADDON_NOTIFICATIONS_SERVICES: Type<unknown>[] = [ | ||||
| @ -65,6 +65,7 @@ const preferencesRoutes: Routes = [ | ||||
|                 CoreSettingsDelegate.registerHandler(AddonNotificationsSettingsHandler.instance); | ||||
| 
 | ||||
|                 AddonNotificationsMainMenuHandler.initialize(); | ||||
|                 AddonNotifications.initialize(); | ||||
|             }, | ||||
|         }, | ||||
|     ], | ||||
|  | ||||
| @ -14,15 +14,18 @@ | ||||
| 
 | ||||
| import { Injectable } from '@angular/core'; | ||||
| 
 | ||||
| import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites'; | ||||
| import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites'; | ||||
| import { CoreWSExternalWarning } from '@services/ws'; | ||||
| import { CoreTextUtils } from '@services/utils/text'; | ||||
| import { CoreTimeUtils } from '@services/utils/time'; | ||||
| import { CoreUser } from '@features/user/services/user'; | ||||
| import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; | ||||
| import { CoreLogger } from '@singletons/logger'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { makeSingleton, Translate } from '@singletons'; | ||||
| import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; | ||||
| import { CoreEvents } from '@singletons/events'; | ||||
| import { CoreDomUtils } from '@services/utils/dom'; | ||||
| import { CoreUtils } from '@services/utils/utils'; | ||||
| 
 | ||||
| const ROOT_CACHE_KEY = 'mmaNotifications:'; | ||||
| 
 | ||||
| @ -43,6 +46,15 @@ export class AddonNotificationsProvider { | ||||
|         this.logger = CoreLogger.getInstance('AddonNotificationsProvider'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Initialize the service. | ||||
|      */ | ||||
|     initialize(): void { | ||||
|         CoreEvents.on(CoreEvents.LOGIN, (data) => { | ||||
|             this.warnPushDisabledForAdmin(data.siteId); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Function to format notification data. | ||||
|      * | ||||
| @ -115,16 +127,17 @@ export class AddonNotificationsProvider { | ||||
|     /** | ||||
|      * Get notification preferences. | ||||
|      * | ||||
|      * @param siteId Site ID. If not defined, use current site. | ||||
|      * @param options Options. | ||||
|      * @return Promise resolved with the notification preferences. | ||||
|      */ | ||||
|     async getNotificationPreferences(siteId?: string): Promise<AddonNotificationsPreferences> { | ||||
|     async getNotificationPreferences(options: CoreSitesCommonWSOptions = {}): Promise<AddonNotificationsPreferences> { | ||||
|         this.logger.debug('Get notification preferences'); | ||||
| 
 | ||||
|         const site = await CoreSites.getSite(siteId); | ||||
|         const site = await CoreSites.getSite(options.siteId); | ||||
|         const preSets: CoreSiteWSPreSets = { | ||||
|             cacheKey: this.getNotificationPreferencesCacheKey(), | ||||
|             updateFrequency: CoreSite.FREQUENCY_SOMETIMES, | ||||
|             ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
 | ||||
|         }; | ||||
| 
 | ||||
|         const data = await site.read<AddonNotificationsGetUserNotificationPreferencesResult>( | ||||
| @ -382,6 +395,80 @@ export class AddonNotificationsProvider { | ||||
|         await site.invalidateWsCacheForKey(this.getNotificationsCacheKey()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Is user is an admin and push are disabled, notify him. | ||||
|      * | ||||
|      * @param siteId Site ID. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async warnPushDisabledForAdmin(siteId?: string): Promise<void> { | ||||
|         if (!siteId) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             const site = await CoreSites.getSite(siteId); | ||||
| 
 | ||||
|             if (!site.getInfo()?.userissiteadmin) { | ||||
|                 // Not an admin or we don't know, stop.
 | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // Check if the admin already asked not to be reminded.
 | ||||
|             const dontAsk = await site.getLocalSiteConfig('AddonNotificationsDontRemindPushDisabled', 0); | ||||
|             if (dontAsk) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // Check if push are disabled.
 | ||||
|             const preferences = await this.getNotificationPreferences({ | ||||
|                 readingStrategy: CoreSitesReadingStrategy.ONLY_NETWORK, | ||||
|                 siteId, | ||||
|             }); | ||||
| 
 | ||||
|             const processor = preferences.processors.find(processor => processor.name === 'airnotifier'); | ||||
|             if (processor) { | ||||
|                 // Enabled.
 | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // Warn the admin.
 | ||||
|             const dontShowAgain = await CoreDomUtils.showPrompt( | ||||
|                 Translate.instant('addon.notifications.pushdisabledwarning'), | ||||
|                 undefined, | ||||
|                 Translate.instant('core.dontshowagain'), | ||||
|                 'checkbox', | ||||
|                 [ | ||||
|                     { | ||||
|                         text: Translate.instant('core.ok'), | ||||
|                     }, | ||||
|                     { | ||||
|                         text: Translate.instant('core.goto', { $a: Translate.instant('core.settings.settings') }), | ||||
|                         handler: (data, resolve) => { | ||||
|                             resolve(data[0]); | ||||
| 
 | ||||
|                             const url = CoreTextUtils.concatenatePaths( | ||||
|                                 site.getURL(), | ||||
|                                 site.isVersionGreaterEqualThan('3.11') ? | ||||
|                                     'message/output/airnotifier/checkconfiguration.php' : | ||||
|                                     'admin/message.php', | ||||
|                             ); | ||||
| 
 | ||||
|                             // Don't try auto-login, admins cannot use it.
 | ||||
|                             CoreUtils.openInBrowser(url); | ||||
|                         }, | ||||
|                     }, | ||||
|                 ], | ||||
|             ); | ||||
| 
 | ||||
|             if (dontShowAgain) { | ||||
|                 await site.setLocalSiteConfig('AddonNotificationsDontRemindPushDisabled', 1); | ||||
|             } | ||||
|         } catch { | ||||
|             // Ignore errors.
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export const AddonNotifications = makeSingleton(AddonNotificationsProvider); | ||||
|  | ||||
| @ -123,6 +123,7 @@ | ||||
|     "fulllistofcourses": "All courses", | ||||
|     "fullnameandsitename": "{{fullname}} ({{sitename}})", | ||||
|     "fullscreen": "Fullscreen", | ||||
|     "goto": "Go to {{$a}}", | ||||
|     "group": "Group", | ||||
|     "groupsseparate": "Separate groups", | ||||
|     "groupsvisible": "Visible groups", | ||||
|  | ||||
| @ -1478,7 +1478,7 @@ export class CoreDomUtilsProvider { | ||||
|      * @param header Modal header. | ||||
|      * @param placeholderOrLabel Placeholder (for textual/numeric inputs) or label (for radio/checkbox). By default, "Password". | ||||
|      * @param type Type of the input element. By default, password. | ||||
|      * @param options More options to pass to the alert. | ||||
|      * @param buttons Buttons. If not provided, OK and Cancel buttons will be displayed. | ||||
|      * @return Promise resolved with the input data (true for checkbox/radio) if the user clicks OK, rejected if cancels. | ||||
|      */ | ||||
|     showPrompt( | ||||
| @ -1486,12 +1486,25 @@ export class CoreDomUtilsProvider { | ||||
|         header?: string, | ||||
|         placeholderOrLabel?: string, | ||||
|         type: TextFieldTypes | 'checkbox' | 'radio' | 'textarea' = 'password', | ||||
|         buttons?: PromptButton[], | ||||
|     ): Promise<any> { // eslint-disable-line @typescript-eslint/no-explicit-any
 | ||||
|         return new Promise((resolve, reject) => { | ||||
|             placeholderOrLabel = placeholderOrLabel ?? Translate.instant('core.login.password'); | ||||
| 
 | ||||
|             const isCheckbox = type === 'checkbox'; | ||||
|             const isRadio = type === 'radio'; | ||||
| 
 | ||||
|             // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||
|             const resolvePromise = (data: any) => { | ||||
|                 if (isCheckbox) { | ||||
|                     resolve(data[0]); | ||||
|                 } else if (isRadio) { | ||||
|                     resolve(data); | ||||
|                 } else { | ||||
|                     resolve(data.promptinput); | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
|             const options: AlertOptions = { | ||||
|                 header, | ||||
|                 message, | ||||
| @ -1504,7 +1517,25 @@ export class CoreDomUtilsProvider { | ||||
|                         value: (isCheckbox || isRadio) ? true : undefined, | ||||
|                     }, | ||||
|                 ], | ||||
|                 buttons: [ | ||||
|             }; | ||||
| 
 | ||||
|             if (buttons?.length) { | ||||
|                 options.buttons = buttons.map((button) => ({ | ||||
|                     ...button, | ||||
|                     handler: (data) => { | ||||
|                         if (!button.handler) { | ||||
|                             // Just resolve the promise.
 | ||||
|                             resolvePromise(data); | ||||
| 
 | ||||
|                             return; | ||||
|                         } | ||||
| 
 | ||||
|                         button.handler(data, resolve, reject); | ||||
|                     }, | ||||
|                 })); | ||||
|             } else { | ||||
|                 // Default buttons.
 | ||||
|                 options.buttons = [ | ||||
|                     { | ||||
|                         text: Translate.instant('core.cancel'), | ||||
|                         role: 'cancel', | ||||
| @ -1514,18 +1545,10 @@ export class CoreDomUtilsProvider { | ||||
|                     }, | ||||
|                     { | ||||
|                         text: Translate.instant('core.ok'), | ||||
|                         handler: (data) => { | ||||
|                             if (isCheckbox) { | ||||
|                                 resolve(data[0]); | ||||
|                             } else if (isRadio) { | ||||
|                                 resolve(data); | ||||
|                             } else { | ||||
|                                 resolve(data.promptinput); | ||||
|                             } | ||||
|                         }, | ||||
|                         handler: resolvePromise, | ||||
|                     }, | ||||
|                 ], | ||||
|             }; | ||||
|                 ]; | ||||
|             } | ||||
| 
 | ||||
|             this.showAlertWithOptions(options); | ||||
|         }); | ||||
| @ -2045,3 +2068,11 @@ export type OpenModalOptions = ModalOptions & { | ||||
|     waitForDismissCompleted?: boolean; | ||||
|     closeOnNavigate?: boolean; // Default true.
 | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Buttons for prompt alert. | ||||
|  */ | ||||
| export type PromptButton = Omit<AlertButton, 'handler'> & { | ||||
|     // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||
|     handler?: (value: any, resolve: (value: any) => void, reject: (reason: any) => void) => void; | ||||
| }; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user