-
Notifications
You must be signed in to change notification settings - Fork 14
[OGUI-1854] Notify user via native browser notification when a new run has started #3258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
fa667bc
033aeb8
ac82b0e
591fb80
4abdbfa
caf1e3f
22d4ca0
669f350
05d4d6a
f0ff74b
34331ae
db1b8f2
f2475f2
89d648b
af57099
03d1080
3ba3362
c1655dc
3f6a5f9
286b31c
5d82e3d
d1f0aa2
6076a27
2ffef7d
c4e4ec3
cc0fabd
0243bff
ba1fbd4
37ddd34
866f953
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,7 @@ | |
| * or submit itself to any jurisdiction. | ||
| */ | ||
|
|
||
| import { LogManager } from '@aliceo2/web-ui'; | ||
| import { LogManager, WebSocketMessage } from '@aliceo2/web-ui'; | ||
| import { EmitterKeys } from '../../common/library/enums/emitterKeys.enum.js'; | ||
| import { Transition } from '../../common/library/enums/transition.enum.js'; | ||
| import { RunStatus } from '../../common/library/runStatus.enum.js'; | ||
|
|
@@ -23,22 +23,25 @@ | |
| * A service that fetches information about runs and their status. | ||
| */ | ||
| export class RunModeService { | ||
| /** | ||
|
Check warning on line 26 in QualityControl/lib/services/RunModeService.js
|
||
| * Creates a new RunModeService to fetch objects paths and their associated run status | ||
| * @param {object} config - Configuration defined as `bookkeeping` in the config file. | ||
| * @param {BookkeepingService} bookkeepingService - Used to check the status of a run. | ||
| * @param {CcdbService} dataService - Used to fetch data from the CCDB. | ||
| * @param {EventEmitter} eventEmitter - Event emitter to be used to emit events when new data is available | ||
| * @param {WebSocket} ws - web-ui websocket server implementation | ||
|
Check warning on line 32 in QualityControl/lib/services/RunModeService.js
|
||
| */ | ||
| constructor( | ||
| config, | ||
| bookkeepingService, | ||
| dataService, | ||
| eventEmitter, | ||
| webSocketService, | ||
| ) { | ||
| this._bookkeepingService = bookkeepingService; | ||
| this._dataService = dataService; | ||
| this._eventEmitter = eventEmitter; | ||
| this._webSocketService = webSocketService; | ||
|
|
||
| this._ongoingRuns = new Map(); | ||
| this._lastRunsRefresh = 0; | ||
|
|
@@ -131,6 +134,13 @@ | |
| this._logger.errorMessage(`Error fetching initial paths for run ${runNumber}: ${error.message || error}`); | ||
| } | ||
| this._ongoingRuns.set(runNumber, rawPaths); | ||
|
|
||
| const wsMessage = new WebSocketMessage(); | ||
| wsMessage.command = `${EmitterKeys.RUN_TRACK}:${Transition.START_ACTIVITY}`; | ||
| wsMessage.payload = { | ||
| runNumber, | ||
| }; | ||
| this._webSocketService.broadcast(wsMessage); | ||
| } else if (transition === Transition.STOP_ACTIVITY) { | ||
| this._ongoingRuns.delete(runNumber); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2019-2020 CERN and copyright holders of ALICE O2. | ||
| * See http://alice-o2.web.cern.ch/copyright for details of the copyright holders. | ||
| * All rights not expressly granted are reserved. | ||
| * | ||
| * This software is distributed under the terms of the GNU General Public | ||
| * License v3 (GPL Version 3), copied verbatim in the file "COPYING". | ||
| * | ||
| * In applying this license CERN does not waive the privileges and immunities | ||
| * granted to it by virtue of its status as an Intergovernmental Organization | ||
| * or submit itself to any jurisdiction. | ||
| */ | ||
|
|
||
| import { Observable, BrowserStorage, showNativeBrowserNotification } from '/js/src/index.js'; | ||
| import { EmitterKeys } from '../../../../library/enums/emitterKeys.enum.js'; | ||
| import { StorageKeysEnum } from '../../enums/storageKeys.enum.js'; | ||
| import { Transition } from '../../../../library/enums/transition.enum.js'; | ||
| import {areBrowserNotificationsGranted} from "@aliceo2/web-ui/Frontend/js/src/index.js"; | ||
|
Check failure on line 19 in QualityControl/public/common/notifications/model/NotificationRunStartModel.js
|
||
|
|
||
| /** | ||
| * Model responsible for handling browser notifications when a new run starts. | ||
| */ | ||
| export default class NotificationRunStartModel extends Observable { | ||
| /** | ||
| * Initialize with empty values | ||
| * @param {Model} model - root model of the application | ||
| */ | ||
| constructor(model) { | ||
| super(); | ||
|
|
||
| this.model = model; | ||
| this._browserNotificationStorage = new BrowserStorage(StorageKeysEnum.NOTIFICATION_START_RUN_SETTING); | ||
|
|
||
| this.model.ws.addListener('command', (message) => { | ||
| if (message.command === EmitterKeys.RUN_TRACK) { | ||
| this._handleWSRunTrack.bind(this, message.payload); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Returns whether browser notifications for run start events | ||
| * are enabled for the current user. | ||
| * @returns {boolean} `true` if notifications are enabled, `false` otherwise. | ||
| */ | ||
| async getBrowserNotificationSetting() { | ||
| try { | ||
| if (this._browserNotificationStorage.getLocalItem(this.model.session.personid.toString())) { | ||
| return areBrowserNotificationsGranted(); | ||
| } | ||
| return false; | ||
| } catch { | ||
| this._browserNotificationStorage.removeLocalItem(this.model.session.personid.toString()); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Persists the browser notification preference for the current user | ||
| * and notifies all observers. | ||
| * @param {boolean} enabled - Whether notifications should be enabled. | ||
| * @returns {undefined} | ||
| */ | ||
| setBrowserNotificationSetting(enabled) { | ||
| this._browserNotificationStorage.setLocalItem(this.model.session.personid.toString(), enabled); | ||
| this.notify(); | ||
| } | ||
|
|
||
| /** | ||
| * Handles {@link EmitterKeys.RUN_TRACK} WebSocket events. | ||
| * A native browser notification is displayed only when: | ||
| * - The transition is {@link Transition.START_ACTIVITY} | ||
| * - The user has enabled notifications | ||
| * @param {object} payload - WebSocket payload. | ||
| * @param {number} payload.runNumber - Run number that started. | ||
| * @returns {undefined} | ||
| */ | ||
| async _handleWSRunTrack({ runNumber }) { | ||
| if (!this.getBrowserNotificationSetting()) { | ||
|
||
| return; | ||
| } | ||
|
|
||
| showNativeBrowserNotification({ | ||
| title: `RUN ${runNumber ?? 'unknown'} has started`, | ||
| onclick: () => { | ||
| // On notification click we always navigate to the `objectTree` page. | ||
| // Additionally, we view the run using the given `runNumber`. | ||
| this.model.router.go(`?page=objectTree&RunNumber=${runNumber}`); | ||
|
|
||
| // If RunMode is not activated, we should enable it | ||
| const { isRunModeActivated } = this.model.filterModel; | ||
| if (!isRunModeActivated) { | ||
| this.model.filterModel.activateRunsMode(this.model.filterModel.getPageTargetModel()); | ||
| } | ||
|
|
||
| // We select the given `runNumber` in RunMode. | ||
| // We do not have to set the parameter in the URL, as this is already achieved on navigation. | ||
| this.model.filterModel.setFilterValue('RunNumber', runNumber?.toString()); | ||
| }, | ||
| }); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.