@sapui5/sap.ushell 1.119.3 → 1.120.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/main/js/sap/ushell/.library +3 -3
- package/src/main/js/sap/ushell/Container.js +272 -41
- package/src/main/js/sap/ushell/Fiori20Adapter.js +1 -1
- package/src/main/js/sap/ushell/Fiori20AdapterTest.js +3 -2
- package/src/main/js/sap/ushell/NWBCInterface.js +1 -1
- package/src/main/js/sap/ushell/SessionHandler.js +11 -6
- package/src/main/js/sap/ushell/TechnicalParameters.js +1 -1
- package/src/main/js/sap/ushell/URLTemplateProcessor.js +1 -1
- package/src/main/js/sap/ushell/Ui5NativeServiceFactory.js +1 -1
- package/src/main/js/sap/ushell/Ui5ServiceFactory.js +1 -1
- package/src/main/js/sap/ushell/User.js +26 -35
- package/src/main/js/sap/ushell/_ApplicationType/urlTemplateResolution.js +1 -1
- package/src/main/js/sap/ushell/_URLTemplateProcessor/DefinitionParameterSetBuilder.js +1 -1
- package/src/main/js/sap/ushell/_URLTemplateProcessor/DependencyGraph.js +1 -1
- package/src/main/js/sap/ushell/_URLTemplateProcessor/Functions.js +1 -1
- package/src/main/js/sap/ushell/_URLTemplateProcessor/Resolvers.js +1 -1
- package/src/main/js/sap/ushell/_URLTemplateProcessor/TemplateParameterParser.js +1 -1
- package/src/main/js/sap/ushell/_URLTemplateProcessor/utils.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/ClientSideTargetResolutionAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/CommonDataModelAdapter.js +15 -11
- package/src/main/js/sap/ushell/adapters/cdm/ConfigurationDefaultsAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/ContainerAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/LaunchPageAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/PagesCommonDataModelAdapter.js +16 -11
- package/src/main/js/sap/ushell/adapters/cdm/PersonalizationAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/PersonalizationV2Adapter.js +18 -0
- package/src/main/js/sap/ushell/adapters/cdm/Ui5ComponentLoaderAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/_LaunchPage/modifyHome.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/_LaunchPage/readCatalogs.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/_LaunchPage/readHome.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/_LaunchPage/uri.transform.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/util/AppForInbound.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/util/cdmSiteUtils.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/AdapterBase.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/LaunchPageAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/StaticGroupsAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/_LaunchPage/readApplications.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/_LaunchPage/readCatalogs.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/_LaunchPage/readHome.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/_LaunchPage/readPages.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/_LaunchPage/readUtils.js +1 -1
- package/src/main/js/sap/ushell/adapters/cdm/v3/_LaunchPage/readVisualizations.js +1 -1
- package/src/main/js/sap/ushell/adapters/cep/NavTargetResolutionAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cep/SearchCEPAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/cflp/UserDefaultParameterPersistenceAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/AdapterContainer.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/AppStateAdapter.js +24 -18
- package/src/main/js/sap/ushell/adapters/local/ClientSideTargetResolutionAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/ContainerAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/LaunchPageAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/MenuAdapter.js +4 -7
- package/src/main/js/sap/ushell/adapters/local/NavTargetResolutionAdapter.js +17 -22
- package/src/main/js/sap/ushell/adapters/local/PageBuildingAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/PagePersistenceAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/PersonalizationAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/PersonalizationV2Adapter.js +19 -0
- package/src/main/js/sap/ushell/adapters/local/SearchAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/SearchCEPAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/SupportTicketAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/Ui5ComponentLoaderAdapter.js +1 -1
- package/src/main/js/sap/ushell/adapters/local/UserDefaultParameterPersistenceAdapter.js +11 -7
- package/src/main/js/sap/ushell/adapters/local/UserInfoAdapter.js +8 -8
- package/src/main/js/sap/ushell/api/RTA.js +47 -0
- package/src/main/js/sap/ushell/appRuntime/ui5/AppRuntime.js +12 -5
- package/src/main/js/sap/ushell/appRuntime/ui5/AppRuntimeContext.js +2 -2
- package/src/main/js/sap/ushell/appRuntime/ui5/services/adapters/Ui5ComponentLoaderAdapter.js +1 -1
- package/src/main/js/sap/ushell/bootstrap/SchedulingAgent.js +2 -2
- package/src/main/js/sap/ushell/bootstrap/_SchedulingAgent/logger.js +1 -1
- package/src/main/js/sap/ushell/bootstrap/_SchedulingAgent/state.js +1 -1
- package/src/main/js/sap/ushell/bootstrap/cdm/cdm-def-dev.js +6 -3
- package/src/main/js/sap/ushell/bootstrap/common/common.configure.ui5datetimeformat.js +1 -1
- package/src/main/js/sap/ushell/bootstrap/common/common.configure.ushell.js +3 -0
- package/src/main/js/sap/ushell/bootstrap/common/common.load.launchpad.js +1 -1
- package/src/main/js/sap/ushell/bootstrap/common/common.util.js +34 -2
- package/src/main/js/sap/ushell/bootstrap/sandbox2.js +7 -2
- package/src/main/js/sap/ushell/components/ComponentKeysHandler.js +1 -1
- package/src/main/js/sap/ushell/components/HomepageManager.js +5 -5
- package/src/main/js/sap/ushell/components/SharedComponentUtils.js +7 -10
- package/src/main/js/sap/ushell/components/_HeaderManager/ShellHeader.controller.js +3 -3
- package/src/main/js/sap/ushell/components/_HomepageManager/DashboardLoadingManager.js +5 -0
- package/src/main/js/sap/ushell/components/_HomepageManager/PagingManager.js +5 -0
- package/src/main/js/sap/ushell/components/_HomepageManager/PersistentPageOperationAdapter.js +5 -0
- package/src/main/js/sap/ushell/components/_HomepageManager/TransientPageOperationAdapter.js +5 -0
- package/src/main/js/sap/ushell/components/appfinder/AppFinderView.js +1 -1
- package/src/main/js/sap/ushell/components/appfinder/CatalogView.js +1 -1
- package/src/main/js/sap/ushell/components/appfinder/EasyAccess.controller.js +3 -3
- package/src/main/js/sap/ushell/components/appfinder/EasyAccessView.js +0 -8
- package/src/main/js/sap/ushell/components/appfinder/HierarchyApps.controller.js +4 -4
- package/src/main/js/sap/ushell/components/appfinder/HierarchyFolders.controller.js +18 -16
- package/src/main/js/sap/ushell/components/appfinder/manifest.json +2 -2
- package/src/main/js/sap/ushell/components/applicationIntegration/AppLifeCycle.js +2 -2
- package/src/main/js/sap/ushell/components/applicationIntegration/application/Application.js +1 -1
- package/src/main/js/sap/ushell/components/applicationIntegration/application/BlueBoxHandler.js +1 -1
- package/src/main/js/sap/ushell/components/applicationIntegration/application/PostMessageAPI.js +2 -2
- package/src/main/js/sap/ushell/components/applicationIntegration/configuration/AppMeta.js +1 -1
- package/src/main/js/sap/ushell/components/applicationIntegration/elements/model.js +1 -1
- package/src/main/js/sap/ushell/components/applicationIntegration/relatedServices/RelatedServices.js +1 -1
- package/src/main/js/sap/ushell/components/applicationIntegration/relatedShellElements/RelatedShellElements.js +1 -1
- package/src/main/js/sap/ushell/components/cards/Card.controller.js +2 -2
- package/src/main/js/sap/ushell/components/container/ApplicationContainer.js +92 -71
- package/src/main/js/sap/ushell/components/contentFinder/Component.js +1 -1
- package/src/main/js/sap/ushell/components/contentFinder/controller/AppSearch.controller.js +1 -1
- package/src/main/js/sap/ushell/components/contentFinder/controller/ContentFinderDialog.controller.js +1 -1
- package/src/main/js/sap/ushell/components/contentFinder/controller/WidgetGallery.controller.js +1 -1
- package/src/main/js/sap/ushell/components/contentFinder/manifest.json +1 -1
- package/src/main/js/sap/ushell/components/contentFinder/model/formatter.js +4 -4
- package/src/main/js/sap/ushell/components/factsheet/Component.js +1 -1
- package/src/main/js/sap/ushell/components/homeApp/error/manifest.json +1 -1
- package/src/main/js/sap/ushell/components/homepage/ActionMode.js +1 -1
- package/src/main/js/sap/ushell/components/homepage/DashboardContent.view.js +1 -1
- package/src/main/js/sap/ushell/components/homepage/DashboardGroupsBox.js +1 -1
- package/src/main/js/sap/ushell/components/homepage/DashboardUIActions.js +1 -1
- package/src/main/js/sap/ushell/components/homepage/manifest.json +2 -2
- package/src/main/js/sap/ushell/components/pages/ActionMode.js +5 -5
- package/src/main/js/sap/ushell/components/pages/Component.js +1 -1
- package/src/main/js/sap/ushell/components/pages/MyHomeImport.js +1 -1
- package/src/main/js/sap/ushell/components/pages/StateManager.js +37 -24
- package/src/main/js/sap/ushell/components/pages/controller/ImportDialog.controller.js +1 -1
- package/src/main/js/sap/ushell/components/pages/controller/PageRuntime.controller.js +1 -1
- package/src/main/js/sap/ushell/components/pages/manifest.json +2 -2
- package/src/main/js/sap/ushell/components/runtimeSwitcher/controller/RuntimeSwitcher.controller.js +7 -4
- package/src/main/js/sap/ushell/components/runtimeSwitcher/manifest.json +1 -1
- package/src/main/js/sap/ushell/components/shell/MenuBar/controller/MenuBar.controller.js +6 -7
- package/src/main/js/sap/ushell/components/shell/MenuBar/manifest.json +2 -2
- package/src/main/js/sap/ushell/components/shell/NavigationBarMenu/controller/NavigationBarMenu.controller.js +39 -13
- package/src/main/js/sap/ushell/components/shell/NavigationBarMenu/manifest.json +3 -3
- package/src/main/js/sap/ushell/components/shell/Notifications/Component.js +5 -5
- package/src/main/js/sap/ushell/components/shell/Notifications/Notifications.controller.js +25 -45
- package/src/main/js/sap/ushell/components/shell/PostLoadingHeaderEnhancement/Component.js +2 -2
- package/src/main/js/sap/ushell/components/shell/ProductSwitch/Component.js +1 -1
- package/src/main/js/sap/ushell/components/shell/Search/ESearch.js +1 -1
- package/src/main/js/sap/ushell/components/shell/Search/manifest.json +2 -2
- package/src/main/js/sap/ushell/components/shell/SearchCEP/Component.js +2 -2
- package/src/main/js/sap/ushell/components/shell/SearchCEP/SearchCEP.controller.js +3 -3
- package/src/main/js/sap/ushell/components/shell/SearchCEP/SearchProviders/FrequentActivityProvider.js +1 -1
- package/src/main/js/sap/ushell/components/shell/SearchCEP/SearchProviders/RecentSearchProvider.js +1 -1
- package/src/main/js/sap/ushell/components/shell/SearchCEP/SearchProviders/SearchProvider.js +1 -1
- package/src/main/js/sap/ushell/components/shell/SearchCEP/SearchProviders/SearchServiceProvider.js +1 -1
- package/src/main/js/sap/ushell/components/shell/Settings/Component.js +4 -4
- package/src/main/js/sap/ushell/components/shell/Settings/ProfilingLoader.js +4 -0
- package/src/main/js/sap/ushell/components/shell/Settings/UserSettings.controller.js +4 -0
- package/src/main/js/sap/ushell/components/shell/Settings/UserSettings.view.xml +4 -3
- package/src/main/js/sap/ushell/components/shell/Settings/homepage/HomepageEntry.js +10 -13
- package/src/main/js/sap/ushell/components/shell/Settings/notifications/NotificationsSetting.controller.js +13 -22
- package/src/main/js/sap/ushell/components/shell/Settings/userAccount/UserAccountSelector.controller.js +2 -2
- package/src/main/js/sap/ushell/components/shell/Settings/userActivities/UserActivitiesSetting.controller.js +11 -14
- package/src/main/js/sap/ushell/components/shell/Settings/userDefaults/manifest.json +1 -1
- package/src/main/js/sap/ushell/components/shell/UserActionsMenu/Component.js +1 -1
- package/src/main/js/sap/ushell/components/shell/UserActionsMenu/UserActionsMenu.controller.js +2 -2
- package/src/main/js/sap/ushell/components/shell/UserImage/Component.js +2 -2
- package/src/main/js/sap/ushell/components/tiles/indicatorTileUtils/smartBusinessUtil.js +4 -6
- package/src/main/js/sap/ushell/components/visualizationOrganizer/Component.js +14 -18
- package/src/main/js/sap/ushell/components/workPageBuilder/Component.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/controller/WorkPageBuilder.accessibility.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/controller/WorkPageBuilder.controller.js +16 -12
- package/src/main/js/sap/ushell/components/workPageBuilder/controller/WorkPageHost.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/controls/WorkPage.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/controls/WorkPageButton.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/controls/WorkPageCell.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/controls/WorkPageColumn.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/controls/WorkPageColumnResizer.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/controls/WorkPageRow.js +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/manifest.json +1 -1
- package/src/main/js/sap/ushell/components/workPageBuilder/view/WorkPageBuilder.view.xml +3 -3
- package/src/main/js/sap/ushell/components/workPageRuntime/Component.js +1 -1
- package/src/main/js/sap/ushell/components/workPageRuntime/controller/WorkPageRuntime.controller.js +1 -2
- package/src/main/js/sap/ushell/components/workPageRuntime/manifest.json +1 -1
- package/src/main/js/sap/ushell/components/workPageRuntime/services/NavigationResolver.js +1 -1
- package/src/main/js/sap/ushell/components/workPageRuntime/services/WorkPage.js +1 -1
- package/src/main/js/sap/ushell/designtime/ApplicationContainer.designtime.js +1 -1
- package/src/main/js/sap/ushell/library.js +1 -1
- package/src/main/js/sap/ushell/navigationMode.js +1 -1
- package/src/main/js/sap/ushell/performance/ShellAnalytics.js +1 -1
- package/src/main/js/sap/ushell/performance/StatisticalRecord.js +1 -1
- package/src/main/js/sap/ushell/plugins/appwarmup/Component.js +1 -1
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/AccessKeysHandler.js +1 -1
- package/src/main/js/sap/ushell/renderer/History.js +84 -0
- package/src/main/js/sap/ushell/renderer/LogonFrameProvider.js +96 -0
- package/src/main/js/sap/ushell/renderer/Renderer.js +2851 -0
- package/src/main/js/sap/ushell/renderer/Shell.controller.js +3155 -0
- package/src/main/js/sap/ushell/{renderers/fiori2/ShellAsync.view.js → renderer/Shell.view.js} +29 -18
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/ShellLayout.js +3 -3
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/allMyApps/AllMyApps.controller.js +4 -4
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/allMyApps/AllMyApps.view.xml +1 -1
- package/src/main/js/sap/ushell/renderer/allMyApps/AllMyAppsKeyboardHandler.js +108 -0
- package/src/main/js/sap/ushell/renderer/allMyApps/AllMyAppsManager.js +453 -0
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources.properties +4 -0
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/search/searchComponent/Component.js +3 -3
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/search/searchComponent/controller/CEPSearchApp.controller.js +1 -1
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/search/searchComponent/controller/SearchApp.controller.js +1 -1
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/search/searchComponent/manifest.json +2 -2
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/search/searchComponent/view/CEPSearchApp.view.js +2 -2
- package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/search/searchComponent/view/SearchApp.view.js +2 -2
- package/src/main/js/sap/ushell/renderers/fiori2/History.js +7 -68
- package/src/main/js/sap/ushell/renderers/fiori2/LogonFrameProvider.js +9 -79
- package/src/main/js/sap/ushell/renderers/fiori2/Renderer.js +101 -1882
- package/src/main/js/sap/ushell/renderers/fiori2/RendererExtensions.js +2 -3
- package/src/main/js/sap/ushell/renderers/fiori2/Shell.controller.js +8 -3130
- package/src/main/js/sap/ushell/renderers/fiori2/Shell.view.js +7 -7
- package/src/main/js/sap/ushell/renderers/fiori2/allMyApps/AllMyAppsKeyboardHandler.js +7 -92
- package/src/main/js/sap/ushell/renderers/fiori2/allMyApps/AllMyAppsManager.js +8 -438
- package/src/main/js/sap/ushell/resources.js +1 -1
- package/src/main/js/sap/ushell/services/AllMyApps.js +16 -7
- package/src/main/js/sap/ushell/services/AppConfiguration.js +12 -0
- package/src/main/js/sap/ushell/services/AppLifeCycle.js +11 -14
- package/src/main/js/sap/ushell/services/AppState.js +12 -8
- package/src/main/js/sap/ushell/services/Bookmark.js +15 -13
- package/src/main/js/sap/ushell/services/BookmarkV2.js +919 -0
- package/src/main/js/sap/ushell/services/ClientSideTargetResolution.js +229 -241
- package/src/main/js/sap/ushell/services/CommonDataModel.js +14 -4
- package/src/main/js/sap/ushell/services/Configuration.js +12 -11
- package/src/main/js/sap/ushell/services/ConfigurationDefaults.js +13 -10
- package/src/main/js/sap/ushell/services/Container.js +1 -1
- package/src/main/js/sap/ushell/services/ContentExtensionAdapterFactory.js +1 -1
- package/src/main/js/sap/ushell/services/CrossApplicationNavigation.js +8 -6
- package/src/main/js/sap/ushell/services/DarkModeSupport.js +16 -10
- package/src/main/js/sap/ushell/services/EndUserFeedback.js +1 -1
- package/src/main/js/sap/ushell/services/Extension/FloatingContainer.js +103 -0
- package/src/main/js/sap/ushell/services/Extension/Footer.js +61 -0
- package/src/main/js/sap/ushell/services/Extension/Header.js +193 -0
- package/src/main/js/sap/ushell/services/Extension/Item.js +195 -0
- package/src/main/js/sap/ushell/services/Extension/SidePane.js +155 -0
- package/src/main/js/sap/ushell/services/Extension/ToolArea.js +152 -0
- package/src/main/js/sap/ushell/services/Extension.js +381 -0
- package/src/main/js/sap/ushell/services/LaunchPage.js +1 -1
- package/src/main/js/sap/ushell/services/Menu.js +48 -59
- package/src/main/js/sap/ushell/services/Message.js +15 -14
- package/src/main/js/sap/ushell/services/MessageBroker.js +12 -12
- package/src/main/js/sap/ushell/services/NavTargetResolution.js +48 -70
- package/src/main/js/sap/ushell/services/Navigation/utils.js +565 -0
- package/src/main/js/sap/ushell/services/Navigation.js +152 -139
- package/src/main/js/sap/ushell/services/NavigationDataProvider.js +11 -8
- package/src/main/js/sap/ushell/services/Notifications.js +118 -1523
- package/src/main/js/sap/ushell/services/NotificationsV2.js +1872 -0
- package/src/main/js/sap/ushell/services/PageBuilding.js +11 -8
- package/src/main/js/sap/ushell/services/PagePersistence.js +11 -8
- package/src/main/js/sap/ushell/services/PageReferencing.js +11 -8
- package/src/main/js/sap/ushell/services/Pages.js +11 -15
- package/src/main/js/sap/ushell/services/Personalization.js +5 -3
- package/src/main/js/sap/ushell/services/PersonalizationV2/ContextContainer.js +410 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/Personalizer.js +109 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/TransientPersonalizer.js +57 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/Variant.js +180 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/VariantSet.js +296 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/VariantSetAdapter.js +125 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/WindowAdapter.js +71 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/WindowAdapterContainer.js +172 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/constants.js +23 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/constants.private.js +18 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2/utils.js +233 -0
- package/src/main/js/sap/ushell/services/PersonalizationV2.js +641 -0
- package/src/main/js/sap/ushell/services/PluginManager.js +47 -55
- package/src/main/js/sap/ushell/services/ReferenceResolver.js +61 -54
- package/src/main/js/sap/ushell/services/Search.js +15 -2
- package/src/main/js/sap/ushell/services/SearchCEP.js +40 -44
- package/src/main/js/sap/ushell/services/SearchableContent.js +9 -9
- package/src/main/js/sap/ushell/services/ShellNavigation.js +14 -13
- package/src/main/js/sap/ushell/services/SmartNavigation.js +1 -1
- package/src/main/js/sap/ushell/services/SpaceContent.js +9 -10
- package/src/main/js/sap/ushell/services/SupportTicket.js +14 -14
- package/src/main/js/sap/ushell/services/UITracer.js +31 -35
- package/src/main/js/sap/ushell/services/URLParsing.js +9 -11
- package/src/main/js/sap/ushell/services/URLShortening.js +1 -1
- package/src/main/js/sap/ushell/services/URLTemplate.js +14 -13
- package/src/main/js/sap/ushell/services/Ui5ComponentLoader.js +29 -26
- package/src/main/js/sap/ushell/services/UsageAnalytics.js +6 -0
- package/src/main/js/sap/ushell/services/UserDefaultParameterPersistence.js +11 -7
- package/src/main/js/sap/ushell/services/UserDefaultParameters.js +20 -26
- package/src/main/js/sap/ushell/services/UserInfo.js +44 -23
- package/src/main/js/sap/ushell/services/UserRecents.js +13 -5
- package/src/main/js/sap/ushell/services/VisualizationDataProvider.js +12 -9
- package/src/main/js/sap/ushell/services/VisualizationInstantiation.js +10 -8
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/Formatter.js +1 -1
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/InboundIndex.js +1 -1
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/InboundProvider.js +1 -1
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/PrelaunchOperations.js +1 -1
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/Search.js +1 -1
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/StagedLogger.js +1 -1
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/SystemContext.js +1 -1
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/Utils.js +3 -4
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/VirtualInbounds.js +4 -4
- package/src/main/js/sap/ushell/services/_ClientSideTargetResolution/XAppStateProcessing.js +1 -1
- package/src/main/js/sap/ushell/services/_CommonDataModel/SiteConverter.js +1 -1
- package/src/main/js/sap/ushell/services/_ContentExtensionAdapterFactory/ContentExtensionAdapterConfig.js +1 -1
- package/src/main/js/sap/ushell/services/_ContentExtensionAdapterFactory/FeaturedGroupConfig.js +1 -1
- package/src/main/js/sap/ushell/services/_CrossApplicationNavigation/utils.js +2 -1
- package/src/main/js/sap/ushell/services/_MessageBroker/MessageBrokerEngine.js +1 -1
- package/src/main/js/sap/ushell/services/_PageReferencing/PageReferencer.js +1 -1
- package/src/main/js/sap/ushell/services/_Personalization/ContextContainer.js +6 -0
- package/src/main/js/sap/ushell/services/_Personalization/PersonalizationContainer.js +5 -1
- package/src/main/js/sap/ushell/services/_Personalization/PersonalizationContainerVariant.js +13 -9
- package/src/main/js/sap/ushell/services/_Personalization/PersonalizationContainerVariantSet.js +17 -13
- package/src/main/js/sap/ushell/services/_Personalization/Personalizer.js +5 -0
- package/src/main/js/sap/ushell/services/_Personalization/TransientPersonalizer.js +5 -1
- package/src/main/js/sap/ushell/services/_Personalization/Variant.js +4 -0
- package/src/main/js/sap/ushell/services/_Personalization/VariantSet.js +17 -9
- package/src/main/js/sap/ushell/services/_Personalization/VariantSetAdapter.js +4 -6
- package/src/main/js/sap/ushell/services/_Personalization/WindowAdapter.js +5 -44
- package/src/main/js/sap/ushell/services/_Personalization/WindowAdapterContainer.js +5 -101
- package/src/main/js/sap/ushell/services/_Personalization/constants.js +3 -0
- package/src/main/js/sap/ushell/services/_Personalization/constants.private.js +3 -0
- package/src/main/js/sap/ushell/services/_Personalization/utils.js +3 -0
- package/src/main/js/sap/ushell/services/_PluginManager/Extensions.js +1 -1
- package/src/main/js/sap/ushell/services/_PluginManager/HeaderExtensions.js +1 -1
- package/src/main/js/sap/ushell/services/_PluginManager/MenuExtensions.js +1 -1
- package/src/main/js/sap/ushell/services/_Ui5ComponentLoader/utils.js +29 -5
- package/src/main/js/sap/ushell/services/_UserRecents/UserRecentsBase.js +19 -27
- package/src/main/js/sap/ushell/services/_VisualizationInstantiation/VizInstance.js +4 -0
- package/src/main/js/sap/ushell/services/_VisualizationInstantiation/VizInstanceAbap.js +3 -0
- package/src/main/js/sap/ushell/services/_VisualizationInstantiation/VizInstanceLink.js +1 -1
- package/src/main/js/sap/ushell/services/personalization/VariantSetAdapter.js +13 -15
- package/src/main/js/sap/ushell/support/plugins/flpConfig/FlpConfigurationPlugin.js +1 -1
- package/src/main/js/sap/ushell/themes/sap_horizon/ShellAppTitle.less +4 -4
- package/src/main/js/sap/ushell/themes/sap_horizon_dark/ShellAppTitle.less +4 -4
- package/src/main/js/sap/ushell/themes/sap_horizon_hcb/ShellAppTitle.less +2 -2
- package/src/main/js/sap/ushell/themes/sap_horizon_hcw/ShellAppTitle.less +2 -2
- package/src/main/js/sap/ushell/ui/AppContainer.js +2 -2
- package/src/main/js/sap/ushell/ui/ContentNodeSelector.js +2 -2
- package/src/main/js/sap/ushell/ui/ShellHeader.js +2 -2
- package/src/main/js/sap/ushell/ui/cards/RecentActivitiesExtension.js +1 -1
- package/src/main/js/sap/ushell/ui/footerbar/AddBookmarkButton.js +8 -12
- package/src/main/js/sap/ushell/ui/launchpad/ExtendedChangeDetection.js +1 -1
- package/src/main/js/sap/ushell/ui/launchpad/Page.js +1 -1
- package/src/main/js/sap/ushell/ui/launchpad/Section.js +21 -8
- package/src/main/js/sap/ushell/ui/launchpad/TileState.js +0 -1
- package/src/main/js/sap/ushell/ui/launchpad/section/CompactArea.js +1 -1
- package/src/main/js/sap/ushell/ui/shell/ShellAppTitle.js +1 -1
- package/src/main/js/sap/ushell/ui/shell/ShellHeadItem.js +1 -1
- package/src/main/js/sap/ushell/ui/shell/SysInfoBar.js +1 -1
- package/src/main/js/sap/ushell/ui/shell/ToolAreaItem.js +1 -1
- package/src/main/js/sap/ushell/ui/utils.js +1 -1
- package/src/main/js/sap/ushell/ui5service/ShellUIService.js +1 -1
- package/src/main/js/sap/ushell/ui5service/UserStatus.js +1 -1
- package/src/main/js/sap/ushell/ui5service/_ShellUIService/shelluiservice.class.factory.js +14 -26
- package/src/main/js/sap/ushell/utils/Deferred.js +88 -0
- package/src/main/js/sap/ushell/utils/UrlShortening.js +1 -1
- package/src/main/js/sap/ushell/utils/WindowUtils.js +8 -8
- package/src/main/js/sap/ushell/utils.js +31 -67
- package/src/test/js/sap/ushell/bootstrap/sandbox.js +7 -2
- package/ui5.yaml +8 -2
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/HeadEndItemsOverflowPopover.fragment.xml +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_ar.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_bg.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_ca.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_cs.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_cy.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_da.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_de.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_el.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_en.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_en_GB.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_en_US_sappsd.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_en_US_saprigi.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_en_US_saptrc.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_es.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_es_MX.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_et.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_fi.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_fr.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_fr_CA.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_hi.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_hr.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_hu.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_id.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_it.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_iw.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_ja.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_kk.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_ko.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_lt.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_lv.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_ms.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_nl.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_no.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_pl.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_pt.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_pt_PT.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_ro.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_ru.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_sh.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_sk.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_sl.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_sv.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_th.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_tr.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_uk.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_vi.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_zh_CN.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/resources/resources_zh_TW.properties +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/search/util.js +0 -0
- /package/src/main/js/sap/ushell/{renderers/fiori2 → renderer}/utils.js +0 -0
|
@@ -0,0 +1,1872 @@
|
|
|
1
|
+
// Copyright (c) 2009-2023 SAP SE, All Rights Reserved
|
|
2
|
+
|
|
3
|
+
sap.ui.define([
|
|
4
|
+
"sap/base/Log",
|
|
5
|
+
"sap/ushell/utils/Deferred",
|
|
6
|
+
"sap/ui/core/Core",
|
|
7
|
+
"sap/ui/core/Configuration",
|
|
8
|
+
"sap/ui/core/ws/SapPcpWebSocket",
|
|
9
|
+
"sap/ui/model/json/JSONModel",
|
|
10
|
+
"sap/ui/thirdparty/datajs",
|
|
11
|
+
"sap/ushell/utils"
|
|
12
|
+
], function (
|
|
13
|
+
Log,
|
|
14
|
+
Deferred,
|
|
15
|
+
Core,
|
|
16
|
+
Configuration,
|
|
17
|
+
SapPcpWebSocket,
|
|
18
|
+
JSONModel,
|
|
19
|
+
OData,
|
|
20
|
+
ushellUtils
|
|
21
|
+
) {
|
|
22
|
+
"use strict";
|
|
23
|
+
|
|
24
|
+
/*eslint consistent-this: ["error", "oNotificationsService"]*/
|
|
25
|
+
|
|
26
|
+
const S_DEFAULT_WEBSOCKET_URL = "/sap/bc/apc/iwngw/notification_push_apc";
|
|
27
|
+
const I_DEFAULT_POLLING_INTERVAL = 60; // Seconds
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @alias sap.ushell.services.NotificationsV2
|
|
31
|
+
* @class
|
|
32
|
+
* @classdesc UShell service for fetching user notification data from the Notification center/service<br>
|
|
33
|
+
* and exposing them to the Unified Shell and Fiori applications UI controls.
|
|
34
|
+
*
|
|
35
|
+
* <b>Note:</b> To retrieve a valid instance of this service, it is necessary to call
|
|
36
|
+
* <code>sap.ushell.Container.getServiceAsync("NotificationsV2")</code>. For details, see
|
|
37
|
+
* {@link sap.ushell.services.Container#getServiceAsync}.
|
|
38
|
+
*
|
|
39
|
+
* In order to get user notifications, Unified Shell notification service issues OData requests<br>
|
|
40
|
+
* to the service defined by the configuration property <code>serviceUrl</code>,<br>
|
|
41
|
+
* for example: "/sap/opu/odata4/iwngw/notification/default/iwngw/notification_srv/0001"<br>.
|
|
42
|
+
*
|
|
43
|
+
* Unified Shell Notification service has several working modes, depending on the environment and the available resources:<br>
|
|
44
|
+
* PackagedApp mode: Fiori launchpad runs in the context of PackagedApp<br>
|
|
45
|
+
* FioriClient mode: Fiori launchpad runs in the context of FioriLaunchpad<br>
|
|
46
|
+
* WebSocket mode: Fiori launchpad runs in a browser, and WebSocket connection to the notifications provider is available<br>
|
|
47
|
+
* Polling mode: Fiori launchpad in runs in a browser, and WebSocket connection to the notifications provider is not available<br>
|
|
48
|
+
*
|
|
49
|
+
* The notification service exposes an API that includes:
|
|
50
|
+
* - Service enabling and initialization<br>
|
|
51
|
+
* - Registration of callback functions (by Shell/FLP controls) that will be called for every data update<br>.
|
|
52
|
+
* - Retrieval of notification data (e.g. notifications, number of unseen notifications)
|
|
53
|
+
* - Execution of a notification actions
|
|
54
|
+
* - Marking user notifications as seen
|
|
55
|
+
*
|
|
56
|
+
* @param {object} oContainerInterface The interface provided by the container
|
|
57
|
+
* @param {object} sParameters Not used in this service
|
|
58
|
+
* @param {object} oServiceConfiguration configuration
|
|
59
|
+
*
|
|
60
|
+
* @hideconstructor
|
|
61
|
+
*
|
|
62
|
+
* @since 1.119
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
function Notifications (oContainerInterface, sParameters, oServiceConfiguration) {
|
|
66
|
+
const oModel = new JSONModel();
|
|
67
|
+
const oServiceConfig = oServiceConfiguration && oServiceConfiguration.config;
|
|
68
|
+
const aRequestURIs = {
|
|
69
|
+
getNotifications: {},
|
|
70
|
+
getNotificationsByType: {},
|
|
71
|
+
getNotificationsInGroup: {},
|
|
72
|
+
getBadgeNumber: {},
|
|
73
|
+
resetBadgeNumber: {},
|
|
74
|
+
getNotificationTypesSettings: {},
|
|
75
|
+
getNotificationsGroupHeaders: {},
|
|
76
|
+
getMobileSupportSettings: {},
|
|
77
|
+
getEmailSupportSettings: {},
|
|
78
|
+
getWebSocketValidity: {},
|
|
79
|
+
getNotificationCount: {}
|
|
80
|
+
};
|
|
81
|
+
const aUpdateNotificationsCallbacks = [];
|
|
82
|
+
const aUpdateNotificationsCountCallbacks = [];
|
|
83
|
+
const tWebSocketRecoveryPeriod = 5000;
|
|
84
|
+
const tFioriClientInitializationPeriod = 6000;
|
|
85
|
+
const oOperationEnum = {
|
|
86
|
+
NOTIFICATIONS: 0,
|
|
87
|
+
NOTIFICATIONS_BY_TYPE: 1,
|
|
88
|
+
GET_BADGE_NUMBER: 2,
|
|
89
|
+
RESET_BADGE_NUMBER: 3,
|
|
90
|
+
GET_SETTINGS: 4,
|
|
91
|
+
GET_MOBILE_SUPPORT_SETTINGS: 5,
|
|
92
|
+
NOTIFICATIONS_GROUP_HEADERS: 6,
|
|
93
|
+
NOTIFICATIONS_IN_GROUP: 7,
|
|
94
|
+
GET_NOTIFICATIONS_COUNT: 8,
|
|
95
|
+
VALIDATE_WEBSOCKET_CHANNEL: 9,
|
|
96
|
+
GET_EMAIL_SUPPORT_SETTINGS: 10,
|
|
97
|
+
NOTIFICATIONS_BY_DATE_DESCENDING: "notificationsByDateDescending",
|
|
98
|
+
NOTIFICATIONS_BY_DATE_ASCENDING: "notificationsByDateAscending",
|
|
99
|
+
NOTIFICATIONS_BY_PRIORITY_DESCENDING: "notificationsByPriorityDescending",
|
|
100
|
+
NOTIFICATIONS_BY_TYPE_DESCENDING: "notificationsByTypeDescending"
|
|
101
|
+
};
|
|
102
|
+
const oModesEnum = {
|
|
103
|
+
PACKAGED_APP: 0,
|
|
104
|
+
FIORI_CLIENT: 1,
|
|
105
|
+
WEB_SOCKET: 2,
|
|
106
|
+
POLLING: 3
|
|
107
|
+
};
|
|
108
|
+
const oUserFlagsReadFromPersonalizationDeferred = new Deferred();
|
|
109
|
+
const oNotificationSettingsAvailabilityDeferred = new Deferred();
|
|
110
|
+
const oUserFlagsReadFromPersonalizationPromise = oUserFlagsReadFromPersonalizationDeferred.promise();
|
|
111
|
+
const oDummyItems = {};
|
|
112
|
+
const iInitialBufferSize = 10;
|
|
113
|
+
|
|
114
|
+
let tInitializationTimestamp = new Date();
|
|
115
|
+
let oWebSocket;
|
|
116
|
+
let initialReadTimer;
|
|
117
|
+
let webSocketRecoveryTimer;
|
|
118
|
+
let pollingTimer;
|
|
119
|
+
let bIntentBasedConsumption = false;
|
|
120
|
+
let aConsumedIntents = [];
|
|
121
|
+
let bInitialized = false;
|
|
122
|
+
let bOnServiceStop = false;
|
|
123
|
+
let bEnabled = true;
|
|
124
|
+
let sHeaderXcsrfToken;
|
|
125
|
+
let sDataServiceVersion;
|
|
126
|
+
let bWebSocketRecoveryAttempted = false;
|
|
127
|
+
let oCurrentMode;
|
|
128
|
+
let bFirstDataLoaded = false;
|
|
129
|
+
let bHighPriorityBannerEnabled = true;
|
|
130
|
+
let bNotificationSettingsMobileSupport;
|
|
131
|
+
let bNotificationSettingsEmailSupport;
|
|
132
|
+
let bUseDummyItems = false;
|
|
133
|
+
let bInvalidCsrfTokenRecoveryMode = false;
|
|
134
|
+
let bCsrfDataSet = false;
|
|
135
|
+
let aDismissNotifications = [];
|
|
136
|
+
|
|
137
|
+
// *************************************************************************************************
|
|
138
|
+
// ************************************* Service API - Begin ***************************************
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Indicates whether notification service is enabled.<br>
|
|
142
|
+
* Enabling is based on the <code>enable</code> service configuration flag.<br>
|
|
143
|
+
* The service configuration must also include serviceUrl attribute.<br>
|
|
144
|
+
*
|
|
145
|
+
* @returns {boolean} A boolean value indicating whether the notifications service is enabled
|
|
146
|
+
* @public
|
|
147
|
+
* @alias sap.ushell.services.NotificationsV2#isEnabled
|
|
148
|
+
*/
|
|
149
|
+
this.isEnabled = function () {
|
|
150
|
+
if (!oServiceConfig.enabled || !oServiceConfig.serviceUrl) {
|
|
151
|
+
bEnabled = false;
|
|
152
|
+
if (oServiceConfig.enabled && !oServiceConfig.serviceUrl) {
|
|
153
|
+
Log.warning("No serviceUrl was found in the service configuration");
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
bEnabled = true;
|
|
157
|
+
}
|
|
158
|
+
return bEnabled;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Initializes the notification service
|
|
163
|
+
*
|
|
164
|
+
* Initialization is performed only if the following two conditions are fulfilled:<br>
|
|
165
|
+
* 1. Notification service is enabled<br>
|
|
166
|
+
* 2. Notification service hasn't been initialized yet<br>
|
|
167
|
+
*
|
|
168
|
+
* The main initialization functionality is determining and setting the mode in which notifications are consumed.<br>
|
|
169
|
+
* The possible modes are:<br>
|
|
170
|
+
* PACKAGED_APP - Notifications are fetched when a callback is called by PackagedApp environment<br>
|
|
171
|
+
* FIORI_CLIENT - Notifications are fetched when a callback is called by FioriClient environment<br>
|
|
172
|
+
* WEB_SOCKET - Notifications are fetched on WebSocket "ping"<br>
|
|
173
|
+
* POLLING - Notifications are fetched using periodic polling mechanism<br>
|
|
174
|
+
*
|
|
175
|
+
* @public
|
|
176
|
+
* @alias sap.ushell.services.NotificationsV2#init
|
|
177
|
+
*/
|
|
178
|
+
this.init = function () {
|
|
179
|
+
if (!bInitialized && this.isEnabled()) {
|
|
180
|
+
Core.getEventBus().subscribe("launchpad", "sessionTimeout", this.destroy, this);
|
|
181
|
+
this.lastNotificationDate = new Date();
|
|
182
|
+
this._setWorkingMode();
|
|
183
|
+
bInitialized = true;
|
|
184
|
+
this.bUpdateDependencyInitiatorExists = false;
|
|
185
|
+
this._userSettingInitialization();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Listen for requests to enable or disable the connection to the server
|
|
189
|
+
Core.getEventBus().subscribe("launchpad", "setConnectionToServer", this._onSetConnectionToServer, this);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* This event handler enables or disables the connection to the server
|
|
194
|
+
*
|
|
195
|
+
* @param {string} channelID Channel ID of the event
|
|
196
|
+
* @param {string} eventID Event ID of the event
|
|
197
|
+
* @param {{active: boolean}} data Indicates if the connection is to be enabled or disabled
|
|
198
|
+
*
|
|
199
|
+
* @private
|
|
200
|
+
* @alias sap.ushell.services.NotificationsV2#_onSetConnectionToServer
|
|
201
|
+
*/
|
|
202
|
+
this._onSetConnectionToServer = function (channelID, eventID, data) {
|
|
203
|
+
if (data.active) {
|
|
204
|
+
this._resumeConnection();
|
|
205
|
+
} else {
|
|
206
|
+
this._closeConnection();
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Returns the number of unseen notifications<br>
|
|
212
|
+
* e.g. Notifications that the user hasn't seen yet.
|
|
213
|
+
*
|
|
214
|
+
* @returns {Promise} Promise resolves with the number of unread notifications of the user
|
|
215
|
+
* @public
|
|
216
|
+
* @alias sap.ushell.services.NotificationsV2#getUnseenNotificationsCount
|
|
217
|
+
*/
|
|
218
|
+
this.getUnseenNotificationsCount = function () {
|
|
219
|
+
return Promise.resolve(oModel.getProperty("/UnseenCount"));
|
|
220
|
+
};
|
|
221
|
+
/**
|
|
222
|
+
* Returns the number of notifications<br>
|
|
223
|
+
* e.g. Notifications for user.
|
|
224
|
+
*
|
|
225
|
+
* @returns {int} Returns the number of notifications of the user
|
|
226
|
+
* @public
|
|
227
|
+
* @alias sap.ushell.services.NotificationsV2#getNotificationsCount
|
|
228
|
+
*/
|
|
229
|
+
this.getNotificationsCount = function () {
|
|
230
|
+
return oModel.getProperty("/NotificationsCount") || "0";
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
this._createRequest = function (sUri) {
|
|
234
|
+
const oHeader = {
|
|
235
|
+
"Accept-Language": Configuration.getLanguageTag(),
|
|
236
|
+
"X-CSRF-Token": this._getHeaderXcsrfToken() || "fetch" // fetch if not token was obtained previously
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
requestUri: sUri,
|
|
240
|
+
headers: oHeader
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Returns the notifications of the user sorted by type include the group headers and the notifications
|
|
246
|
+
*
|
|
247
|
+
* @returns {Promise} Promise for all notification items
|
|
248
|
+
* @public
|
|
249
|
+
* @alias sap.ushell.services.NotificationsV2#getNotificationsByTypeWithGroupHeaders
|
|
250
|
+
*/
|
|
251
|
+
this.getNotificationsByTypeWithGroupHeaders = function () {
|
|
252
|
+
const oRequest = this._createRequest(this._getRequestURI(oOperationEnum.NOTIFICATIONS_BY_TYPE));
|
|
253
|
+
|
|
254
|
+
return new Promise((resolve, reject) => {
|
|
255
|
+
OData.request(oRequest, resolve, (oMessage) => {
|
|
256
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
257
|
+
resolve(oMessage.response.body);
|
|
258
|
+
} else {
|
|
259
|
+
Log.error("Notification service - oData executeAction failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
260
|
+
reject(oMessage);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Returns the group headers of the user notifications
|
|
268
|
+
*
|
|
269
|
+
* @returns {Promise} Promise for all group headers
|
|
270
|
+
* @public
|
|
271
|
+
* @alias sap.ushell.services.NotificationsV2#getNotificationsGroupHeaders
|
|
272
|
+
*/
|
|
273
|
+
this.getNotificationsGroupHeaders = function () {
|
|
274
|
+
const oRequest = this._createRequest(this._getRequestURI(oOperationEnum.NOTIFICATIONS_GROUP_HEADERS));
|
|
275
|
+
|
|
276
|
+
return new Promise((resolve, reject) => {
|
|
277
|
+
OData.request(oRequest, resolve, (oMessage) => {
|
|
278
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
279
|
+
resolve(oMessage.response.body);
|
|
280
|
+
} else {
|
|
281
|
+
Log.error("Notification service - oData executeAction failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
282
|
+
reject();
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// Private. The function is used in Notifications.controller.
|
|
289
|
+
this.getNotificationsBufferInGroup = function (sGroup, iSkip, iTop) {
|
|
290
|
+
if (bUseDummyItems === true) {
|
|
291
|
+
const aResponse = oDummyItems[oOperationEnum.NOTIFICATIONS_IN_GROUP].slice(iSkip, iSkip + iTop);
|
|
292
|
+
const oResponse = JSON.stringify({
|
|
293
|
+
"@odata.context": "$metadata#Notifications",
|
|
294
|
+
value: aResponse
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
return new Promise((resolve) => {
|
|
298
|
+
window.setTimeout(() => resolve(oResponse), 1000);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const oNotificationsService = this;
|
|
303
|
+
const oArgs = {
|
|
304
|
+
group: sGroup,
|
|
305
|
+
skip: iSkip,
|
|
306
|
+
top: iTop
|
|
307
|
+
};
|
|
308
|
+
const oRequest = this._createRequest(this._getRequestURI(oOperationEnum.NOTIFICATIONS_IN_GROUP, oArgs));
|
|
309
|
+
|
|
310
|
+
return new Promise((resolve, reject) => {
|
|
311
|
+
OData.request(oRequest,
|
|
312
|
+
(oResult) => {
|
|
313
|
+
oNotificationsService._updateCSRF(oResult.response);
|
|
314
|
+
resolve(oResult.value);
|
|
315
|
+
},
|
|
316
|
+
(oMessage) => {
|
|
317
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
318
|
+
oNotificationsService._updateCSRF(oMessage.response);
|
|
319
|
+
resolve(JSON.parse(oMessage.response.body).value);
|
|
320
|
+
} else {
|
|
321
|
+
Log.error("Notification service - oData executeAction failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
322
|
+
reject();
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
// Private. The function is used in Notifications.controller.
|
|
329
|
+
this.getNotificationsBufferBySortingType = function (sSortingType, iSkip, iTop) {
|
|
330
|
+
if (bUseDummyItems === true) {
|
|
331
|
+
const oResponse = JSON.stringify({
|
|
332
|
+
"@odata.context": "$metadata#Notifications",
|
|
333
|
+
value: oDummyItems[sSortingType].slice(iSkip, iSkip + iTop)
|
|
334
|
+
});
|
|
335
|
+
return new Promise((resolve) => window.setTimeout(() => resolve(oResponse), 1000));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const oNotificationsService = this;
|
|
339
|
+
const oArgs = {
|
|
340
|
+
skip: iSkip,
|
|
341
|
+
top: iTop
|
|
342
|
+
};
|
|
343
|
+
const oRequestObject = this._createRequest(this._getRequestURI(sSortingType, oArgs));
|
|
344
|
+
|
|
345
|
+
return new Promise((resolve, reject) => {
|
|
346
|
+
OData.request(oRequestObject,
|
|
347
|
+
(oResult) => {
|
|
348
|
+
oNotificationsService._updateCSRF(oResult.response);
|
|
349
|
+
resolve(oResult.value);
|
|
350
|
+
},
|
|
351
|
+
(oMessage) => {
|
|
352
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
353
|
+
oNotificationsService._updateCSRF(oMessage.response);
|
|
354
|
+
resolve(JSON.parse(oMessage.response.body).value);
|
|
355
|
+
} else {
|
|
356
|
+
Log.error("Notification service - oData executeAction failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
357
|
+
reject();
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Returns the 10 most recent notifications of the user
|
|
365
|
+
*
|
|
366
|
+
* @returns {Promise} Promise object that on success - returns the 10 most recent user notification items
|
|
367
|
+
* @private
|
|
368
|
+
* @alias sap.ushell.services.NotificationsV2#getNotifications
|
|
369
|
+
*/
|
|
370
|
+
this.getNotifications = function () {
|
|
371
|
+
if ((oCurrentMode === oModesEnum.FIORI_CLIENT) || (oCurrentMode === oModesEnum.PACKAGED_APP)) {
|
|
372
|
+
// In Fiori Client mode, notification service fetches notification on initialization,
|
|
373
|
+
// and after that - notification data is updated only by pushed notifications.
|
|
374
|
+
// hence, there's no way that Notification service is updated regarding other changes
|
|
375
|
+
// for example: if the user approved/rejected a notification via other device.
|
|
376
|
+
// In order to solve this - we bring updated data when getNotifications is called from Fiori Client
|
|
377
|
+
return this._readNotificationsData(false).then(() => oModel.getProperty("/Notifications"));
|
|
378
|
+
}
|
|
379
|
+
// In case of offline testing (when OData calls fail):
|
|
380
|
+
// Comment the following line and uncomment the next one
|
|
381
|
+
return Promise.resolve(oModel.getProperty("/Notifications"));
|
|
382
|
+
// return Promise.resolve(this._getDummyJSON());
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Launches a notification action oData call.<br>
|
|
387
|
+
* After launching the action, the function gets updated notification data in order to push the updated data to the consumers.
|
|
388
|
+
*
|
|
389
|
+
* @param {string} sNotificationGroupId The ID of the notification header/group whose action is being executed
|
|
390
|
+
* @param {string} sActionId The ID of the action that is being executed
|
|
391
|
+
* @returns {Promise} Promise object that on success resolves to undefined or it is rejected with failed notifications
|
|
392
|
+
* @public
|
|
393
|
+
* @alias sap.ushell.services.NotificationsV2#executeBulkAction
|
|
394
|
+
*/
|
|
395
|
+
this.executeBulkAction = function (sNotificationGroupId, sActionId) {
|
|
396
|
+
return new Promise((resolve, reject) => {
|
|
397
|
+
this.sendBulkAction(sNotificationGroupId, sActionId).then((res) => {
|
|
398
|
+
const aSucceededNotifications = [];
|
|
399
|
+
const aFailedNotifications = [];
|
|
400
|
+
res.forEach((oNotification) => {
|
|
401
|
+
const sNotificationId = oNotification.NotificationId;
|
|
402
|
+
if (oNotification.Success) {
|
|
403
|
+
aSucceededNotifications.push(sNotificationId);
|
|
404
|
+
} else {
|
|
405
|
+
aFailedNotifications.push(sNotificationId);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
const oResult = {
|
|
409
|
+
succededNotifications: aSucceededNotifications,
|
|
410
|
+
failedNotifications: aFailedNotifications
|
|
411
|
+
};
|
|
412
|
+
if (aFailedNotifications.length) {
|
|
413
|
+
reject(oResult);
|
|
414
|
+
} else {
|
|
415
|
+
resolve(oResult);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
this.dismissBulkNotifications = function (sNotificationGroupId) {
|
|
422
|
+
return this.sendBulkDismiss(sNotificationGroupId);
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
this.executeAction = function (sNotificationId, sActionId) {
|
|
426
|
+
const oNotificationsService = this;
|
|
427
|
+
const sActionUrl = oServiceConfig.serviceUrl + "/ExecuteAction";
|
|
428
|
+
const oRequestBody = { NotificationId: sNotificationId, ActionId: sActionId };
|
|
429
|
+
const oRequestObject = {
|
|
430
|
+
requestUri: sActionUrl,
|
|
431
|
+
method: "POST",
|
|
432
|
+
data: oRequestBody,
|
|
433
|
+
headers: {
|
|
434
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
435
|
+
"Content-Type": "application/json",
|
|
436
|
+
DataServiceVersion: sDataServiceVersion,
|
|
437
|
+
"X-CSRF-Token": sHeaderXcsrfToken
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
return new Promise((resolve, reject) => {
|
|
441
|
+
OData.request(
|
|
442
|
+
oRequestObject,
|
|
443
|
+
(oResult) => {
|
|
444
|
+
const responseAck = { isSucessfull: true, message: "" };
|
|
445
|
+
if (oResult && oResult.response && oResult.response.statusCode === 200 && oResult.response.body) {
|
|
446
|
+
const responseAckJson = JSON.parse(oResult.response.body);
|
|
447
|
+
responseAck.isSucessfull = responseAckJson.Success;
|
|
448
|
+
responseAck.message = responseAckJson.MessageText;
|
|
449
|
+
}
|
|
450
|
+
resolve(responseAck);
|
|
451
|
+
},
|
|
452
|
+
(oMessage) => {
|
|
453
|
+
const responseAck = { isSucessfull: false, message: "" };
|
|
454
|
+
|
|
455
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
456
|
+
const responseAckJson = JSON.parse(oMessage.response.body);
|
|
457
|
+
responseAck.isSucessfull = responseAckJson.Success;
|
|
458
|
+
responseAck.message = responseAckJson.MessageText;
|
|
459
|
+
resolve(responseAck);
|
|
460
|
+
} else if (oNotificationsService._csrfTokenInvalid(oMessage) && (bInvalidCsrfTokenRecoveryMode === false)) {
|
|
461
|
+
oNotificationsService._invalidCsrfTokenRecovery(resolve, reject, oNotificationsService.executeAction, [sNotificationId, sActionId]);
|
|
462
|
+
} else {
|
|
463
|
+
Log.error("Notification service - oData executeAction failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
464
|
+
reject(oMessage);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
this.sendBulkAction = function (sParentId, sActionId) {
|
|
471
|
+
const oNotificationsService = this;
|
|
472
|
+
const sActionUrl = oServiceConfig.serviceUrl + "/BulkActionByHeader";
|
|
473
|
+
const oRequestBody = { ParentId: sParentId, ActionId: sActionId };
|
|
474
|
+
const oRequestObject = {
|
|
475
|
+
requestUri: sActionUrl,
|
|
476
|
+
method: "POST",
|
|
477
|
+
data: oRequestBody,
|
|
478
|
+
headers: {
|
|
479
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
480
|
+
"Content-Type": "application/json",
|
|
481
|
+
DataServiceVersion: sDataServiceVersion,
|
|
482
|
+
"X-CSRF-Token": sHeaderXcsrfToken
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
return new Promise((resolve, reject) => {
|
|
487
|
+
OData.request(
|
|
488
|
+
oRequestObject,
|
|
489
|
+
(oResult) => {
|
|
490
|
+
let responseAck;
|
|
491
|
+
if (oResult && oResult.response && oResult.response.statusCode === 200 && oResult.response.body) {
|
|
492
|
+
let responseAckJson = JSON.parse(oResult.response.body);
|
|
493
|
+
responseAck = responseAckJson.value;
|
|
494
|
+
}
|
|
495
|
+
resolve(responseAck);
|
|
496
|
+
},
|
|
497
|
+
(oResult) => {
|
|
498
|
+
if (oResult.response && oResult.response.statusCode === 200 && oResult.response.body) {
|
|
499
|
+
let responseAckJson = JSON.parse(oResult.response.body);
|
|
500
|
+
let responseAck = responseAckJson.value;
|
|
501
|
+
resolve(responseAck);
|
|
502
|
+
} else if (oNotificationsService._csrfTokenInvalid(oResult) && (bInvalidCsrfTokenRecoveryMode === false)) {
|
|
503
|
+
oNotificationsService._invalidCsrfTokenRecovery(resolve, reject, oNotificationsService.sendBulkAction, [sParentId, sActionId]);
|
|
504
|
+
} else {
|
|
505
|
+
Log.error("Notification service - oData executeBulkAction failed: ", oResult.message, "sap.ushell.services.NotificationsV2");
|
|
506
|
+
reject();
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
this.sendBulkDismiss = function (sParentId) {
|
|
513
|
+
const oNotificationsService = this;
|
|
514
|
+
const sActionUrl = oServiceConfig.serviceUrl + "/DismissAll";
|
|
515
|
+
const oRequestBody = { ParentId: sParentId };
|
|
516
|
+
const oRequestObject = {
|
|
517
|
+
requestUri: sActionUrl,
|
|
518
|
+
method: "POST",
|
|
519
|
+
data: oRequestBody,
|
|
520
|
+
headers: {
|
|
521
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
522
|
+
"Content-Type": "application/json",
|
|
523
|
+
DataServiceVersion: sDataServiceVersion,
|
|
524
|
+
"X-CSRF-Token": sHeaderXcsrfToken
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
return new Promise((resolve, reject) => {
|
|
529
|
+
OData.request(oRequestObject, () => resolve(), (oResult) => {
|
|
530
|
+
if (oResult.response && oResult.response.statusCode === 200) {
|
|
531
|
+
resolve();
|
|
532
|
+
} else if (oNotificationsService._csrfTokenInvalid(oResult) && (bInvalidCsrfTokenRecoveryMode === false)) {
|
|
533
|
+
oNotificationsService._invalidCsrfTokenRecovery(resolve, reject, oNotificationsService.sendBulkDismiss, [sParentId]);
|
|
534
|
+
} else {
|
|
535
|
+
const oMessage = oResult ? oResult.message : "";
|
|
536
|
+
Log.error("Notification service - oData executeBulkAction failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
537
|
+
reject();
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
});
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Launches mark as read notification call.<br>
|
|
545
|
+
* After launching the action, the function gets updated notification data in order to push the updated data to the consumers.
|
|
546
|
+
*
|
|
547
|
+
* @param {string} sNotificationId The ID of the notification whose action is being executed
|
|
548
|
+
* @returns {Promise<undefined>} Promise object that on success resolves to undefined or it is rejected with a message object
|
|
549
|
+
* @public
|
|
550
|
+
* @alias sap.ushell.services.NotificationsV2#markRead
|
|
551
|
+
*/
|
|
552
|
+
this.markRead = function (sNotificationId) {
|
|
553
|
+
const oNotificationsService = this;
|
|
554
|
+
const sActionUrl = oServiceConfig.serviceUrl + "/MarkRead";
|
|
555
|
+
const oRequestBody = { NotificationId: sNotificationId };
|
|
556
|
+
const oRequestObject = {
|
|
557
|
+
requestUri: sActionUrl,
|
|
558
|
+
method: "POST",
|
|
559
|
+
data: oRequestBody,
|
|
560
|
+
headers: {
|
|
561
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
562
|
+
"Content-Type": "application/json",
|
|
563
|
+
DataServiceVersion: sDataServiceVersion,
|
|
564
|
+
"X-CSRF-Token": sHeaderXcsrfToken
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
return new Promise((resolve, reject) => {
|
|
569
|
+
OData.request(oRequestObject, () => resolve(), (oMessage) => {
|
|
570
|
+
if (oNotificationsService._csrfTokenInvalid(oMessage) && (bInvalidCsrfTokenRecoveryMode === false)) {
|
|
571
|
+
oNotificationsService._invalidCsrfTokenRecovery(resolve, reject, oNotificationsService.markRead, [sNotificationId]);
|
|
572
|
+
} else {
|
|
573
|
+
Log.error("Notification service - oData reset badge number failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
574
|
+
reject(oMessage);
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Launches dismiss notification call.<br>
|
|
582
|
+
*
|
|
583
|
+
* @param {string} sNotificationId The ID of the notification whose action is being executed
|
|
584
|
+
* @returns {Promise<undefined>} Promise object that on success resolves to undefined or it is rejected with a message object
|
|
585
|
+
* @public
|
|
586
|
+
* @alias sap.ushell.services.NotificationsV2#dismissNotification
|
|
587
|
+
*/
|
|
588
|
+
this.dismissNotification = function (sNotificationId) {
|
|
589
|
+
const sActionUrl = oServiceConfig.serviceUrl + "/Dismiss";
|
|
590
|
+
const oNotificationsService = this;
|
|
591
|
+
const oRequestBody = { NotificationId: sNotificationId };
|
|
592
|
+
const oRequestObject = {
|
|
593
|
+
requestUri: sActionUrl,
|
|
594
|
+
method: "POST",
|
|
595
|
+
data: oRequestBody,
|
|
596
|
+
headers: {
|
|
597
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
598
|
+
"Content-Type": "application/json",
|
|
599
|
+
DataServiceVersion: sDataServiceVersion,
|
|
600
|
+
"X-CSRF-Token": sHeaderXcsrfToken
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
return new Promise((resolve, reject) => {
|
|
605
|
+
OData.request(
|
|
606
|
+
oRequestObject,
|
|
607
|
+
() => {
|
|
608
|
+
oNotificationsService._addDismissNotifications(sNotificationId);
|
|
609
|
+
resolve();
|
|
610
|
+
},
|
|
611
|
+
(oMessage) => {
|
|
612
|
+
if (oNotificationsService._csrfTokenInvalid(oMessage) && (bInvalidCsrfTokenRecoveryMode === false)) {
|
|
613
|
+
oNotificationsService._invalidCsrfTokenRecovery(resolve, reject, oNotificationsService.dismissNotification, [sNotificationId]);
|
|
614
|
+
} else {
|
|
615
|
+
Log.error("Notification service - oData dismiss notification failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
616
|
+
reject(oMessage);
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
});
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Gets a callback function that will be called when updated notifications data is available.
|
|
624
|
+
*
|
|
625
|
+
* @param {function} callback The callback function that is registered and called on data update.
|
|
626
|
+
* @public
|
|
627
|
+
* @alias sap.ushell.services.NotificationsV2#registerNotificationsUpdateCallback
|
|
628
|
+
*/
|
|
629
|
+
this.registerNotificationsUpdateCallback = function (callback) {
|
|
630
|
+
aUpdateNotificationsCallbacks.push(callback);
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Gets a callback function that will be called when updated unseen notifications count is available.
|
|
635
|
+
*
|
|
636
|
+
* @param {function} callback The callback function that is registered and called on data update.
|
|
637
|
+
* @public
|
|
638
|
+
* @alias sap.ushell.services.NotificationsV2#registerNotificationCountUpdateCallback
|
|
639
|
+
*/
|
|
640
|
+
this.registerNotificationCountUpdateCallback = function (callback) {
|
|
641
|
+
aUpdateNotificationsCountCallbacks.push(callback);
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* @returns {boolean} boolean value whether first request was already performed and data was returned.<br>
|
|
646
|
+
* @public
|
|
647
|
+
* @alias sap.ushell.services.NotificationsV2#isFirstDataLoaded
|
|
648
|
+
*/
|
|
649
|
+
this.isFirstDataLoaded = function () {
|
|
650
|
+
return bFirstDataLoaded;
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* @returns {Promise} promise with the user settings flags
|
|
655
|
+
* @private
|
|
656
|
+
*/
|
|
657
|
+
this.getUserSettingsFlags = function () {
|
|
658
|
+
return oUserFlagsReadFromPersonalizationPromise.then(() => {
|
|
659
|
+
return { highPriorityBannerEnabled: bHighPriorityBannerEnabled };
|
|
660
|
+
});
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
this.setUserSettingsFlags = function (oFlags) {
|
|
664
|
+
bHighPriorityBannerEnabled = oFlags.highPriorityBannerEnabled;
|
|
665
|
+
this._writeUserSettingsFlagsToPersonalization(oFlags);
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* @returns {boolean} value indicating whether the Push to Mobile capability is supported by the Notification channel
|
|
670
|
+
* @private
|
|
671
|
+
*/
|
|
672
|
+
this._getNotificationSettingsMobileSupport = function () {
|
|
673
|
+
return bNotificationSettingsMobileSupport;
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* @returns {Array} dismissed notifications
|
|
678
|
+
* @private
|
|
679
|
+
*/
|
|
680
|
+
this._getDismissNotifications = function () {
|
|
681
|
+
return aDismissNotifications;
|
|
682
|
+
};
|
|
683
|
+
|
|
684
|
+
this.filterDismisssedItems = function (aRecentNotificationsArray, aNotifications) {
|
|
685
|
+
return aRecentNotificationsArray.filter((oRecentItem) => {
|
|
686
|
+
return !aNotifications.some((sDismissItem) => sDismissItem === oRecentItem.originalItemId);
|
|
687
|
+
});
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* adds an item to the array of dissmissed notifications
|
|
692
|
+
* @param {string} sId Notification ID.
|
|
693
|
+
* @private
|
|
694
|
+
*/
|
|
695
|
+
this._addDismissNotifications = function (sId) {
|
|
696
|
+
if (aDismissNotifications.indexOf(sId) === -1) {
|
|
697
|
+
aDismissNotifications.push(sId);
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* initialize array of dissmissed notifications
|
|
703
|
+
* @private
|
|
704
|
+
*/
|
|
705
|
+
this._initializeDismissNotifications = function () {
|
|
706
|
+
aDismissNotifications = [];
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* @returns {boolean} value indicating whether the Push to Mobile capability is supported by the Notification channel
|
|
711
|
+
* @private
|
|
712
|
+
*/
|
|
713
|
+
this._getNotificationSettingsEmailSupport = function () {
|
|
714
|
+
return bNotificationSettingsEmailSupport;
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
this.destroy = function () {
|
|
718
|
+
bOnServiceStop = true;
|
|
719
|
+
|
|
720
|
+
// Clear timers
|
|
721
|
+
if (initialReadTimer) {
|
|
722
|
+
clearTimeout(initialReadTimer);
|
|
723
|
+
} else if (webSocketRecoveryTimer) {
|
|
724
|
+
clearTimeout(webSocketRecoveryTimer);
|
|
725
|
+
} else if (pollingTimer) {
|
|
726
|
+
clearTimeout(pollingTimer);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Close web socket
|
|
730
|
+
if ((oCurrentMode === oModesEnum.WEB_SOCKET) && oWebSocket) {
|
|
731
|
+
oWebSocket.close();
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// Clear event subscriptions
|
|
735
|
+
Core.getEventBus().unsubscribe("launchpad", "sessionTimeout", this.destroy, this);
|
|
736
|
+
Core.getEventBus().unsubscribe("launchpad", "setConnectionToServer",
|
|
737
|
+
this._onSetConnectionToServer, this);
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
// ************************************** Service API - End ****************************************
|
|
741
|
+
// *************************************************************************************************
|
|
742
|
+
|
|
743
|
+
// *************************************************************************************************
|
|
744
|
+
// ********************************* oData functionality - Begin ***********************************
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Fetching the number of notifications that the user hasn't seen yet <br>
|
|
748
|
+
* and announcing the relevant consumers by calling all registered callback functions.<br>
|
|
749
|
+
*
|
|
750
|
+
* This function is similar to _readNotificationsData.
|
|
751
|
+
* In the future the two functions will be sent together in a single batch request, when batch is supported.
|
|
752
|
+
*
|
|
753
|
+
* @returns {Promise} promise
|
|
754
|
+
* @private
|
|
755
|
+
*/
|
|
756
|
+
this._readUnseenNotificationsCount = function () {
|
|
757
|
+
const oNotificationsService = this;
|
|
758
|
+
const oRequestObject = this._createRequest(this._getRequestURI(oOperationEnum.GET_BADGE_NUMBER));
|
|
759
|
+
|
|
760
|
+
return new Promise((resolve, reject) => {
|
|
761
|
+
OData.read(
|
|
762
|
+
oRequestObject,
|
|
763
|
+
(oResult, oResponseData) => {
|
|
764
|
+
oModel.setProperty("/UnseenCount", oResponseData.data.GetBadgeNumber.Number);
|
|
765
|
+
oNotificationsService._setNativeIconBadge(oResponseData.data.GetBadgeNumber.Number);
|
|
766
|
+
resolve(oResponseData.data.GetBadgeNumber.Number);
|
|
767
|
+
},
|
|
768
|
+
(oMessage) => {
|
|
769
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
770
|
+
const oReturnedObject = JSON.parse(oMessage.response.body);
|
|
771
|
+
oModel.setProperty("/UnseenCount", oReturnedObject.value);
|
|
772
|
+
oNotificationsService._setNativeIconBadge(oReturnedObject.value);
|
|
773
|
+
resolve(oReturnedObject.value);
|
|
774
|
+
} else {
|
|
775
|
+
Log.error("Notification service - oData read unseen notifications count failed: ", oMessage.message, "sap.ushell.services.NotificationsV2");
|
|
776
|
+
reject(oMessage);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
);
|
|
780
|
+
});
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
/**
|
|
784
|
+
* Fetching the number of notifications for user<br>
|
|
785
|
+
* @returns {object} promise with notifications count
|
|
786
|
+
*/
|
|
787
|
+
this.readNotificationsCount = function () {
|
|
788
|
+
const oRequestObject = this._createRequest(this._getRequestURI(oOperationEnum.GET_NOTIFICATIONS_COUNT));
|
|
789
|
+
return new Promise((resolve, reject) => {
|
|
790
|
+
OData.read(
|
|
791
|
+
oRequestObject,
|
|
792
|
+
(oResult, oResponseData) => resolve(oResponseData.data),
|
|
793
|
+
(oMessage) => {
|
|
794
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
795
|
+
const oReturnedObject = JSON.parse(oMessage.response.body);
|
|
796
|
+
resolve(oReturnedObject.value);
|
|
797
|
+
} else {
|
|
798
|
+
Log.error("Notification service - oData read notifications count failed: ", oMessage.message, "sap.ushell.services.NotificationsV2");
|
|
799
|
+
reject(oMessage);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
);
|
|
803
|
+
});
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* @returns {Promise} Returns promise object that is resolved if Notification settings data is available
|
|
808
|
+
* @private
|
|
809
|
+
*/
|
|
810
|
+
this._getNotificationSettingsAvailability = function () {
|
|
811
|
+
return oNotificationSettingsAvailabilityDeferred.promise();
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Mark all notifications as seen.<br>
|
|
816
|
+
* the main use-case is when the user navigated to the notification center and sees all the pending notifications.
|
|
817
|
+
* @returns {Promise} Promise taht resolves when operation is finished
|
|
818
|
+
*
|
|
819
|
+
* @public
|
|
820
|
+
* @alias sap.ushell.services.NotificationsV2#notificationsSeen
|
|
821
|
+
*/
|
|
822
|
+
this.notificationsSeen = function () {
|
|
823
|
+
const oNotificationsService = this;
|
|
824
|
+
const oRequestObject = {
|
|
825
|
+
requestUri: this._getRequestURI(oOperationEnum.RESET_BADGE_NUMBER),
|
|
826
|
+
method: "POST",
|
|
827
|
+
headers: {
|
|
828
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
829
|
+
"Content-Type": "application/json",
|
|
830
|
+
DataServiceVersion: sDataServiceVersion,
|
|
831
|
+
"X-CSRF-Token": sHeaderXcsrfToken
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
if (this._isFioriClientMode() === true || this._isPackagedMode() === true) {
|
|
836
|
+
this._setNativeIconBadge(0);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
return new Promise((resolve, reject) => {
|
|
840
|
+
OData.request(
|
|
841
|
+
oRequestObject,
|
|
842
|
+
resolve,
|
|
843
|
+
function (oMessage) {
|
|
844
|
+
if (oNotificationsService._csrfTokenInvalid(oMessage) && (bInvalidCsrfTokenRecoveryMode === false)) {
|
|
845
|
+
oNotificationsService._invalidCsrfTokenRecovery(resolve, reject, oNotificationsService.notificationsSeen);
|
|
846
|
+
} else {
|
|
847
|
+
Log.error("Notification service - oData reset badge number failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
848
|
+
reject(oMessage);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
});
|
|
853
|
+
};
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* Basic notifications data read flow, occurs either on service initialization or on web-socket/polling update event.
|
|
857
|
+
* Includes two read operations:
|
|
858
|
+
* - Read UnseenNotificationsCount and update consumers
|
|
859
|
+
* - Read several (i.e. iInitialBufferSize) notification items
|
|
860
|
+
*
|
|
861
|
+
* The two returned promise objects are pushed into an array, and after resolved, the following steps are performed:
|
|
862
|
+
* - Notifications (unseen) count consumers are updated
|
|
863
|
+
* - Service model is updated with the read notification objects
|
|
864
|
+
* - Notifications update consumers are updated
|
|
865
|
+
*
|
|
866
|
+
* @param {boolean} bUpdateConsumers value indicating whether the consumers should be updated
|
|
867
|
+
* @returns {Promise} promise indicating success of both read actions
|
|
868
|
+
* @private
|
|
869
|
+
*/
|
|
870
|
+
this._readNotificationsData = function (bUpdateConsumers) {
|
|
871
|
+
const oNotificationsService = this;
|
|
872
|
+
|
|
873
|
+
this.readNotificationsCount().then((oResponseData) => oModel.setProperty("/NotificationsCount", oResponseData));
|
|
874
|
+
|
|
875
|
+
const oReadUnseenCountPromise = this._readUnseenNotificationsCount(bUpdateConsumers).then(() => {
|
|
876
|
+
if (bUpdateConsumers === true) {
|
|
877
|
+
oNotificationsService._updateNotificationsCountConsumers();
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
const oReadNotificationsPromise = this.getNotificationsBufferBySortingType(oOperationEnum.NOTIFICATIONS_BY_DATE_DESCENDING, 0, iInitialBufferSize)
|
|
882
|
+
.then((oResponseData) => {
|
|
883
|
+
// Measure notification
|
|
884
|
+
oModel.setProperty("/Notifications", oResponseData);
|
|
885
|
+
oNotificationsService._notificationAlert(oResponseData);
|
|
886
|
+
if (bUpdateConsumers === true) {
|
|
887
|
+
oNotificationsService._updateNotificationsConsumers();
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
return Promise.all([oReadUnseenCountPromise, oReadNotificationsPromise]);
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
this._getHeaderXcsrfToken = function () {
|
|
895
|
+
return sHeaderXcsrfToken;
|
|
896
|
+
};
|
|
897
|
+
|
|
898
|
+
this._getDataServiceVersion = function () {
|
|
899
|
+
return sDataServiceVersion;
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Returns the appropriate URI that should be used in an OData request according to the nature of the request and according to filtering that might be required.
|
|
904
|
+
* The object aRequestURIs is filled with the basic and/or byIntents-filter URI, and is used for maintaining the URIs throughout the session.
|
|
905
|
+
*
|
|
906
|
+
* @param {object} oRequiredURI value form the enumeration oOperationEnum, representing the relevant request
|
|
907
|
+
* @param {object} oArgs additional arguments
|
|
908
|
+
* @returns {string} The URI that should be user in the OData.read call
|
|
909
|
+
*/
|
|
910
|
+
this._getRequestURI = function (oRequiredURI, oArgs) {
|
|
911
|
+
const sEncodedConsumedIntents = encodeURI(this._getConsumedIntents(oRequiredURI));
|
|
912
|
+
let sReturnedURI;
|
|
913
|
+
|
|
914
|
+
switch (oRequiredURI) {
|
|
915
|
+
// Get notifications
|
|
916
|
+
case oOperationEnum.NOTIFICATIONS:
|
|
917
|
+
if (aRequestURIs.getNotifications.basic === undefined) {
|
|
918
|
+
aRequestURIs.getNotifications.basic = oServiceConfig.serviceUrl + "/Notifications?$expand=Actions,NavigationTargetParams&$filter=IsGroupHeader%20eq%20false";
|
|
919
|
+
}
|
|
920
|
+
if (this._isIntentBasedConsumption()) {
|
|
921
|
+
if (aRequestURIs.getNotifications.byIntents === undefined) {
|
|
922
|
+
aRequestURIs.getNotifications.byIntents = aRequestURIs.getNotifications.basic.concat("&intents%20eq%20" + sEncodedConsumedIntents);
|
|
923
|
+
}
|
|
924
|
+
return aRequestURIs.getNotifications.byIntents;
|
|
925
|
+
}
|
|
926
|
+
return aRequestURIs.getNotifications.basic;
|
|
927
|
+
// Get notifications, grouped by type
|
|
928
|
+
case oOperationEnum.NOTIFICATIONS_BY_TYPE:
|
|
929
|
+
if (aRequestURIs.getNotificationsByType.basic === undefined) {
|
|
930
|
+
aRequestURIs.getNotificationsByType.basic = oServiceConfig.serviceUrl + "/Notifications?$expand=Actions,NavigationTargetParams";
|
|
931
|
+
}
|
|
932
|
+
if (this._isIntentBasedConsumption()) {
|
|
933
|
+
if (aRequestURIs.getNotificationsByType.byIntents === undefined) {
|
|
934
|
+
aRequestURIs.getNotificationsByType.byIntents = aRequestURIs.getNotificationsByType.basic.concat("&$filter=intents%20eq%20" + sEncodedConsumedIntents);
|
|
935
|
+
}
|
|
936
|
+
return aRequestURIs.getNotificationsByType.byIntents;
|
|
937
|
+
}
|
|
938
|
+
return aRequestURIs.getNotificationsByType.basic;
|
|
939
|
+
|
|
940
|
+
// Get notifications group Headers
|
|
941
|
+
case oOperationEnum.NOTIFICATIONS_GROUP_HEADERS:
|
|
942
|
+
if (aRequestURIs.getNotificationsGroupHeaders.basic === undefined) {
|
|
943
|
+
aRequestURIs.getNotificationsGroupHeaders.basic = oServiceConfig.serviceUrl + "/Notifications?$expand=Actions,NavigationTargetParams&$filter=IsGroupHeader%20eq%20true";
|
|
944
|
+
}
|
|
945
|
+
if (this._isIntentBasedConsumption()) {
|
|
946
|
+
if (aRequestURIs.getNotificationsGroupHeaders.byIntents === undefined) {
|
|
947
|
+
aRequestURIs.getNotificationsGroupHeaders.byIntents = aRequestURIs.getNotificationsGroupHeaders.basic.concat("&intents%20eq%20" + sEncodedConsumedIntents);
|
|
948
|
+
}
|
|
949
|
+
return aRequestURIs.getNotificationsGroupHeaders.byIntents;
|
|
950
|
+
}
|
|
951
|
+
return aRequestURIs.getNotificationsGroupHeaders.basic;
|
|
952
|
+
|
|
953
|
+
// Get notifications in group
|
|
954
|
+
case oOperationEnum.NOTIFICATIONS_IN_GROUP:
|
|
955
|
+
sReturnedURI = oServiceConfig.serviceUrl + "/Notifications?$expand=Actions,NavigationTargetParams&$orderby=CreatedAt desc&$filter=IsGroupHeader eq false and ParentId eq "
|
|
956
|
+
+ oArgs.group + "&$skip=" + oArgs.skip + "&$top=" + oArgs.top;
|
|
957
|
+
|
|
958
|
+
if (this._isIntentBasedConsumption() === true) {
|
|
959
|
+
sReturnedURI = sReturnedURI.concat("&intents%20eq%20" + sEncodedConsumedIntents);
|
|
960
|
+
}
|
|
961
|
+
break;
|
|
962
|
+
|
|
963
|
+
// Get badge number
|
|
964
|
+
case oOperationEnum.GET_BADGE_NUMBER:
|
|
965
|
+
if (aRequestURIs.getBadgeNumber.basic === undefined) {
|
|
966
|
+
aRequestURIs.getBadgeNumber.basic = oServiceConfig.serviceUrl + "/GetBadgeNumber()";
|
|
967
|
+
}
|
|
968
|
+
if (this._isIntentBasedConsumption()) {
|
|
969
|
+
if (aRequestURIs.getBadgeNumber.byIntents === undefined) {
|
|
970
|
+
aRequestURIs.getBadgeNumber.byIntents = oServiceConfig.serviceUrl + "/GetBadgeCountByIntent(" + sEncodedConsumedIntents + ")";
|
|
971
|
+
}
|
|
972
|
+
return aRequestURIs.getBadgeNumber.byIntents;
|
|
973
|
+
}
|
|
974
|
+
return aRequestURIs.getBadgeNumber.basic;
|
|
975
|
+
|
|
976
|
+
// Get Notification Count
|
|
977
|
+
case oOperationEnum.GET_NOTIFICATIONS_COUNT:
|
|
978
|
+
if (aRequestURIs.getNotificationCount.basic === undefined) {
|
|
979
|
+
aRequestURIs.getNotificationCount.basic = oServiceConfig.serviceUrl + "/Notifications/$count";
|
|
980
|
+
}
|
|
981
|
+
return aRequestURIs.getNotificationCount.basic;
|
|
982
|
+
|
|
983
|
+
// Reset badge number (i.e. mark all notifications as "seen")
|
|
984
|
+
case oOperationEnum.RESET_BADGE_NUMBER:
|
|
985
|
+
if (aRequestURIs.resetBadgeNumber.basic === undefined) {
|
|
986
|
+
aRequestURIs.resetBadgeNumber.basic = oServiceConfig.serviceUrl + "/ResetBadgeNumber";
|
|
987
|
+
}
|
|
988
|
+
return aRequestURIs.resetBadgeNumber.basic;
|
|
989
|
+
|
|
990
|
+
// Get user settings
|
|
991
|
+
case oOperationEnum.GET_SETTINGS:
|
|
992
|
+
if (aRequestURIs.getNotificationTypesSettings.basic === undefined) {
|
|
993
|
+
aRequestURIs.getNotificationTypesSettings.basic = oServiceConfig.serviceUrl + "/NotificationTypePersonalizationSet";
|
|
994
|
+
}
|
|
995
|
+
return aRequestURIs.getNotificationTypesSettings.basic;
|
|
996
|
+
|
|
997
|
+
case oOperationEnum.GET_MOBILE_SUPPORT_SETTINGS:
|
|
998
|
+
if (aRequestURIs.getMobileSupportSettings.basic === undefined) {
|
|
999
|
+
aRequestURIs.getMobileSupportSettings.basic = oServiceConfig.serviceUrl + "/Channels(ChannelId='SAP_SMP')";
|
|
1000
|
+
}
|
|
1001
|
+
return aRequestURIs.getMobileSupportSettings.basic;
|
|
1002
|
+
|
|
1003
|
+
case oOperationEnum.GET_EMAIL_SUPPORT_SETTINGS:
|
|
1004
|
+
if (aRequestURIs.getEmailSupportSettings.basic === undefined) {
|
|
1005
|
+
aRequestURIs.getEmailSupportSettings.basic = oServiceConfig.serviceUrl + "/Channels(ChannelId='SAP_EMAIL')";
|
|
1006
|
+
}
|
|
1007
|
+
return aRequestURIs.getEmailSupportSettings.basic;
|
|
1008
|
+
|
|
1009
|
+
case oOperationEnum.VALIDATE_WEBSOCKET_CHANNEL:
|
|
1010
|
+
if (aRequestURIs.getWebSocketValidity.basic === undefined) {
|
|
1011
|
+
aRequestURIs.getWebSocketValidity.basic = oServiceConfig.serviceUrl + "/Channels('SAP_WEBSOCKET')";
|
|
1012
|
+
}
|
|
1013
|
+
return aRequestURIs.getWebSocketValidity.basic;
|
|
1014
|
+
|
|
1015
|
+
// Get a buffer of notifications (using $skip, $top and $orderby options) sorted by date in descending order
|
|
1016
|
+
case oOperationEnum.NOTIFICATIONS_BY_DATE_DESCENDING:
|
|
1017
|
+
sReturnedURI = oServiceConfig.serviceUrl + "/Notifications?$expand=Actions,NavigationTargetParams&$orderby=CreatedAt%20desc&$filter=IsGroupHeader%20eq%20false&$skip="
|
|
1018
|
+
+ oArgs.skip + "&$top=" + oArgs.top;
|
|
1019
|
+
if (this._isIntentBasedConsumption() === true) {
|
|
1020
|
+
sReturnedURI = sReturnedURI.concat("&intents%20eq%20" + sEncodedConsumedIntents);
|
|
1021
|
+
}
|
|
1022
|
+
break;
|
|
1023
|
+
|
|
1024
|
+
// Get a buffer of notifications (using $skip, $top and $orderby options) sorted by date in ascending order
|
|
1025
|
+
case oOperationEnum.NOTIFICATIONS_BY_DATE_ASCENDING:
|
|
1026
|
+
sReturnedURI = oServiceConfig.serviceUrl + "/Notifications?$expand=Actions,NavigationTargetParams&$orderby=CreatedAt%20asc&$filter=IsGroupHeader%20eq%20false&$skip="
|
|
1027
|
+
+ oArgs.skip + "&$top=" + oArgs.top;
|
|
1028
|
+
if (this._isIntentBasedConsumption() === true) {
|
|
1029
|
+
sReturnedURI = sReturnedURI.concat("&intents%20eq%20" + sEncodedConsumedIntents);
|
|
1030
|
+
}
|
|
1031
|
+
break;
|
|
1032
|
+
|
|
1033
|
+
// Get a buffer of notifications (using $skip, $top and $orderby options) sorted by priority in ascending order
|
|
1034
|
+
case oOperationEnum.NOTIFICATIONS_BY_PRIORITY_DESCENDING:
|
|
1035
|
+
sReturnedURI = oServiceConfig.serviceUrl + "/Notifications?$expand=Actions,NavigationTargetParams&$orderby=Priority%20desc&$filter=IsGroupHeader%20eq%20false&$skip="
|
|
1036
|
+
+ oArgs.skip + "&$top=" + oArgs.top;
|
|
1037
|
+
if (this._isIntentBasedConsumption() === true) {
|
|
1038
|
+
sReturnedURI = sReturnedURI.concat("&intents%20eq%20" + sEncodedConsumedIntents);
|
|
1039
|
+
}
|
|
1040
|
+
break;
|
|
1041
|
+
|
|
1042
|
+
default:
|
|
1043
|
+
sReturnedURI = "";
|
|
1044
|
+
}
|
|
1045
|
+
return sReturnedURI;
|
|
1046
|
+
};
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* @returns {Promise} Promise object that is resolved with the settings from the sever
|
|
1050
|
+
* @private
|
|
1051
|
+
*/
|
|
1052
|
+
this.readSettings = function () {
|
|
1053
|
+
const oRequestObject = this._createRequest(this._getRequestURI(oOperationEnum.GET_SETTINGS));
|
|
1054
|
+
|
|
1055
|
+
return new Promise((resolve, reject) => {
|
|
1056
|
+
OData.request(
|
|
1057
|
+
oRequestObject,
|
|
1058
|
+
(oResult) => resolve(oResult.results),
|
|
1059
|
+
(oMessage) => {
|
|
1060
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
1061
|
+
resolve(oMessage.response.body);
|
|
1062
|
+
} else {
|
|
1063
|
+
Log.error("Notification service - oData get settings failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
1064
|
+
reject(oMessage);
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
});
|
|
1068
|
+
};
|
|
1069
|
+
|
|
1070
|
+
/**
|
|
1071
|
+
* Verifying whether the "push notifications to mobile" feature is supported.
|
|
1072
|
+
*
|
|
1073
|
+
* @returns {object} A Deferred.promise object that is always resolved even if the request failed.<br>
|
|
1074
|
+
* In case of failure - the response property successStatus gets the value <code>false</code>
|
|
1075
|
+
*/
|
|
1076
|
+
this._readMobileSettingsFromServer = function () {
|
|
1077
|
+
return this._readChannelSettingsFromServer(oOperationEnum.GET_MOBILE_SUPPORT_SETTINGS);
|
|
1078
|
+
};
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* Verifying whether the "push notifications to mobile" feature is supported.
|
|
1082
|
+
*
|
|
1083
|
+
* @returns {Promise} promise is always resolved even if the request failed.<br>
|
|
1084
|
+
* In case of failure - the response property successStatus gets the value <code>false</code>
|
|
1085
|
+
*/
|
|
1086
|
+
this._readEmailSettingsFromServer = function () {
|
|
1087
|
+
return this._readChannelSettingsFromServer(oOperationEnum.GET_EMAIL_SUPPORT_SETTINGS);
|
|
1088
|
+
};
|
|
1089
|
+
|
|
1090
|
+
this._readChannelSettingsFromServer = function (operation) {
|
|
1091
|
+
const sRequestUrl = this._getRequestURI(operation);
|
|
1092
|
+
const oRequestObject = this._createRequest(sRequestUrl);
|
|
1093
|
+
let oResponseObject;
|
|
1094
|
+
let sUpdatedResponseString;
|
|
1095
|
+
|
|
1096
|
+
return new Promise((resolve) => {
|
|
1097
|
+
OData.request(
|
|
1098
|
+
oRequestObject,
|
|
1099
|
+
(oResult) => {
|
|
1100
|
+
if (typeof (oResult.results) === "string") {
|
|
1101
|
+
oResponseObject = JSON.parse(oResult.results);
|
|
1102
|
+
oResponseObject.successStatus = true;
|
|
1103
|
+
sUpdatedResponseString = JSON.stringify(oResponseObject);
|
|
1104
|
+
resolve(sUpdatedResponseString);
|
|
1105
|
+
} else {
|
|
1106
|
+
oResult.results.successStatus = true;
|
|
1107
|
+
resolve(oResult.results);
|
|
1108
|
+
}
|
|
1109
|
+
},
|
|
1110
|
+
(oMessage) => {
|
|
1111
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
1112
|
+
oResponseObject = JSON.parse(oMessage.response.body);
|
|
1113
|
+
oResponseObject.successStatus = true;
|
|
1114
|
+
sUpdatedResponseString = JSON.stringify(oResponseObject);
|
|
1115
|
+
resolve(sUpdatedResponseString);
|
|
1116
|
+
} else {
|
|
1117
|
+
Log.error("Notification service - oData get settings failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
1118
|
+
resolve(JSON.stringify({ successStatus: false }));
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
);
|
|
1122
|
+
});
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Verifying whether the WebSocket is active (while it is already opened)
|
|
1127
|
+
*
|
|
1128
|
+
* @returns {Promise} promise is always resolved even if the request fails.<br>
|
|
1129
|
+
* The actual response is returned as the done function's boolean parameter:<br>
|
|
1130
|
+
* In case of active WebSocket - the value <code>true</code> is returned, and <code>false</code> otherwise.
|
|
1131
|
+
*/
|
|
1132
|
+
this._checkWebSocketActivity = function () {
|
|
1133
|
+
const oRequestObject = this._createRequest(this._getRequestURI(oOperationEnum.VALIDATE_WEBSOCKET_CHANNEL));
|
|
1134
|
+
return new Promise((resolve) => {
|
|
1135
|
+
OData.request(
|
|
1136
|
+
oRequestObject,
|
|
1137
|
+
(oResult) => {
|
|
1138
|
+
if (typeof (oResult.results) === "string") {
|
|
1139
|
+
const oResponseObject = JSON.parse(oResult.results);
|
|
1140
|
+
resolve(oResponseObject.IsActive);
|
|
1141
|
+
} else {
|
|
1142
|
+
resolve(false);
|
|
1143
|
+
}
|
|
1144
|
+
},
|
|
1145
|
+
(oMessage) => {
|
|
1146
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
1147
|
+
const oResponseObject = JSON.parse(oMessage.response.body);
|
|
1148
|
+
resolve(oResponseObject.IsActive);
|
|
1149
|
+
} else {
|
|
1150
|
+
Log.error("Notification service - oData get settings failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
1151
|
+
resolve(false);
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
});
|
|
1155
|
+
};
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* @param {object} oEntry Settings entry to be saved
|
|
1159
|
+
* @returns {Promise} Save settings promise
|
|
1160
|
+
* @private
|
|
1161
|
+
*/
|
|
1162
|
+
this.saveSettingsEntry = function (oEntry) {
|
|
1163
|
+
const oNotificationsService = this;
|
|
1164
|
+
const sSetSettingsUrl = this._getRequestURI(oOperationEnum.GET_SETTINGS) + "(NotificationTypeId=" + oEntry.NotificationTypeId + ")";
|
|
1165
|
+
const oRequestObject = {
|
|
1166
|
+
requestUri: sSetSettingsUrl,
|
|
1167
|
+
method: "PUT",
|
|
1168
|
+
headers: {
|
|
1169
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
1170
|
+
"Content-Type": "application/json",
|
|
1171
|
+
DataServiceVersion: sDataServiceVersion,
|
|
1172
|
+
"X-CSRF-Token": sHeaderXcsrfToken
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
|
|
1176
|
+
// make sure to always send the entire set of properties to the backend
|
|
1177
|
+
oRequestObject.data = JSON.parse(JSON.stringify(oEntry));
|
|
1178
|
+
oRequestObject.data["@odata.context"] = "$metadata#NotificationTypePersonalizationSet/$entity";
|
|
1179
|
+
|
|
1180
|
+
return new Promise((resolve, reject) => {
|
|
1181
|
+
OData.request(
|
|
1182
|
+
oRequestObject,
|
|
1183
|
+
resolve,
|
|
1184
|
+
(oMessage) => {
|
|
1185
|
+
if (oMessage.response && oMessage.response.statusCode === 200 && oMessage.response.body) {
|
|
1186
|
+
resolve(oMessage.response.body);
|
|
1187
|
+
} else if (oNotificationsService._csrfTokenInvalid(oMessage) && (bInvalidCsrfTokenRecoveryMode === false)) {
|
|
1188
|
+
oNotificationsService._invalidCsrfTokenRecovery(resolve, reject, oNotificationsService.saveSettingsEntry, [oEntry]);
|
|
1189
|
+
} else {
|
|
1190
|
+
Log.error("Notification service - oData set settings entry failed: ", oMessage, "sap.ushell.services.NotificationsV2");
|
|
1191
|
+
reject(oMessage);
|
|
1192
|
+
}
|
|
1193
|
+
});
|
|
1194
|
+
});
|
|
1195
|
+
};
|
|
1196
|
+
|
|
1197
|
+
// ********************************** oData functionality - End ************************************
|
|
1198
|
+
// *************************************************************************************************
|
|
1199
|
+
|
|
1200
|
+
this._updateNotificationsConsumers = function () {
|
|
1201
|
+
aUpdateNotificationsCallbacks.forEach(callback => callback());
|
|
1202
|
+
};
|
|
1203
|
+
|
|
1204
|
+
this._updateNotificationsCountConsumers = function () {
|
|
1205
|
+
aUpdateNotificationsCountCallbacks.forEach(callback => callback());
|
|
1206
|
+
};
|
|
1207
|
+
|
|
1208
|
+
this._updateAllConsumers = function () {
|
|
1209
|
+
this._updateNotificationsConsumers();
|
|
1210
|
+
this._updateNotificationsCountConsumers();
|
|
1211
|
+
};
|
|
1212
|
+
|
|
1213
|
+
this._getModel = function () {
|
|
1214
|
+
return oModel;
|
|
1215
|
+
};
|
|
1216
|
+
|
|
1217
|
+
//*************************************************************************************************
|
|
1218
|
+
//*********************** Handle Notifications consumption / modes - Begin ***********************
|
|
1219
|
+
|
|
1220
|
+
this._getMode = function () {
|
|
1221
|
+
return oCurrentMode;
|
|
1222
|
+
};
|
|
1223
|
+
|
|
1224
|
+
/**
|
|
1225
|
+
* There are four possible modes of working of Notification service, defined by oModesEnum.
|
|
1226
|
+
* The following functions (i.e. steps) are executes sequentially, from _setWorkingMode (step 1) downwards
|
|
1227
|
+
* in order to find what is the relevant working mode for notification service and to activate it.
|
|
1228
|
+
*/
|
|
1229
|
+
|
|
1230
|
+
/**
|
|
1231
|
+
* Starting the process of defining the mode in which notifications service consume notifications data.
|
|
1232
|
+
* Step 1. Handle packagedApp mode
|
|
1233
|
+
*/
|
|
1234
|
+
this._setWorkingMode = function () {
|
|
1235
|
+
let aConsumedIntentsFromConfig;
|
|
1236
|
+
|
|
1237
|
+
// check service configuration for ConsumedIntents enabling flag and data
|
|
1238
|
+
if (oServiceConfig.intentBasedConsumption === true) {
|
|
1239
|
+
aConsumedIntents = this._getIntentsFromConfiguration(oServiceConfig.consumedIntents);
|
|
1240
|
+
if (aConsumedIntents.length > 0) {
|
|
1241
|
+
// First setting of the flag is from service configuration
|
|
1242
|
+
bIntentBasedConsumption = true;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// Check if this is packagedApp use-case
|
|
1247
|
+
if (this._isPackagedMode()) {
|
|
1248
|
+
oCurrentMode = oModesEnum.PACKAGED_APP;
|
|
1249
|
+
|
|
1250
|
+
// Consumed intents are read from PackagedApp configuration, if exist
|
|
1251
|
+
aConsumedIntentsFromConfig = this._getIntentsFromConfiguration(window.fiori_client_appConfig.applications);
|
|
1252
|
+
if (aConsumedIntentsFromConfig.length > 0) {
|
|
1253
|
+
aConsumedIntents = aConsumedIntentsFromConfig;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
if (aConsumedIntents.length > 0) {
|
|
1257
|
+
// Second setting of the flag (to true) is done in case of PackagedApp mode and if any intents were configured
|
|
1258
|
+
bIntentBasedConsumption = true;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
this._registerForPush();
|
|
1262
|
+
this._readNotificationsData(true);
|
|
1263
|
+
|
|
1264
|
+
this._setNativeIconBadgeWithDelay();
|
|
1265
|
+
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
// Call step 2: Perform the first oData read request
|
|
1270
|
+
this._performFirstRead();
|
|
1271
|
+
};
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* Step 2. Issue the initial oData call for getting notification data, then wait until it is possible to check if we're in Fiori Client mode:
|
|
1275
|
+
* The execution of the _isFioriClientMode check must be delayed by 6000ms for initial loading since it relies on the flag sap.FioriClient that is set by FioriClient
|
|
1276
|
+
*/
|
|
1277
|
+
this._performFirstRead = function () {
|
|
1278
|
+
const oNotificationsService = this;
|
|
1279
|
+
|
|
1280
|
+
this._readNotificationsData(true).then(() => {
|
|
1281
|
+
// Calculate time left until Fiori Client mode can be checked
|
|
1282
|
+
const tFioriClientRemainingDelay = oNotificationsService._getFioriClientRemainingDelay();
|
|
1283
|
+
if (tFioriClientRemainingDelay <= 0) {
|
|
1284
|
+
oNotificationsService._fioriClientStep();
|
|
1285
|
+
} else {
|
|
1286
|
+
initialReadTimer = setTimeout(function () {
|
|
1287
|
+
oNotificationsService._fioriClientStep();
|
|
1288
|
+
}, tFioriClientRemainingDelay);
|
|
1289
|
+
}
|
|
1290
|
+
bFirstDataLoaded = true;
|
|
1291
|
+
}).catch((sMsg) => {
|
|
1292
|
+
Log.error("Notifications oData read failed. Error: " + sMsg);
|
|
1293
|
+
});
|
|
1294
|
+
};
|
|
1295
|
+
|
|
1296
|
+
/**
|
|
1297
|
+
* Step 3. waiting the delay necessary for Fiori Client - Check if this is indeed Fiori Client mode
|
|
1298
|
+
* If so - initialize Fiori Client mode. If not - go to the nest step (webSocket)
|
|
1299
|
+
*/
|
|
1300
|
+
this._fioriClientStep = function () {
|
|
1301
|
+
if (this._isFioriClientMode()) {
|
|
1302
|
+
oCurrentMode = oModesEnum.FIORI_CLIENT;
|
|
1303
|
+
this._addPushNotificationHandler();
|
|
1304
|
+
|
|
1305
|
+
this.getUnseenNotificationsCount()
|
|
1306
|
+
.then(function (iBadgeValue) {
|
|
1307
|
+
this._setNativeIconBadge(iBadgeValue, () => { });
|
|
1308
|
+
}.bind(this))
|
|
1309
|
+
.catch(() => { });
|
|
1310
|
+
} else {
|
|
1311
|
+
this._webSocketStep();
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* Step 4. WebSocket step
|
|
1317
|
+
*/
|
|
1318
|
+
this._webSocketStep = function () {
|
|
1319
|
+
oCurrentMode = oModesEnum.WEB_SOCKET;
|
|
1320
|
+
this._establishWebSocketConnection();
|
|
1321
|
+
};
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* Step 5. WebSocket recovery step
|
|
1325
|
+
* Called on WebSocket onClose event.
|
|
1326
|
+
* In this case there is one additional trial to establish the WebSocket connection.
|
|
1327
|
+
* If the additional attempt also fails - move to polling
|
|
1328
|
+
*/
|
|
1329
|
+
this._webSocketRecoveryStep = function () {
|
|
1330
|
+
if (bWebSocketRecoveryAttempted === false) {
|
|
1331
|
+
bWebSocketRecoveryAttempted = true;
|
|
1332
|
+
webSocketRecoveryTimer = window.setTimeout(this._webSocketStep.bind(this), tWebSocketRecoveryPeriod);
|
|
1333
|
+
} else {
|
|
1334
|
+
// Since the first request for notifications data was already issued -
|
|
1335
|
+
// the first polling request is delayed by (iPollingInterval * 1000) seconds
|
|
1336
|
+
this._activatePollingAfterInterval();
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
|
|
1340
|
+
this._activatePollingAfterInterval = function () {
|
|
1341
|
+
const iPollingInterval = oServiceConfig.pollingIntervalInSeconds || I_DEFAULT_POLLING_INTERVAL;
|
|
1342
|
+
|
|
1343
|
+
window.clearTimeout(pollingTimer);
|
|
1344
|
+
pollingTimer = window.setTimeout(this._activatePolling.bind(this), ushellUtils.sanitizeTimeoutDelay(iPollingInterval * 1000));
|
|
1345
|
+
};
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Step 6. Polling
|
|
1349
|
+
*/
|
|
1350
|
+
this._activatePolling = function () {
|
|
1351
|
+
const iPollingInterval = oServiceConfig.pollingIntervalInSeconds || I_DEFAULT_POLLING_INTERVAL;
|
|
1352
|
+
|
|
1353
|
+
oCurrentMode = oModesEnum.POLLING;
|
|
1354
|
+
this._readNotificationsData(true);
|
|
1355
|
+
// Call again after a delay
|
|
1356
|
+
window.clearTimeout(pollingTimer);
|
|
1357
|
+
pollingTimer = window.setTimeout(this._activatePolling.bind(this, iPollingInterval, false), ushellUtils.sanitizeTimeoutDelay(iPollingInterval * 1000));
|
|
1358
|
+
};
|
|
1359
|
+
|
|
1360
|
+
this._formatAsDate = function (sUnformatted) {
|
|
1361
|
+
return new Date(sUnformatted);
|
|
1362
|
+
};
|
|
1363
|
+
|
|
1364
|
+
this._notificationAlert = function (results) {
|
|
1365
|
+
// If alerts/banners for HIGH priority notifications are disabled by the user - then return
|
|
1366
|
+
if (bHighPriorityBannerEnabled === false) {
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
const aNewNotifications = [];
|
|
1371
|
+
let nextLastNotificationDate = 0;
|
|
1372
|
+
|
|
1373
|
+
for (const oNotification in results) {
|
|
1374
|
+
if (this.lastNotificationDate && this._formatAsDate(results[oNotification].CreatedAt) > this.lastNotificationDate) {
|
|
1375
|
+
if (results[oNotification].Priority === "HIGH") {
|
|
1376
|
+
aNewNotifications.push(results[oNotification]);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
// get the last notification date
|
|
1380
|
+
if (nextLastNotificationDate < this._formatAsDate(results[oNotification].CreatedAt)) {
|
|
1381
|
+
nextLastNotificationDate = this._formatAsDate(results[oNotification].CreatedAt);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
if (this.lastNotificationDate && aNewNotifications.length > 0) {
|
|
1385
|
+
Core.getEventBus().publish("sap.ushell.services.Notifications", "onNewNotifications", aNewNotifications);
|
|
1386
|
+
}
|
|
1387
|
+
this.lastNotificationDate = nextLastNotificationDate;
|
|
1388
|
+
};
|
|
1389
|
+
|
|
1390
|
+
/**
|
|
1391
|
+
* Returning the time, in milliseconds, left until the end of FioriClient waiting period.
|
|
1392
|
+
* The required period is represented by tFioriClientInitializationPeriod, and we reduce the time passed from service initialization until now
|
|
1393
|
+
* @returns {int} Remaining delay
|
|
1394
|
+
*/
|
|
1395
|
+
this._getFioriClientRemainingDelay = function () {
|
|
1396
|
+
return tFioriClientInitializationPeriod - (new Date() - tInitializationTimestamp);
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
/**
|
|
1400
|
+
* Establishing a WebSocket connection for push updates
|
|
1401
|
+
*/
|
|
1402
|
+
this._establishWebSocketConnection = function () {
|
|
1403
|
+
const oNotificationsService = this;
|
|
1404
|
+
let bDeliberateClose = false;
|
|
1405
|
+
|
|
1406
|
+
try {
|
|
1407
|
+
// Init WebSocket connection
|
|
1408
|
+
oWebSocket = this._getWebSocketObjectObject(oServiceConfig.webSocketUrl || S_DEFAULT_WEBSOCKET_URL, [SapPcpWebSocket.SUPPORTED_PROTOCOLS.v10]);
|
|
1409
|
+
|
|
1410
|
+
oWebSocket.attachMessage(this, function (oMessage/*, oData*/) {
|
|
1411
|
+
const oPcpFields = oMessage.getParameter("pcpFields");
|
|
1412
|
+
if ((oPcpFields) && (oPcpFields.Command) && (oPcpFields.Command === "Notification")) {
|
|
1413
|
+
// Receive "pings" for Notification EntitySet
|
|
1414
|
+
// Another optional "ping" would be oPcpFields.Command === "Badge" for new Badge Number, but is currently not supported.
|
|
1415
|
+
oNotificationsService._readNotificationsData(true);
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
oWebSocket.attachOpen(this, function () {
|
|
1420
|
+
oNotificationsService._checkWebSocketActivity().then((bIsActive) => {
|
|
1421
|
+
// In case when bIsActive is false, the webSocket is not active although the connection is opened.
|
|
1422
|
+
// in this case we should close the WebSocket connection and switch to polling step.
|
|
1423
|
+
if (!bIsActive) {
|
|
1424
|
+
bDeliberateClose = true;
|
|
1425
|
+
oWebSocket.close();
|
|
1426
|
+
oNotificationsService._activatePollingAfterInterval();
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
Log.info("Notifications UShell service WebSocket: webSocket connection opened");
|
|
1430
|
+
});
|
|
1431
|
+
|
|
1432
|
+
oWebSocket.attachClose(this, function (oEvent) {
|
|
1433
|
+
Log.warning("Notifications UShell service WebSocket: attachClose called with code: " + oEvent.mParameters.code + " and reason: " + oEvent.mParameters.reason);
|
|
1434
|
+
if ((!bOnServiceStop) && (!bDeliberateClose)) {
|
|
1435
|
+
oNotificationsService._webSocketRecoveryStep();
|
|
1436
|
+
}
|
|
1437
|
+
});
|
|
1438
|
+
|
|
1439
|
+
// attachError is not being handled since each attachError is followed by a call to attachClose (...which includes handling)
|
|
1440
|
+
oWebSocket.attachError(this, function () {
|
|
1441
|
+
Log.warning("Notifications UShell service WebSocket: attachError called!");
|
|
1442
|
+
});
|
|
1443
|
+
} catch (e) {
|
|
1444
|
+
Log.error("Exception occurred while creating new sap.ui.core.ws.SapPcpWebSocket. Message: " + e.message);
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
|
|
1448
|
+
// *********************** Handle Notifications consumption / modes - End **************************
|
|
1449
|
+
// *************************************************************************************************
|
|
1450
|
+
|
|
1451
|
+
// *************************************************************************************************
|
|
1452
|
+
// **************** Helper functions for Fiori client and PackagedApp mode - Begin *****************
|
|
1453
|
+
|
|
1454
|
+
this._isFioriClientMode = function () {
|
|
1455
|
+
return !(sap.FioriClient === undefined);
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* Helper function for Packaged App mode
|
|
1460
|
+
*/
|
|
1461
|
+
this._isPackagedMode = function () {
|
|
1462
|
+
return (window.fiori_client_appConfig && window.fiori_client_appConfig.prepackaged === true);
|
|
1463
|
+
};
|
|
1464
|
+
|
|
1465
|
+
this._setNativeIconBadge = function (iBadgeValue) {
|
|
1466
|
+
if (sap.Push && sap.Push.setBadgeNumber) {
|
|
1467
|
+
sap.Push.setBadgeNumber(iBadgeValue, () => { });
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
|
|
1471
|
+
this._setNativeIconBadgeWithDelay = function () {
|
|
1472
|
+
setTimeout(function () {
|
|
1473
|
+
this.getUnseenNotificationsCount().then(function (iBadgeValue) {
|
|
1474
|
+
this._setNativeIconBadge(iBadgeValue);
|
|
1475
|
+
}.bind(this))
|
|
1476
|
+
.catch(() => { });
|
|
1477
|
+
}.bind(this), 4000);
|
|
1478
|
+
};
|
|
1479
|
+
|
|
1480
|
+
this._getIntentsFromConfiguration = function (aInput) {
|
|
1481
|
+
const aTempConsumedIntents = [];
|
|
1482
|
+
if (aInput && aInput.length > 0) {
|
|
1483
|
+
let sTempIntent;
|
|
1484
|
+
|
|
1485
|
+
for (let index = 0; index < aInput.length; index++) {
|
|
1486
|
+
sTempIntent = aInput[index].intent;
|
|
1487
|
+
aTempConsumedIntents.push(sTempIntent);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
return aTempConsumedIntents;
|
|
1491
|
+
};
|
|
1492
|
+
|
|
1493
|
+
this._handlePushedNotification = function (oNotificationData) {
|
|
1494
|
+
let sSemanticObject;
|
|
1495
|
+
let sAction;
|
|
1496
|
+
let oParameters;
|
|
1497
|
+
let aParameters = [];
|
|
1498
|
+
|
|
1499
|
+
if (oNotificationData !== undefined) {
|
|
1500
|
+
// Either oNotificationData.additionalData is not defined
|
|
1501
|
+
// OR oNotificationData.additionalData has the value "true" (foreground use-case)
|
|
1502
|
+
if ((oNotificationData.additionalData === undefined) || (oNotificationData.additionalData.foreground === true)) {
|
|
1503
|
+
// The given notification object is ignored, and we relate to this use-case as a "ping",
|
|
1504
|
+
// telling us that notifications data (in the Notification Center) was changed, hence the call to _readNotificationsData
|
|
1505
|
+
this._readNotificationsData(true);
|
|
1506
|
+
|
|
1507
|
+
// Background use-case (oNotificationData.additionalData is defined and equals "false")
|
|
1508
|
+
} else {
|
|
1509
|
+
// Read the semantic object, the action and the navigation parameters from the additionalData part of the notification,
|
|
1510
|
+
// or as a fallback - from the notification item's data
|
|
1511
|
+
|
|
1512
|
+
if (oNotificationData.additionalData && oNotificationData.additionalData.NavigationTargetObject) {
|
|
1513
|
+
sSemanticObject = oNotificationData.additionalData.NavigationTargetObject;
|
|
1514
|
+
} else {
|
|
1515
|
+
sSemanticObject = oNotificationData.NavigationTargetObject;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
if (oNotificationData.additionalData && oNotificationData.additionalData.NavigationTargetAction) {
|
|
1519
|
+
sAction = oNotificationData.additionalData.NavigationTargetAction;
|
|
1520
|
+
} else {
|
|
1521
|
+
sAction = oNotificationData.NavigationTargetAction;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
if (oNotificationData.additionalData && oNotificationData.additionalData.NavigationTargetParam) {
|
|
1525
|
+
oParameters = oNotificationData.additionalData.NavigationTargetParam;
|
|
1526
|
+
} else {
|
|
1527
|
+
oParameters = oNotificationData.NavigationTargetParam;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
if (oParameters) {
|
|
1531
|
+
if (typeof oParameters === "string" || oParameters instanceof String) {
|
|
1532
|
+
aParameters[0] = oParameters;
|
|
1533
|
+
} else if (Array.isArray(oParameters) === true) {
|
|
1534
|
+
aParameters = oParameters;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
const sNotificationId = oNotificationData.NotificationId;
|
|
1539
|
+
|
|
1540
|
+
if (sSemanticObject && sAction) {
|
|
1541
|
+
// Perform a navigation action according to the pushed notification's intent
|
|
1542
|
+
ushellUtils.toExternalWithParameters(sSemanticObject, sAction, aParameters);
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
this.markRead(sNotificationId);
|
|
1546
|
+
|
|
1547
|
+
this._readNotificationsData(true);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
};
|
|
1551
|
+
|
|
1552
|
+
this._registerForPush = function () {
|
|
1553
|
+
if (sap.Push) {
|
|
1554
|
+
sap.Push.initPush(this._handlePushedNotification.bind(this));
|
|
1555
|
+
}
|
|
1556
|
+
};
|
|
1557
|
+
|
|
1558
|
+
/**
|
|
1559
|
+
* For Fiori Client use case on mobile platform.
|
|
1560
|
+
* This function registers the callback this._handlePushedNotification for the deviceready event
|
|
1561
|
+
*/
|
|
1562
|
+
this._addPushNotificationHandler = function () {
|
|
1563
|
+
document.addEventListener("deviceready", this._registerForPush.bind(this), false);
|
|
1564
|
+
};
|
|
1565
|
+
|
|
1566
|
+
this._isIntentBasedConsumption = function () {
|
|
1567
|
+
return bIntentBasedConsumption;
|
|
1568
|
+
};
|
|
1569
|
+
|
|
1570
|
+
/**
|
|
1571
|
+
* Creates and returns the intents filter string of an OData request
|
|
1572
|
+
* For example: &NavigationIntent%20eq%20%27Action-toappstatesample%27%20or%20NavigationIntent%20eq%20%27Action-toappnavsample%27
|
|
1573
|
+
*/
|
|
1574
|
+
this._getConsumedIntents = function (oRequestURI) {
|
|
1575
|
+
let sConsumedIntents = "";
|
|
1576
|
+
|
|
1577
|
+
if (!this._isIntentBasedConsumption()) {
|
|
1578
|
+
return sConsumedIntents;
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
if (aConsumedIntents.length > 0) {
|
|
1582
|
+
// If it is not GetBadgeNumber use-case then the intents filter string should start with "&"
|
|
1583
|
+
if (oRequestURI !== oOperationEnum.GET_BADGE_NUMBER) {
|
|
1584
|
+
sConsumedIntents = "&";
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
for (let index = 0; index < aConsumedIntents.length; index++) {
|
|
1588
|
+
// If it is GetBadgeNumber use case then the intent are comma separated
|
|
1589
|
+
if (oRequestURI === oOperationEnum.GET_BADGE_NUMBER) {
|
|
1590
|
+
if (index === 0) {
|
|
1591
|
+
sConsumedIntents = aConsumedIntents[index];
|
|
1592
|
+
} else {
|
|
1593
|
+
sConsumedIntents = sConsumedIntents + "," + aConsumedIntents[index];
|
|
1594
|
+
}
|
|
1595
|
+
} else {
|
|
1596
|
+
sConsumedIntents = sConsumedIntents + "NavigationIntent%20eq%20%27" + aConsumedIntents[index] + "%27";
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
return sConsumedIntents;
|
|
1601
|
+
};
|
|
1602
|
+
|
|
1603
|
+
this._revalidateCsrfToken = function () {
|
|
1604
|
+
sHeaderXcsrfToken = undefined;
|
|
1605
|
+
bCsrfDataSet = false;
|
|
1606
|
+
|
|
1607
|
+
return this.getNotificationsBufferBySortingType(oOperationEnum.NOTIFICATIONS_BY_DATE_DESCENDING, 0, 1);
|
|
1608
|
+
};
|
|
1609
|
+
|
|
1610
|
+
this._csrfTokenInvalid = function (oMessage) {
|
|
1611
|
+
const oResponse = oMessage.response;
|
|
1612
|
+
const bAuthorizationError = oResponse && oResponse.statusCode === 403;
|
|
1613
|
+
const sCSRFTokenHeader = oResponse ? oResponse.headers["x-csrf-token"] : "";
|
|
1614
|
+
// There have been instances of services returning "Required" as well as "required",
|
|
1615
|
+
// therefore the method toLowerCase is used.
|
|
1616
|
+
const bCSRFTokenRequired = sCSRFTokenHeader.toLowerCase() === "required";
|
|
1617
|
+
return bAuthorizationError && bCSRFTokenRequired;
|
|
1618
|
+
};
|
|
1619
|
+
|
|
1620
|
+
/**
|
|
1621
|
+
* Called in case that the CSRF token becomes invalid during the session.
|
|
1622
|
+
*
|
|
1623
|
+
* This problem (i.e., invalid CSRF token) is found when a POST oData call fails (e.g, markRead).
|
|
1624
|
+
* in such a case this function is called in order to perform the recovery flow.
|
|
1625
|
+
*
|
|
1626
|
+
* The recovery flow includes two main steps:
|
|
1627
|
+
* 1. Obtaining the new/valid CSRF token from the notification channel
|
|
1628
|
+
* 2. Calling the function that failed (with the same parameters)
|
|
1629
|
+
* 3. resolving/rejecting the deferred object of the first function call (the one that failed because the token became invalid) in order to continue with the original flow
|
|
1630
|
+
*
|
|
1631
|
+
* This function doesn't return anything, instead it calls the provided resolve or reject callbacks
|
|
1632
|
+
*
|
|
1633
|
+
* @private
|
|
1634
|
+
*/
|
|
1635
|
+
this._invalidCsrfTokenRecovery = function (resolve, reject, fnFailedFunction, aArgsArray) {
|
|
1636
|
+
const oNotificationsService = this;
|
|
1637
|
+
|
|
1638
|
+
bInvalidCsrfTokenRecoveryMode = true;
|
|
1639
|
+
|
|
1640
|
+
// Getting the new/valid CSRF token
|
|
1641
|
+
this._revalidateCsrfToken().then(() => {
|
|
1642
|
+
// Call the failed function (with the same parameters)
|
|
1643
|
+
fnFailedFunction.apply(oNotificationsService, aArgsArray)
|
|
1644
|
+
.then(resolve)
|
|
1645
|
+
.catch((e) => {
|
|
1646
|
+
if (e.response && e.response.statusCode === 200 && e.response.body) {
|
|
1647
|
+
resolve(e.response.body);
|
|
1648
|
+
} else {
|
|
1649
|
+
reject(e);
|
|
1650
|
+
}
|
|
1651
|
+
})
|
|
1652
|
+
.finally(() => {
|
|
1653
|
+
bInvalidCsrfTokenRecoveryMode = false;
|
|
1654
|
+
});
|
|
1655
|
+
}).catch((e) => {
|
|
1656
|
+
bInvalidCsrfTokenRecoveryMode = false;
|
|
1657
|
+
Log.error("Notification service - oData markRead failed: ", e.message, "sap.ushell.services.NotificationsV2");
|
|
1658
|
+
reject(e);
|
|
1659
|
+
});
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
// **************** Helper functions for Fiori client and PackagedApp mode - End *****************
|
|
1663
|
+
// ***********************************************************************************************
|
|
1664
|
+
|
|
1665
|
+
this._notificationsAscendingSortBy = function (aNotifications, sPropertyToSortBy) {
|
|
1666
|
+
aNotifications.sort((x, y) => {
|
|
1667
|
+
let val1 = x[sPropertyToSortBy];
|
|
1668
|
+
let val2 = y[sPropertyToSortBy];
|
|
1669
|
+
|
|
1670
|
+
if (val1 === val2) {
|
|
1671
|
+
val1 = x.id;
|
|
1672
|
+
val2 = y.id;
|
|
1673
|
+
}
|
|
1674
|
+
return val2 > val1 ? -1 : 1;
|
|
1675
|
+
});
|
|
1676
|
+
return aNotifications;
|
|
1677
|
+
};
|
|
1678
|
+
|
|
1679
|
+
this._getWebSocketObjectObject = function (sWebSocketUrl, aVersionProtocol) {
|
|
1680
|
+
return new SapPcpWebSocket(sWebSocketUrl, aVersionProtocol);
|
|
1681
|
+
};
|
|
1682
|
+
|
|
1683
|
+
this.getOperationEnum = function () {
|
|
1684
|
+
return oOperationEnum;
|
|
1685
|
+
};
|
|
1686
|
+
|
|
1687
|
+
/**
|
|
1688
|
+
* Read user settings flags from the personalization and update the variable bHighPriorityBannerEnabled.
|
|
1689
|
+
* If the data does not yet exists in the personalization,
|
|
1690
|
+
* write the default value of bHighPriorityBannerEnabled to the personalization
|
|
1691
|
+
*/
|
|
1692
|
+
this._readUserSettingsFlagsFromPersonalization = function () {
|
|
1693
|
+
const oNotificationsService = this;
|
|
1694
|
+
this._getUserSettingsPersonalizer()
|
|
1695
|
+
.then((oPersonalizer) => {
|
|
1696
|
+
oPersonalizer.getPersData()
|
|
1697
|
+
.then((oFlagsData) => {
|
|
1698
|
+
if (oFlagsData === undefined) {
|
|
1699
|
+
oNotificationsService._writeUserSettingsFlagsToPersonalization({
|
|
1700
|
+
highPriorityBannerEnabled: bHighPriorityBannerEnabled
|
|
1701
|
+
});
|
|
1702
|
+
} else {
|
|
1703
|
+
bHighPriorityBannerEnabled = oFlagsData.highPriorityBannerEnabled;
|
|
1704
|
+
}
|
|
1705
|
+
oUserFlagsReadFromPersonalizationDeferred.resolve();
|
|
1706
|
+
})
|
|
1707
|
+
.catch(() => {
|
|
1708
|
+
Log.error("Reading User Settings flags from Personalization service failed");
|
|
1709
|
+
});
|
|
1710
|
+
})
|
|
1711
|
+
.catch((error) => {
|
|
1712
|
+
Log.error("Personalization service does not work:");
|
|
1713
|
+
Log.error(error.name + ": " + error.message);
|
|
1714
|
+
Log.error("Reading User Settings flags from Personalization service failed");
|
|
1715
|
+
});
|
|
1716
|
+
};
|
|
1717
|
+
|
|
1718
|
+
/**
|
|
1719
|
+
* Write/save user settings flags to the personalization.
|
|
1720
|
+
* The saved data consists of the user's show high-priority notifications alerts flag value.
|
|
1721
|
+
*/
|
|
1722
|
+
this._writeUserSettingsFlagsToPersonalization = function (oFlags) {
|
|
1723
|
+
return this._getUserSettingsPersonalizer()
|
|
1724
|
+
.then((oPersonalizer) => oPersonalizer.setPersData(oFlags))
|
|
1725
|
+
.catch((error) => {
|
|
1726
|
+
Log.error("Personalization service does not work:");
|
|
1727
|
+
Log.error(error.name + ": " + error.message);
|
|
1728
|
+
});
|
|
1729
|
+
};
|
|
1730
|
+
|
|
1731
|
+
this._getUserSettingsPersonalizer = function () {
|
|
1732
|
+
if (!this.oUserSettingsPersonalizerPromise) {
|
|
1733
|
+
this.oUserSettingsPersonalizerPromise = sap.ushell.Container.getServiceAsync("PersonalizationV2")
|
|
1734
|
+
.then((PersonalizationService) => {
|
|
1735
|
+
const oScope = {
|
|
1736
|
+
keyCategory: PersonalizationService.constants.keyCategory.FIXED_KEY,
|
|
1737
|
+
writeFrequency: PersonalizationService.constants.writeFrequency.LOW,
|
|
1738
|
+
clientStorageAllowed: true
|
|
1739
|
+
};
|
|
1740
|
+
|
|
1741
|
+
const oPersId = {
|
|
1742
|
+
container: "sap.ushell.services.Notifications",
|
|
1743
|
+
item: "userSettingsData"
|
|
1744
|
+
};
|
|
1745
|
+
|
|
1746
|
+
return PersonalizationService.getPersonalizer(oPersId, oScope);
|
|
1747
|
+
});
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
return this.oUserSettingsPersonalizerPromise;
|
|
1751
|
+
};
|
|
1752
|
+
|
|
1753
|
+
this._updateCSRF = function (oResponseData) {
|
|
1754
|
+
if ((bCsrfDataSet === true) || (oResponseData.headers === undefined)) {
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1757
|
+
if (!this._getHeaderXcsrfToken()) {
|
|
1758
|
+
sHeaderXcsrfToken = oResponseData.headers["x-csrf-token"] || oResponseData.headers["X-CSRF-Token"] || oResponseData.headers["X-Csrf-Token"];
|
|
1759
|
+
}
|
|
1760
|
+
if (!this._getDataServiceVersion()) {
|
|
1761
|
+
sDataServiceVersion = oResponseData.headers.DataServiceVersion || oResponseData.headers["odata-version"];
|
|
1762
|
+
}
|
|
1763
|
+
bCsrfDataSet = true;
|
|
1764
|
+
};
|
|
1765
|
+
|
|
1766
|
+
/**
|
|
1767
|
+
* Handles all the required steps in order to initialize Notification Settings UI
|
|
1768
|
+
*
|
|
1769
|
+
* Issues two calls to the Notifications channel backend system in order to check whether settings feature and Push to Mobile features are supported
|
|
1770
|
+
*/
|
|
1771
|
+
this._userSettingInitialization = function () {
|
|
1772
|
+
// Contains three boolean flags:
|
|
1773
|
+
// - settingsAvailable: Is the settings feature supported by the notification channel backend system
|
|
1774
|
+
// - mobileAvailable: Is the "push to mobile" feature supported by the notification channel backend system
|
|
1775
|
+
// - emailAvailable: Is the "send email" feature supported by the notification channel backend system
|
|
1776
|
+
const oSettingsStatus = {
|
|
1777
|
+
settingsAvailable: false,
|
|
1778
|
+
mobileAvailable: false,
|
|
1779
|
+
emailAvailable: false
|
|
1780
|
+
};
|
|
1781
|
+
|
|
1782
|
+
// Read the part of user settings data that is kept in personalization service
|
|
1783
|
+
this._readUserSettingsFlagsFromPersonalization();
|
|
1784
|
+
|
|
1785
|
+
// 1st asynchronous call: Get setting data from the backend, for the purpose of verifying that the feature is supported
|
|
1786
|
+
const oSettingsPromise = this.readSettings();
|
|
1787
|
+
// 2nd asynchronous call: verify Push To Mobile capability
|
|
1788
|
+
const oMobileSettingsPromise = this._readMobileSettingsFromServer();
|
|
1789
|
+
const oEmailSettingsPromise = this._readEmailSettingsFromServer();
|
|
1790
|
+
|
|
1791
|
+
const aPromises = [oSettingsPromise, oMobileSettingsPromise, oEmailSettingsPromise];
|
|
1792
|
+
|
|
1793
|
+
oSettingsPromise.then(() => {
|
|
1794
|
+
// Notification setting supported
|
|
1795
|
+
oSettingsStatus.settingsAvailable = true;
|
|
1796
|
+
}).catch(() => {
|
|
1797
|
+
Log.warning("User settings for the Notification service are not available.");
|
|
1798
|
+
oNotificationSettingsAvailabilityDeferred.promise().catch(() => { });
|
|
1799
|
+
oNotificationSettingsAvailabilityDeferred.reject();
|
|
1800
|
+
});
|
|
1801
|
+
|
|
1802
|
+
oMobileSettingsPromise.then((oResult) => {
|
|
1803
|
+
const oResponseObject = JSON.parse(oResult);
|
|
1804
|
+
// Push to Mobile validation returned
|
|
1805
|
+
if (oResponseObject.successStatus) {
|
|
1806
|
+
bNotificationSettingsMobileSupport = oResult ? oResponseObject.IsActive : false;
|
|
1807
|
+
oSettingsStatus.mobileAvailable = bNotificationSettingsMobileSupport;
|
|
1808
|
+
} else {
|
|
1809
|
+
bNotificationSettingsMobileSupport = false;
|
|
1810
|
+
oSettingsStatus.mobileAvailable = false;
|
|
1811
|
+
}
|
|
1812
|
+
}).catch(() => {
|
|
1813
|
+
Log.warning("Mobile settings for the Notification service are not available.");
|
|
1814
|
+
bNotificationSettingsMobileSupport = false;
|
|
1815
|
+
oSettingsStatus.mobileAvailable = false;
|
|
1816
|
+
});
|
|
1817
|
+
|
|
1818
|
+
oEmailSettingsPromise.then((oResult) => {
|
|
1819
|
+
const oResponseObject = JSON.parse(oResult);
|
|
1820
|
+
if (oResponseObject.successStatus) {
|
|
1821
|
+
bNotificationSettingsEmailSupport = oResult ? oResponseObject.IsActive : false;
|
|
1822
|
+
oSettingsStatus.emailAvailable = bNotificationSettingsEmailSupport;
|
|
1823
|
+
} else {
|
|
1824
|
+
bNotificationSettingsEmailSupport = false;
|
|
1825
|
+
oSettingsStatus.emailAvailable = false;
|
|
1826
|
+
}
|
|
1827
|
+
}).catch(() => {
|
|
1828
|
+
Log.warning("Email settings for the Notification service are not available.");
|
|
1829
|
+
bNotificationSettingsEmailSupport = false;
|
|
1830
|
+
oSettingsStatus.emailAvailable = false;
|
|
1831
|
+
});
|
|
1832
|
+
|
|
1833
|
+
// Resolve the deferred object on which the setting UI depends after the two OData calls returned, no matter if they were successful or not
|
|
1834
|
+
Promise.all(aPromises).then(() => {
|
|
1835
|
+
// After both calls returned - the deferred object (on which the rendering of Notification Settings UI depends) is resolved
|
|
1836
|
+
oNotificationSettingsAvailabilityDeferred.resolve(oSettingsStatus);
|
|
1837
|
+
}).catch(() => Log.warning("Settings for the Notification service are not loaded completely."));
|
|
1838
|
+
};
|
|
1839
|
+
|
|
1840
|
+
/**
|
|
1841
|
+
* Used to close all notification connection. In order to resume connection use _resumeConnection method
|
|
1842
|
+
* @private
|
|
1843
|
+
*/
|
|
1844
|
+
this._closeConnection = function () {
|
|
1845
|
+
if (!bOnServiceStop) {
|
|
1846
|
+
if (oCurrentMode === oModesEnum.WEB_SOCKET && oWebSocket) {
|
|
1847
|
+
oWebSocket.close();
|
|
1848
|
+
bOnServiceStop = true;
|
|
1849
|
+
}
|
|
1850
|
+
if (oCurrentMode === oModesEnum.POLLING && pollingTimer) {
|
|
1851
|
+
window.clearTimeout(pollingTimer);
|
|
1852
|
+
bOnServiceStop = true;
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1856
|
+
|
|
1857
|
+
/**
|
|
1858
|
+
* Used to open closed notification connection. Firstly, try to re-establish the websocket connection.
|
|
1859
|
+
* If the websocket connection can not be established, the polling start automatically after failed attempt
|
|
1860
|
+
* @private
|
|
1861
|
+
*/
|
|
1862
|
+
this._resumeConnection = function () {
|
|
1863
|
+
if (bOnServiceStop) {
|
|
1864
|
+
bOnServiceStop = false;
|
|
1865
|
+
this._webSocketStep();
|
|
1866
|
+
}
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
Notifications.hasNoAdapter = true;
|
|
1871
|
+
return Notifications;
|
|
1872
|
+
}, true /* bExport */);
|