From 62a813bbba23b558bb96dde2ad1a2502b8c04111 Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Sun, 24 Oct 2021 22:26:23 +0530 Subject: [PATCH 1/9] Refactor Join Form --- simplq/src/api/requestFactory/token.js | 3 +- .../src/components/pages/Admin/AddMember.jsx | 17 +-- simplq/src/components/pages/Join/JoinForm.jsx | 105 +++++++++++------- simplq/src/components/pages/Join/JoinPage.jsx | 32 +----- simplq/src/store/asyncActions/joinQueue.js | 4 +- 5 files changed, 70 insertions(+), 91 deletions(-) diff --git a/simplq/src/api/requestFactory/token.js b/simplq/src/api/requestFactory/token.js index f960b261..7f63939a 100644 --- a/simplq/src/api/requestFactory/token.js +++ b/simplq/src/api/requestFactory/token.js @@ -14,13 +14,12 @@ export const getUserTokens = () => ({ method: 'get', url: '/tokens' }); * @param {string} queueId * @returns {Object} request - partial axios request without baseURL */ -export const createToken = (name, contactNumber, notifiable, queueId, emailId) => ({ +export const createToken = (name, contactNumber, queueId, emailId) => ({ method: 'post', url: '/token', data: { name, contactNumber, - notifiable, queueId, emailId, }, diff --git a/simplq/src/components/pages/Admin/AddMember.jsx b/simplq/src/components/pages/Admin/AddMember.jsx index 5e0b5d7d..18b8fe10 100644 --- a/simplq/src/components/pages/Admin/AddMember.jsx +++ b/simplq/src/components/pages/Admin/AddMember.jsx @@ -2,19 +2,9 @@ import React from 'react'; import AddIcon from '@material-ui/icons/Add'; import JoinQueueForm from 'components/pages/Join/JoinForm'; import SidePanelItem from 'components/common/SidePanel/SidePanelItem'; -import { useDispatch } from 'react-redux'; -import { useJoinQueue } from 'store/asyncActions'; import styles from './admin.module.scss'; export default ({ queueId }) => { - const joinQueue = useJoinQueue(); - const dispatch = useDispatch(); - - const joinQueueHandler = (name, contactNumber) => { - dispatch(joinQueue({ name, contactNumber, notifiable: false, queueId, goToStatusPage: false })); - // Notifiable false since the user was added by the admin, so he/she might not have an open instance of the website - }; - return ( { tourTag="reactour__addMember" >
- +
); diff --git a/simplq/src/components/pages/Join/JoinForm.jsx b/simplq/src/components/pages/Join/JoinForm.jsx index 9330c5a4..d9677f35 100644 --- a/simplq/src/components/pages/Join/JoinForm.jsx +++ b/simplq/src/components/pages/Join/JoinForm.jsx @@ -1,5 +1,5 @@ -import React, { useState, useRef, useEffect } from 'react'; -import { useSelector } from 'react-redux'; +import React, { useState, useRef, useEffect, useCallback } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; import { handleEnterPress } from 'utils/eventHandling'; import InputField from 'components/common/InputField'; import PhoneInput from 'components/common/PhoneInput'; @@ -11,39 +11,63 @@ import Box from '@material-ui/core/Box'; import { Stepper } from '@material-ui/core'; import StepLabel from '@material-ui/core/StepLabel'; import Typography from '@material-ui/core/Typography'; +import { useJoinQueue } from 'store/asyncActions'; +import { useGetTokenByContactNumber } from 'store/asyncActions/getTokenByContactNumber'; import styles from './JoinForm.module.scss'; import Checkbox from '../../common/Checkbox/Checkbox'; import { selectQueueInfo } from '../../../store/queueInfo'; -export function JoinQueueForm(props) { +export function JoinQueueForm({ queueId, isAdminPage, buttonText }) { const [name, setName] = useState(''); const [invalidName, setInvalidName] = useState(false); - const [contact, setContact] = useState(''); - const [invalidContact, setInvalidContact] = useState(false); - const [email, setEmail] = useState(''); - const [invalidEmail, setInvalidEmail] = useState(false); + const [contactNumber, setContactNumber] = useState(''); + const [invalidContactNumber, setInvalidContactNumber] = useState(false); + const [emailId, setEmailId] = useState(''); + const [invalidEmailId, setInvalidEmailId] = useState(false); const joinQueueActionStatus = useSelector((state) => state.actionStatus['joinQueue']); const prevActionStatus = useRef(); const [activeStep, setActiveStep] = React.useState(0); const queueInfo = useSelector(selectQueueInfo); const [saveToLocalStorage, setSaveToLocalStorage] = useState(true); + const getTokenByContactNumber = useCallback(useGetTokenByContactNumber(), []); const { notifyByEmail } = useSelector(selectQueueInfo); const collectEmail = !!notifyByEmail; + const joinQueue = useJoinQueue(); + const dispatch = useDispatch(); + + const joinQueueHandler = () => { + dispatch( + joinQueue({ + name, + contactNumber, + queueId, + emailId: collectEmail ? emailId : undefined, + goToStatusPage: !isAdminPage, + }) + ); + }; + + const onSubmitGetToken = () => { + dispatch( + getTokenByContactNumber({ queueId, contactNumber, redirectToTokenPageOnSuccess: true }) + ); + }; + const handleNext = async () => { - if (invalidContact) return; - if (contact === '') { - setInvalidContact(true); + if (invalidContactNumber) return; + if (contactNumber === '') { + setInvalidContactNumber(true); return; } - // check if user is on queue page (pages/Admin/AddMember.jsx) where each step (contact + name) is necessary - if (props.queuePage) { + // check if user is on admin page (pages/Admin/AddMember.jsx) where each step (contact + name) is necessary + if (!isAdminPage) { setActiveStep((prevActiveStep) => prevActiveStep + 1); return; } - props.onSubmitGetToken(contact); + onSubmitGetToken(contactNumber); if (queueInfo.selfJoinAllowed) setActiveStep((prevActiveStep) => prevActiveStep + 1); }; @@ -54,9 +78,9 @@ export function JoinQueueForm(props) { useEffect(() => { // Reset form only after successful action if (prevActionStatus.current === 'pending' && joinQueueActionStatus === 'fulfilled') { - setContact(''); + setContactNumber(''); setName(''); - setEmail(''); + setEmailId(''); } // Set previous action status for next render @@ -71,10 +95,10 @@ export function JoinQueueForm(props) { setName(localStorageName); } if (localStorageContact) { - setContact(localStorageContact); + setContactNumber(localStorageContact); } if (localStorageEmail) { - setEmail(localStorageEmail); + setEmailId(localStorageEmail); } }, []); @@ -88,52 +112,52 @@ export function JoinQueueForm(props) { } function handleEmailChange(e) { - setEmail(e.target.value); + setEmailId(e.target.value); } const onSubmit = () => { - if (invalidContact || invalidName) return; + if (invalidContactNumber || invalidName) return; if (name === '') { setInvalidName(true); return; } - if (contact === '') { - setInvalidContact(true); + if (contactNumber === '') { + setInvalidContactNumber(true); return; } - if (collectEmail && email === '') { - setInvalidEmail(true); + if (collectEmail && emailId === '') { + setInvalidEmailId(true); return; } if (saveToLocalStorage) { - localStorage.setItem('contact', contact); + localStorage.setItem('contact', contactNumber); localStorage.setItem('name', name); - localStorage.setItem('email', email); + localStorage.setItem('email', emailId); } else { localStorage.removeItem('contact'); localStorage.removeItem('name'); localStorage.removeItem('email'); } - props.joinQueueHandler(name, contact, collectEmail ? email : undefined); + joinQueueHandler(); // reset to first step on queue page (pages/Admin/AddMember.jsx) - if (props.queuePage) setActiveStep(0); + if (isAdminPage) setActiveStep(0); }; const checkJoinDisabled = () => { return ( - invalidContact || + invalidContactNumber || invalidName || - contact === '' || + contactNumber === '' || name === '' || - (collectEmail && (email === '' || invalidEmail)) + (collectEmail && (emailId === '' || invalidEmailId)) ); }; const checkNextDisabled = () => { - return invalidContact || contact === ''; + return invalidContactNumber || contactNumber === ''; }; const steps = [ @@ -143,10 +167,10 @@ export function JoinQueueForm(props) { item: (
setContact(val)} + isValid={!invalidContactNumber} + setInvalidContact={setInvalidContactNumber} + contact={contactNumber} + onChange={(val) => setContactNumber(val)} onKeyDown={handleNext} />
@@ -172,11 +196,11 @@ export function JoinQueueForm(props) {
handleEnterPress(e, onSubmit)} onChange={handleEmailChange} - error={invalidEmail} - helperText={invalidEmail ? 'Enter a valid name' : ''} + error={invalidEmailId} + helperText={invalidEmailId ? 'Enter a valid name' : ''} />
) : null} @@ -191,8 +215,7 @@ export function JoinQueueForm(props) { Back ); - const isSubmitStep = - index === steps.length - 1 && (queueInfo.selfJoinAllowed || props.queuePage); + const isSubmitStep = index === steps.length - 1 && (queueInfo.selfJoinAllowed || isAdminPage); const boxContent = isSubmitStep ? ( <> - {props.buttonText} + {buttonText} diff --git a/simplq/src/components/pages/Join/JoinPage.jsx b/simplq/src/components/pages/Join/JoinPage.jsx index d8458337..8fce1f2b 100644 --- a/simplq/src/components/pages/Join/JoinPage.jsx +++ b/simplq/src/components/pages/Join/JoinPage.jsx @@ -1,12 +1,11 @@ import React, { useCallback, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useGetQueueInfoByName, useJoinQueue } from 'store/asyncActions'; +import { useGetQueueInfoByName } from 'store/asyncActions'; import { selectQueueInfo } from 'store/queueInfo'; import HeaderSection from 'components/common/HeaderSection'; import QueueInfo from 'components/common/QueueInfo'; import LoadingStatus from 'components/common/Loading'; import Button from 'components/common/Button'; -import { useGetTokenByContactNumber } from 'store/asyncActions/getTokenByContactNumber'; import JoinQueueForm from './JoinForm'; import styles from './JoinPage.module.scss'; import MyTokens from './MyTokens'; @@ -14,8 +13,6 @@ import MyTokens from './MyTokens'; export default ({ match }) => { const queueName = match.params.queueName; const getQueueInfoByName = useCallback(useGetQueueInfoByName(), []); - const getTokenByContactNumber = useCallback(useGetTokenByContactNumber(), []); - const joinQueue = useJoinQueue(); const dispatch = useDispatch(); const queueInfo = useSelector(selectQueueInfo); @@ -25,30 +22,10 @@ export default ({ match }) => { const queueId = queueInfo.queueId; - const joinQueueHandler = async (name1, contactNumber1, emailId1) => { - const queue = await dispatch( - joinQueue({ - name: name1, - contactNumber: contactNumber1, - notifiable: true, - queueId, - emailId: emailId1, - goToStatusPage: true, - }) - ); - return queue; - }; - const onRefreshClick = () => { dispatch(getQueueInfoByName({ queueName })); }; - const onSubmitGetToken = (contactNumber) => { - dispatch( - getTokenByContactNumber({ queueId, contactNumber, redirectToTokenPageOnSuccess: true }) - ); - }; - const getJoinQueueOptions = () => { if (queueInfo.status === 'PAUSED') { return ( @@ -69,12 +46,7 @@ export default ({ match }) => { return ( <>

Please enter your contact details to join this line

- +

Please make sure the contact number is correct and is available, you might be called on the number when your turn comes. diff --git a/simplq/src/store/asyncActions/joinQueue.js b/simplq/src/store/asyncActions/joinQueue.js index dabc2b07..a3d6a6fb 100644 --- a/simplq/src/store/asyncActions/joinQueue.js +++ b/simplq/src/store/asyncActions/joinQueue.js @@ -16,9 +16,9 @@ const useJoinQueue = () => { const joinQueue = createAsyncThunk( typePrefix, - async ({ name, contactNumber, notifiable, queueId, emailId, goToStatusPage }) => { + async ({ name, contactNumber, queueId, emailId, goToStatusPage }) => { const authedRequest = makeAuthedRequest( - RequestFactory.createToken(name, contactNumber, notifiable, queueId, emailId) + RequestFactory.createToken(name, contactNumber, queueId, emailId) ); const response = await authedRequest; if (goToStatusPage) { From f23ab18e6c8557ff07022272252ffcb18a9d1841 Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Tue, 26 Oct 2021 18:45:53 +0530 Subject: [PATCH 2/9] link device --- simplq/.env | 2 +- simplq/package-lock.json | 935 ++++++++++++++++++ simplq/package.json | 1 + simplq/public/firebase-messaging-sw.js | 0 simplq/src/api/auth.js | 13 +- simplq/src/api/requestFactory/index.js | 2 + simplq/src/api/requestFactory/owner.js | 21 + simplq/src/components/ErrorHandler.jsx | 15 +- .../TokenStatus/NotificationContainer.jsx | 2 +- simplq/src/index.jsx | 8 - simplq/src/services/alerts/index.js | 35 + simplq/src/services/notification/firebase.js | 55 ++ .../system.js} | 0 simplq/src/store/appSlice.js | 5 + simplq/src/store/asyncActions/linkDevice.js | 41 + 15 files changed, 1104 insertions(+), 31 deletions(-) create mode 100644 simplq/public/firebase-messaging-sw.js create mode 100644 simplq/src/api/requestFactory/owner.js create mode 100644 simplq/src/services/alerts/index.js create mode 100644 simplq/src/services/notification/firebase.js rename simplq/src/services/{notification.js => notification/system.js} (100%) create mode 100644 simplq/src/store/asyncActions/linkDevice.js diff --git a/simplq/.env b/simplq/.env index 9e29bfe2..673513be 100644 --- a/simplq/.env +++ b/simplq/.env @@ -1 +1 @@ -BASE_URL="https://devbackend.simplq.me/v1" +BASE_URL="http://localhost:8080/v1" diff --git a/simplq/package-lock.json b/simplq/package-lock.json index 241b95d7..4236d548 100644 --- a/simplq/package-lock.json +++ b/simplq/package-lock.json @@ -1318,6 +1318,722 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, + "@firebase/analytics": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.7.2.tgz", + "integrity": "sha512-YxLsPojufkfe3FFg6imOMQdfdJwu5hig17jnldpdmqemj1gOIwE/peTBrksP4rxnIra26XhsBRppcPcVQyxMNQ==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/installations": "0.5.2", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/analytics-compat": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.1.3.tgz", + "integrity": "sha512-FpaJ4sbJnryCRBkKIE45L2wGt2oCmlRK+AZc4JQHw20vb8Mf1WG1qGO+FGNoFev3lJSAd21tyhoLdPvbCTnOZQ==", + "requires": { + "@firebase/analytics": "0.7.2", + "@firebase/analytics-types": "0.7.0", + "@firebase/component": "0.5.7", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/analytics-types": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.7.0.tgz", + "integrity": "sha512-DNE2Waiwy5+zZnCfintkDtBfaW6MjIG883474v6Z0K1XZIvl76cLND4iv0YUb48leyF+PJK1KO2XrgHb/KpmhQ==" + }, + "@firebase/app": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.7.4.tgz", + "integrity": "sha512-XBrZb60m7N1XqmRhSJWADDD3J/0j9wM2VhxC5KUEtFA9SWfTn9Z3EWGtRGz7ahrMkgPJsmo0fXpvUh6cY8pQvQ==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/app-check": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.4.2.tgz", + "integrity": "sha512-DFYt22lUMvvncN3v6x9ZRE2/HHBQdRQyYtHwakAcZrRUALJiU16iDwl2CABuW4JKytTmMj+xXo0fjSIRWtwT/w==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/app-check-compat": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.1.3.tgz", + "integrity": "sha512-ka5ggmfucQDwEJTcFsXPJJ+ygPZz4Q44D5yb0sksfOAsUSpzAR83jDSxebOgTvvk+axNCFamxOsrZEV6KKDjEg==", + "requires": { + "@firebase/app-check": "0.4.2", + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/app-check-interop-types": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.1.0.tgz", + "integrity": "sha512-uZfn9s4uuRsaX5Lwx+gFP3B6YsyOKUE+Rqa6z9ojT4VSRAsZFko9FRn6OxQUA1z5t5d08fY4pf+/+Dkd5wbdbA==" + }, + "@firebase/app-compat": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.1.5.tgz", + "integrity": "sha512-GJURp5Nn8dEm72/y13Z+XMvWmMomsYViNxw6VKYqVH9f9VKnJ46Q8zYtx2ePvOuj7pAqsfwNkvAdAFYcveTe9g==", + "requires": { + "@firebase/app": "0.7.4", + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/app-types": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.7.0.tgz", + "integrity": "sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg==" + }, + "@firebase/auth": { + "version": "0.18.3", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.18.3.tgz", + "integrity": "sha512-uS67CzypGu52H94mkptJ/lpoc0xAtVDksb/4+4HdSRwekxMt5EtyEdLMy8MH73Vk3MwTQWyTEsHEbwrGgk42pQ==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "node-fetch": "2.6.5", + "selenium-webdriver": "4.0.0-rc-1", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/auth-compat": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.1.6.tgz", + "integrity": "sha512-+HNIsti29ZX4AgLH4KdI+DAesX9DOywcmHFbVJtOE6Ow8v2d8NFTi66fa4LEU7HLCvj9YpeiEpHHLs4NamJ1tw==", + "requires": { + "@firebase/auth": "0.18.3", + "@firebase/auth-types": "0.11.0", + "@firebase/component": "0.5.7", + "@firebase/util": "1.4.0", + "node-fetch": "2.6.5", + "selenium-webdriver": "^4.0.0-beta.2", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/auth-interop-types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz", + "integrity": "sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==" + }, + "@firebase/auth-types": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.11.0.tgz", + "integrity": "sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==" + }, + "@firebase/component": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.7.tgz", + "integrity": "sha512-CiAHUPXh2hn/lpzMShNmfAxHNQhKQwmQUJSYMPCjf2bCCt4Z2vLGpS+UWEuNFm9Zf8LNmkS+Z+U/s4Obi5carg==", + "requires": { + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/database": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.12.2.tgz", + "integrity": "sha512-Y1LZR1LIQM8YKMkeUPpAq3/e53hcfcXO+JEZ6vCzBeD6xRawqmpw6B5/DzePdCNNvjcqheXzSaR7T39eRZo/wA==", + "requires": { + "@firebase/auth-interop-types": "0.1.6", + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + }, + "dependencies": { + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/database-compat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.1.2.tgz", + "integrity": "sha512-sV32QIRSNIBj/6OYtpmPzA/SfQz1/NBZbhxg9dIhGaSt9e5HaMxXRuz2lImudX0Sd/v8DKdExrxa++K6rKrRtA==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/database": "0.12.2", + "@firebase/database-types": "0.9.1", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/database-types": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.1.tgz", + "integrity": "sha512-RUixK/YrbpxbfdE+nYP0wMcEsz1xPTnafP0q3UlSS/+fW744OITKtR1J0cMRaXbvY7EH0wUVTNVkrtgxYY8IgQ==", + "requires": { + "@firebase/app-types": "0.7.0", + "@firebase/util": "1.4.0" + } + }, + "@firebase/firestore": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-3.1.1.tgz", + "integrity": "sha512-hFl+Me6F+GhtEaMsmwruOVoaJfoYinjCKyhaXzQT/jUsoBzKUBCd6MKMjYD+D+y1deAmdkFJcRNxPV7CsgF2aw==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "@firebase/webchannel-wrapper": "0.6.0", + "@grpc/grpc-js": "^1.3.2", + "@grpc/proto-loader": "^0.6.0", + "node-fetch": "2.6.5", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/firestore-compat": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.1.4.tgz", + "integrity": "sha512-NuV0cKXE1EAxNkZxRXYjFsBPiXljuq0W3NeKyQYZTmYsVVJ215KHdR/RHAUA+1ZOfrfT2NgoZpBmE7LpYeLwXA==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/firestore": "3.1.1", + "@firebase/firestore-types": "2.5.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/firestore-types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.5.0.tgz", + "integrity": "sha512-I6c2m1zUhZ5SH0cWPmINabDyH5w0PPFHk2UHsjBpKdZllzJZ2TwTkXbDtpHUZNmnc/zAa0WNMNMvcvbb/xJLKA==" + }, + "@firebase/functions": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.7.3.tgz", + "integrity": "sha512-LxLbR9UtULLKMWSs6vtlte2Ka5tBDPGeGwX8Mto2uAtaNdrkoWKdhiJ4OTQx1YTCRIbTQnTg3t50NO8afzTEcQ==", + "requires": { + "@firebase/app-check-interop-types": "0.1.0", + "@firebase/auth-interop-types": "0.1.6", + "@firebase/component": "0.5.7", + "@firebase/messaging-interop-types": "0.1.0", + "@firebase/util": "1.4.0", + "node-fetch": "2.6.5", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/functions-compat": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.1.4.tgz", + "integrity": "sha512-mC/z0uJbGk/RRskabvvDylpMHMsNNwNIxrjBJy3J8ADZUqpJTMuT4gq+pHlPemYqLBZuN8TffIZNVPajXxqc+Q==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/functions": "0.7.3", + "@firebase/functions-types": "0.5.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/functions-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.5.0.tgz", + "integrity": "sha512-qza0M5EwX+Ocrl1cYI14zoipUX4gI/Shwqv0C1nB864INAD42Dgv4v94BCyxGHBg2kzlWy8PNafdP7zPO8aJQA==" + }, + "@firebase/installations": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.5.2.tgz", + "integrity": "sha512-k43qItRUnjIhAcxFRhGrox2ZBY/CFJOizB30hej9HuWOFv4qXoMZOmLtKzyjskFhRn/HW8iBUVguNFAEf6iehw==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/util": "1.4.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-7oQ+TctqekfgZImWkKuda50JZfkmAKMgh5qY4aR4pwRyqZXuJXN1H/BKkHvN1y0S4XWtF0f/wiCLKHhyi1ppPA==", + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/messaging": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.9.2.tgz", + "integrity": "sha512-v95cny/HsupEvFiewsobjEtQ8ItMCPsg+29VLP51SIS3Ix7Kg2TJLZ2tfHkESRFazIhf2+GNwR8hdXoajqz2og==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/installations": "0.5.2", + "@firebase/messaging-interop-types": "0.1.0", + "@firebase/util": "1.4.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/messaging-compat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.1.2.tgz", + "integrity": "sha512-ORxqIlnstjRhTpQsX7A0K9ifBTrqI7MNdWwCRbhvTh7GkzmhMe7ht+YAALrdvHD3Qty49UFrHznaIbF7Gr+nwA==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/messaging": "0.9.2", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/messaging-interop-types": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.1.0.tgz", + "integrity": "sha512-DbvUl/rXAZpQeKBnwz0NYY5OCqr2nFA0Bj28Fmr3NXGqR4PAkfTOHuQlVtLO1Nudo3q0HxAYLa68ZDAcuv2uKQ==" + }, + "@firebase/performance": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.5.2.tgz", + "integrity": "sha512-xHrt/BNiln3OIW9hyqKwck0x4C7Km+XKYQsP8cPDBh8AWFh//DB0ta7DuMXw7JGIuyKpK2D3iq5aQNS0MzMvSw==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/installations": "0.5.2", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/performance-compat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.1.2.tgz", + "integrity": "sha512-L9rt89eIPaucGsO/bwF199mS5+BV3kHTfK1Fr1vCmGL87kLpV8DKVccKc7Z0ZwQelfMvXOGy5jVqH/sHhiQAYg==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/performance": "0.5.2", + "@firebase/performance-types": "0.1.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/performance-types": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.1.0.tgz", + "integrity": "sha512-6p1HxrH0mpx+622Ql6fcxFxfkYSBpE3LSuwM7iTtYU2nw91Hj6THC8Bc8z4nboIq7WvgsT/kOTYVVZzCSlXl8w==" + }, + "@firebase/polyfill": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.36.tgz", + "integrity": "sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg==", + "requires": { + "core-js": "3.6.5", + "promise-polyfill": "8.1.3", + "whatwg-fetch": "2.0.4" + }, + "dependencies": { + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + }, + "promise-polyfill": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", + "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" + }, + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + } + } + }, + "@firebase/remote-config": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.3.1.tgz", + "integrity": "sha512-31nZ0NEcARw1wYKIpoAx63rA0ao28e9zYNrlSC08mBiouSOxu69lthiO0V1ZrFqR/iW9+7M2MqnOUhJ6/LYEwQ==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/installations": "0.5.2", + "@firebase/logger": "0.3.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/remote-config-compat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.1.2.tgz", + "integrity": "sha512-j+joqwZAOO1L3pTlK8aQ3M+781ZbbOtV/TNpU4Tulqq+Psfjlx5SOYVfuF8njbbWGPLhLReFwmEjyE3jnm9hrQ==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/logger": "0.3.0", + "@firebase/remote-config": "0.3.1", + "@firebase/remote-config-types": "0.2.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/remote-config-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.2.0.tgz", + "integrity": "sha512-hqK5sCPeZvcHQ1D6VjJZdW6EexLTXNMJfPdTwbD8NrXUw6UjWC4KWhLK/TSlL0QPsQtcKRkaaoP+9QCgKfMFPw==" + }, + "@firebase/storage": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.8.4.tgz", + "integrity": "sha512-Flv25G8J4hp9wa9qTy9UoaBRl2Vcsr+FGaK6RaRUAzoMw2PA46ZPt/DChJZWxKgpmOq/7HyRc8qNTwqqDJt7dA==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/util": "1.4.0", + "node-fetch": "2.6.5", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/storage-compat": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.1.4.tgz", + "integrity": "sha512-EV14tdnjm5yewGBgsUarGPzRUgqQX26+NVHIW1AoT+bMoODlL5ypYGv2/QA9Phi7JBvo5cAcTe4stEsu3CTF0g==", + "requires": { + "@firebase/component": "0.5.7", + "@firebase/storage": "0.8.4", + "@firebase/storage-types": "0.6.0", + "@firebase/util": "1.4.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/storage-types": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.6.0.tgz", + "integrity": "sha512-1LpWhcCb1ftpkP/akhzjzeFxgVefs6eMD2QeKiJJUGH1qOiows2w5o0sKCUSQrvrRQS1lz3SFGvNR1Ck/gqxeA==" + }, + "@firebase/util": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.4.0.tgz", + "integrity": "sha512-Qn58d+DVi1nGn0bA9RV89zkz0zcbt6aUcRdyiuub/SuEvjKYstWmHcHwh1C0qmE1wPf9a3a+AuaRtduaGaRT7A==", + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@firebase/webchannel-wrapper": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.6.0.tgz", + "integrity": "sha512-Pz4+7HPzKvOFI1ICQ6pyUv/VgStEWq9IGiVaaV1cQLi66NIA1mD5INnY4CDNoVAxlkuZvDEUZ+cVHLQ8iwA2hQ==" + }, + "@grpc/grpc-js": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.4.1.tgz", + "integrity": "sha512-/chkA48TdAvATHA7RXJPeHQLdfFhpu51974s8htjO/XTDHA41j5+SkR5Io+lr9XsLmkZD6HxLyRAFGmA9wjO2w==", + "requires": { + "@grpc/proto-loader": "^0.6.4", + "@types/node": ">=12.12.47" + } + }, + "@grpc/proto-loader": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.6.tgz", + "integrity": "sha512-cdMaPZ8AiFz6ua6PUbP+LKbhwJbFXnrQ/mlnKGUyzDUZ3wp7vPLksnmLCBX6SHgSmjX7CbNVNLFYD5GmmjO4GQ==", + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.10.0", + "yargs": "^16.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + } + } + }, "@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -1723,6 +2439,60 @@ "integrity": "sha512-DvJbbn3dUgMxDnJLH+RZQPnXak1h4ZVYQ7CWiFWjQwBFkVajT4rfw2PdpHLTSTwxrYfnoEXkuBiwkDm6tPMQeA==", "dev": true }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, "@reach/router": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/@reach/router/-/router-1.3.4.tgz", @@ -4789,6 +5559,11 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, "@types/markdown-to-jsx": { "version": "6.11.3", "resolved": "https://registry.npmjs.org/@types/markdown-to-jsx/-/markdown-to-jsx-6.11.3.tgz", @@ -10958,6 +11733,39 @@ "parse-filepath": "^1.0.1" } }, + "firebase": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-9.1.3.tgz", + "integrity": "sha512-OZA60idIzSE5c01qWUDH2plhe+s4VrwbPurAh1KxvPEhMdZSOVK3zrBFHbc7nczFYWRDQpWU6v7gTHAVSANHQg==", + "requires": { + "@firebase/analytics": "0.7.2", + "@firebase/analytics-compat": "0.1.3", + "@firebase/app": "0.7.4", + "@firebase/app-check": "0.4.2", + "@firebase/app-check-compat": "0.1.3", + "@firebase/app-compat": "0.1.5", + "@firebase/app-types": "0.7.0", + "@firebase/auth": "0.18.3", + "@firebase/auth-compat": "0.1.6", + "@firebase/database": "0.12.2", + "@firebase/database-compat": "0.1.2", + "@firebase/firestore": "3.1.1", + "@firebase/firestore-compat": "0.1.4", + "@firebase/functions": "0.7.3", + "@firebase/functions-compat": "0.1.4", + "@firebase/installations": "0.5.2", + "@firebase/messaging": "0.9.2", + "@firebase/messaging-compat": "0.1.2", + "@firebase/performance": "0.5.2", + "@firebase/performance-compat": "0.1.2", + "@firebase/polyfill": "0.3.36", + "@firebase/remote-config": "0.3.1", + "@firebase/remote-config-compat": "0.1.2", + "@firebase/storage": "0.8.4", + "@firebase/storage-compat": "0.1.4", + "@firebase/util": "1.4.0" + } + }, "flagged-respawn": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", @@ -12380,6 +13188,11 @@ "postcss": "^7.0.14" } }, + "idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, "identity-obj-proxy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", @@ -12403,6 +13216,11 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, "immer": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", @@ -13986,6 +14804,17 @@ "object.assign": "^4.1.0" } }, + "jszip": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", + "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, "junk": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", @@ -14116,6 +14945,14 @@ "type-check": "~0.3.2" } }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "requires": { + "immediate": "~3.0.5" + } + }, "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", @@ -14619,6 +15456,11 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -14850,6 +15692,11 @@ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -15534,6 +16381,35 @@ "minimatch": "^3.0.2" } }, + "node-fetch": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", + "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", @@ -17696,6 +18572,26 @@ "xtend": "^4.0.0" } }, + "protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -19618,6 +20514,40 @@ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" }, + "selenium-webdriver": { + "version": "4.0.0-rc-1", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-rc-1.tgz", + "integrity": "sha512-bcrwFPRax8fifRP60p7xkWDGSJJoMkPAzufMlk5K2NyLPht/YZzR2WcIk1+3gR8VOCLlst1P2PI+MXACaFzpIw==", + "requires": { + "jszip": "^3.6.0", + "rimraf": "^3.0.2", + "tmp": "^0.2.1", + "ws": ">=7.4.6" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "requires": { + "rimraf": "^3.0.0" + } + }, + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" + } + } + }, "selfsigned": { "version": "1.10.8", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", @@ -19800,6 +20730,11 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", diff --git a/simplq/package.json b/simplq/package.json index 0b95f413..279a37ce 100644 --- a/simplq/package.json +++ b/simplq/package.json @@ -15,6 +15,7 @@ "aos": "^2.3.4", "axios": "^0.21.1", "components": "^0.1.0", + "firebase": "^9.1.3", "google-libphonenumber": "^3.2.13", "moment": "^2.29.1", "node-sass": "^4.14.1", diff --git a/simplq/public/firebase-messaging-sw.js b/simplq/public/firebase-messaging-sw.js new file mode 100644 index 00000000..e69de29b diff --git a/simplq/src/api/auth.js b/simplq/src/api/auth.js index c70c4997..fe5fdb88 100644 --- a/simplq/src/api/auth.js +++ b/simplq/src/api/auth.js @@ -1,10 +1,10 @@ import { useAuth0 } from '@auth0/auth0-react'; import { v4 as uuidv4 } from 'uuid'; import axios from 'axios'; -import * as Sentry from '@sentry/react'; // config.js is generated at runtime, so disabling eslint warning /* eslint-disable import/no-unresolved, import/extensions */ +import { raiseException } from 'services/alerts'; import { baseURL } from '../config'; const ANONYMOUS_DEVICE_ID_KEY = 'anonymous-device-id'; @@ -53,14 +53,9 @@ const useMakeAuthedRequest = () => { Authorization: await getAuthHeaderValue(auth), }, }).catch((error) => { - // log error to sentry for alerting - let eventId; - Sentry.withScope((scope) => { - scope.setTag('Caught-at', 'API request'); - eventId = Sentry.captureException(error); - }); - // eslint-disable-next-line no-console - console.log(`Sentry exception captured, event id is ${eventId}`); + // log error to alerting + raiseException(error, 'API request'); + // In case of request failure, extract error from response body if (error.response) { // Response has been received from the server diff --git a/simplq/src/api/requestFactory/index.js b/simplq/src/api/requestFactory/index.js index d6cd121d..e3464cc9 100644 --- a/simplq/src/api/requestFactory/index.js +++ b/simplq/src/api/requestFactory/index.js @@ -36,3 +36,5 @@ export { notifyToken, getTokenByContactNumber, } from './token'; + +export { linkDevice, unlinkDevice } from './owner'; diff --git a/simplq/src/api/requestFactory/owner.js b/simplq/src/api/requestFactory/owner.js new file mode 100644 index 00000000..a4d17777 --- /dev/null +++ b/simplq/src/api/requestFactory/owner.js @@ -0,0 +1,21 @@ +/** + * Subscribe to backend for notifications + * + * @param {String} deviceId - device token that identifies this device + * @returns {Object} request - partial axios request without baseURL + */ +export const linkDevice = (deviceId) => ({ + method: 'put', + url: `/owner/link?deviceId=${deviceId}`, +}); + +/** + * Unsubscribe to backend for notifications + * + * @param {String} deviceId - device token that identifies this device + * @returns {Object} request - partial axios request without baseURL + */ +export const unlinkDevice = (deviceId) => ({ + method: 'patch', + url: `/owner/unlink?deviceId=${deviceId}`, +}); diff --git a/simplq/src/components/ErrorHandler.jsx b/simplq/src/components/ErrorHandler.jsx index f6796dde..1cae1e25 100644 --- a/simplq/src/components/ErrorHandler.jsx +++ b/simplq/src/components/ErrorHandler.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import * as Sentry from '@sentry/react'; +import { raiseException } from 'services/alerts'; import PageNotFound from './pages/PageNotFound'; // eslint-disable-next-line import/prefer-default-export @@ -19,17 +19,8 @@ export class ErrorBoundary extends React.Component { } componentDidCatch(error, errorInfo) { - // You can also log the error to an error reporting service - // logErrorToMyService(error, errorInfo); - // log error to sentry for alerting - let eventId; - Sentry.withScope((scope) => { - scope.setTag('Caught-at', 'Error Boundary'); - scope.setExtras(errorInfo); - eventId = Sentry.captureException(error); - }); - // eslint-disable-next-line no-console - console.log(`Sentry exception captured, event id is ${eventId}`); + // log the error to our error reporting service + raiseException(error, 'Error Boundary', errorInfo); } render() { diff --git a/simplq/src/components/pages/TokenStatus/NotificationContainer.jsx b/simplq/src/components/pages/TokenStatus/NotificationContainer.jsx index c9441a52..99eea3e4 100644 --- a/simplq/src/components/pages/TokenStatus/NotificationContainer.jsx +++ b/simplq/src/components/pages/TokenStatus/NotificationContainer.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { useSelector } from 'react-redux'; import Switch from '@material-ui/core/Switch'; import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'; -import { setNotificationPreference } from 'services/notification'; +import { setNotificationPreference } from 'services/notification/system'; import styles from './status.module.scss'; export default () => { diff --git a/simplq/src/index.jsx b/simplq/src/index.jsx index ac3613d2..c1fe1390 100644 --- a/simplq/src/index.jsx +++ b/simplq/src/index.jsx @@ -3,8 +3,6 @@ import ReactDOM from 'react-dom'; import './index.css'; import { createTheme, ThemeProvider } from '@material-ui/core/styles'; import { Provider } from 'react-redux'; -import * as Sentry from '@sentry/react'; -import { Integrations } from '@sentry/tracing'; import AOS from 'aos'; import { Auth0Provider } from '@auth0/auth0-react'; import { store } from './store'; @@ -13,12 +11,6 @@ import Layout from './components/Layout/Layout'; AOS.init(); -Sentry.init({ - dsn: 'https://b95e1a087d284ecca9a50909d2a792e8@o444913.ingest.sentry.io/5420492', - integrations: [new Integrations.BrowserTracing()], - tracesSampleRate: 1.0, -}); - const theme = createTheme({ palette: { primary: { diff --git a/simplq/src/services/alerts/index.js b/simplq/src/services/alerts/index.js new file mode 100644 index 00000000..e986ded7 --- /dev/null +++ b/simplq/src/services/alerts/index.js @@ -0,0 +1,35 @@ +import * as Sentry from '@sentry/react'; +import { Integrations } from '@sentry/tracing'; + +Sentry.init({ + dsn: 'https://b95e1a087d284ecca9a50909d2a792e8@o444913.ingest.sentry.io/5420492', + integrations: [new Integrations.BrowserTracing()], + tracesSampleRate: 1.0, +}); + +/** + * Send exception to monitoring framework. + * + * @param {Exception} ex - exception that was captured. + * @param {string} caughtAt - Optional. A tag indicating where the exception was caught. + * @param {object} extras - Optional. Set an object that will be merged sent as extra data with the event. + */ +export function raiseException(ex, caughtAt, extras) { + Sentry.withScope((scope) => { + if (caughtAt) { + scope.setTag('Caught-at', caughtAt); + } + if (extras) { + scope.setExtras(extras); + } + + const eventId = Sentry.captureException(ex); + + // eslint-disable-next-line no-console + console.log(`Sentry exception captured, event id is ${eventId}`); + // eslint-disable-next-line no-console + console.error(ex); + }); +} + +export default raiseException; diff --git a/simplq/src/services/notification/firebase.js b/simplq/src/services/notification/firebase.js new file mode 100644 index 00000000..42561e95 --- /dev/null +++ b/simplq/src/services/notification/firebase.js @@ -0,0 +1,55 @@ +import { getToken } from 'firebase/messaging'; +import { initializeApp } from 'firebase/app'; +import { + setFirebaseNotificationToken, + setNotificationPermission, + setErrorPopupMessage, +} from 'store/appSlice'; +import { store } from 'store'; +import { raiseException } from 'services/alerts'; +import { useLinkDevice } from 'store/asyncActions/linkDevice'; + +// Public key generated from firebase console +const vapidKey = + 'BCAlBO-AnqZIo_3MEiR5zEwJTFNNWBR6MdmZ5RpStXxTN6vfgUV2mL3c_hz8vQkcQ2bb_a7IMlGUhAnaw3eBZm4'; +// Firebase configuration +const firebaseConfig = { + apiKey: 'AIzaSyCCW7gmWZli24N61NShh-8ALxVy3WtjqNU', + authDomain: 'simplq-fe712.firebaseapp.com', + projectId: 'simplq-fe712', + storageBucket: 'simplq-fe712.appspot.com', + messagingSenderId: '348531792421', + appId: '1:348531792421:web:c481f1740405522d0f3dcc', + measurementId: 'G-8N2SDV8VF5', +}; + +// Initialize Firebase +initializeApp(firebaseConfig); + +/** + * React hook that lets you register for notifications. + */ +export function useRegisterNotifications() { + const linkDevice = useLinkDevice(); + + const registerNotifications = () => { + getToken({ vapidKey }) + .then((deviceId) => { + store.dispatch(setFirebaseNotificationToken(deviceId)); + store.dispatch(setNotificationPermission(true)); + store.dispatch(linkDevice(deviceId)); + }) + .catch((ex) => { + store.dispatch( + setErrorPopupMessage( + 'Your browser has disabled notifications, please enable from Browser Settings' + ) + ); + raiseException(ex, 'firebase/registerNotifications'); + }); + }; + + return registerNotifications; +} + +export function useDeregisterNotifications() {} diff --git a/simplq/src/services/notification.js b/simplq/src/services/notification/system.js similarity index 100% rename from simplq/src/services/notification.js rename to simplq/src/services/notification/system.js diff --git a/simplq/src/store/appSlice.js b/simplq/src/store/appSlice.js index 89920419..dd93433f 100644 --- a/simplq/src/store/appSlice.js +++ b/simplq/src/store/appSlice.js @@ -12,6 +12,7 @@ const appSlice = createSlice({ errorText: '', infoText: '', notificationPermission: null, // This state value is initialised by the notification service. + firebaseNotificationToken: null, // This state value is initialised by the firebase service. }, reducers: { setErrorPopupMessage: (state, action) => { @@ -23,6 +24,9 @@ const appSlice = createSlice({ setNotificationPermission: (state, action) => { state.notificationPermission = action.payload; }, + setFirebaseNotificationToken: (state, action) => { + state.firebaseNotificationToken = action.payload; + }, }, extraReducers: (builder) => { builder @@ -55,6 +59,7 @@ export const { setErrorPopupMessage, setInfoPopupMessage, setNotificationPermission, + setFirebaseNotificationToken, } = appSlice.actions; export default appSlice.reducer; diff --git a/simplq/src/store/asyncActions/linkDevice.js b/simplq/src/store/asyncActions/linkDevice.js new file mode 100644 index 00000000..53029ea9 --- /dev/null +++ b/simplq/src/store/asyncActions/linkDevice.js @@ -0,0 +1,41 @@ +import { createAsyncThunk } from '@reduxjs/toolkit'; +import { useMakeAuthedRequest } from 'api/auth'; +import * as RequestFactory from 'api/requestFactory'; + +const typePrefix = 'linkDevice/action'; + +/** + * A hook to access the linkDevice async action creator. + * + * @returns — linkDevice async action creator + * + * @example + * + * import linkDevice from 'store/tokens' + * + * const linkDevice = useLinkDevice() + */ +const useLinkDevice = () => { + const makeAuthedRequest = useMakeAuthedRequest(); + + const linkDevice = createAsyncThunk(typePrefix, async (deviceId) => { + return makeAuthedRequest(RequestFactory.linkDevice(deviceId)); + }); + + return linkDevice; +}; + +/** + * A shadow function that returns linkDevice async action creator. + * + * This should be used just for the action creators that it generates. + + * @see store/tokensSlice.js + * + * @see https://redux-toolkit.js.org/api/createAsyncThunk#return-value + * + * @returns linkDevice() async action creator + */ +const linkDevice = createAsyncThunk(typePrefix); + +export { linkDevice, useLinkDevice }; From a5b618d3d2c68b22edfcc5049c52cdebf404885c Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Tue, 26 Oct 2021 19:25:29 +0530 Subject: [PATCH 3/9] Setting store values post registration call --- simplq/src/services/notification/firebase.js | 10 ++-------- simplq/src/services/notification/system.js | 5 +---- simplq/src/store/appSlice.js | 15 ++++++++------- simplq/src/store/asyncActions/index.js | 2 ++ 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/simplq/src/services/notification/firebase.js b/simplq/src/services/notification/firebase.js index 42561e95..a3a1446c 100644 --- a/simplq/src/services/notification/firebase.js +++ b/simplq/src/services/notification/firebase.js @@ -1,13 +1,9 @@ import { getToken } from 'firebase/messaging'; import { initializeApp } from 'firebase/app'; -import { - setFirebaseNotificationToken, - setNotificationPermission, - setErrorPopupMessage, -} from 'store/appSlice'; +import { setErrorPopupMessage } from 'store/appSlice'; import { store } from 'store'; import { raiseException } from 'services/alerts'; -import { useLinkDevice } from 'store/asyncActions/linkDevice'; +import { useLinkDevice } from 'store/asyncActions'; // Public key generated from firebase console const vapidKey = @@ -35,8 +31,6 @@ export function useRegisterNotifications() { const registerNotifications = () => { getToken({ vapidKey }) .then((deviceId) => { - store.dispatch(setFirebaseNotificationToken(deviceId)); - store.dispatch(setNotificationPermission(true)); store.dispatch(linkDevice(deviceId)); }) .catch((ex) => { diff --git a/simplq/src/services/notification/system.js b/simplq/src/services/notification/system.js index 99701053..b1968993 100644 --- a/simplq/src/services/notification/system.js +++ b/simplq/src/services/notification/system.js @@ -68,13 +68,10 @@ export const notify = (messageText) => { }; // fix for Notification object not supported on iOS safari -const getNotificationStatus = () => { +export const getNotificationStatus = () => { try { return Notification.permission; } catch (error) { return 'denied'; } }; - -// Initilise notifications at start -store.dispatch(setNotificationPermission(getNotificationStatus())); diff --git a/simplq/src/store/appSlice.js b/simplq/src/store/appSlice.js index dd93433f..363b8127 100644 --- a/simplq/src/store/appSlice.js +++ b/simplq/src/store/appSlice.js @@ -1,6 +1,6 @@ /* eslint-disable no-param-reassign */ import { createSlice } from '@reduxjs/toolkit'; -import { createQueue, deleteQueue, joinQueue } from 'store/asyncActions'; +import { createQueue, deleteQueue, joinQueue, linkDevice } from 'store/asyncActions'; function isRejectedAction(action) { return action.type.endsWith('rejected'); @@ -11,8 +11,9 @@ const appSlice = createSlice({ initialState: { errorText: '', infoText: '', - notificationPermission: null, // This state value is initialised by the notification service. - firebaseNotificationToken: null, // This state value is initialised by the firebase service. + // This value is initilised at start by services/notification/system.js + notificationPermission: null, + firebaseNotificationDeviceId: null, }, reducers: { setErrorPopupMessage: (state, action) => { @@ -24,9 +25,6 @@ const appSlice = createSlice({ setNotificationPermission: (state, action) => { state.notificationPermission = action.payload; }, - setFirebaseNotificationToken: (state, action) => { - state.firebaseNotificationToken = action.payload; - }, }, extraReducers: (builder) => { builder @@ -48,6 +46,10 @@ const appSlice = createSlice({ .addCase(deleteQueue.fulfilled, (state, action) => { state.infoText = `Deleted ${action.payload.queueName}`; }) + .addCase(linkDevice.fulfilled, (state, action) => { + state.notificationPermission = true; + state.firebaseNotificationDeviceId = action.payload.deviceId; + }) .addMatcher(isRejectedAction, (state, action) => { // All failed network calls are handled here state.errorText = action.error.message; @@ -59,7 +61,6 @@ export const { setErrorPopupMessage, setInfoPopupMessage, setNotificationPermission, - setFirebaseNotificationToken, } = appSlice.actions; export default appSlice.reducer; diff --git a/simplq/src/store/asyncActions/index.js b/simplq/src/store/asyncActions/index.js index 7286b98b..efa1f104 100644 --- a/simplq/src/store/asyncActions/index.js +++ b/simplq/src/store/asyncActions/index.js @@ -20,3 +20,5 @@ export { updateQueueSettings, useUpdateQueueSettings } from './updateQueueSettin export { getToken, useGetToken } from './getToken'; export { deleteToken, useDeleteToken } from './deleteToken'; export { notifyToken, useNotifyToken } from './notifyToken'; + +export { linkDevice, useLinkDevice } from './linkDevice'; From 17fe743f255ac91a951cc393bf0dfc676630fe89 Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Mon, 1 Nov 2021 10:55:42 +0530 Subject: [PATCH 4/9] fix imports issue --- simplq/src/store/asyncActions/index.js | 4 ++-- simplq/src/store/asyncActions/linkDevice.js | 11 ----------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/simplq/src/store/asyncActions/index.js b/simplq/src/store/asyncActions/index.js index efa1f104..6eab8455 100644 --- a/simplq/src/store/asyncActions/index.js +++ b/simplq/src/store/asyncActions/index.js @@ -5,6 +5,8 @@ * in separate files and can depend on each other. */ +export { linkDevice, useLinkDevice } from './linkDevice'; + export { getUserQueues, useGetUserQueues } from './getUserQueues'; export { getUserTokens, useGetUserTokens } from './getUserTokens'; export { deleteQueue, useDeleteQueue } from './deleteQueue'; @@ -20,5 +22,3 @@ export { updateQueueSettings, useUpdateQueueSettings } from './updateQueueSettin export { getToken, useGetToken } from './getToken'; export { deleteToken, useDeleteToken } from './deleteToken'; export { notifyToken, useNotifyToken } from './notifyToken'; - -export { linkDevice, useLinkDevice } from './linkDevice'; diff --git a/simplq/src/store/asyncActions/linkDevice.js b/simplq/src/store/asyncActions/linkDevice.js index 53029ea9..bd17ce86 100644 --- a/simplq/src/store/asyncActions/linkDevice.js +++ b/simplq/src/store/asyncActions/linkDevice.js @@ -25,17 +25,6 @@ const useLinkDevice = () => { return linkDevice; }; -/** - * A shadow function that returns linkDevice async action creator. - * - * This should be used just for the action creators that it generates. - - * @see store/tokensSlice.js - * - * @see https://redux-toolkit.js.org/api/createAsyncThunk#return-value - * - * @returns linkDevice() async action creator - */ const linkDevice = createAsyncThunk(typePrefix); export { linkDevice, useLinkDevice }; From fbf33c10c16353ab246b73ba5178757613468de2 Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Mon, 1 Nov 2021 12:32:09 +0530 Subject: [PATCH 5/9] Integrate with join form --- simplq/src/components/pages/Join/JoinForm.jsx | 16 +++++++++++++ simplq/src/services/notification/firebase.js | 24 +++++++++---------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/simplq/src/components/pages/Join/JoinForm.jsx b/simplq/src/components/pages/Join/JoinForm.jsx index d9677f35..ae7d832a 100644 --- a/simplq/src/components/pages/Join/JoinForm.jsx +++ b/simplq/src/components/pages/Join/JoinForm.jsx @@ -13,6 +13,7 @@ import StepLabel from '@material-ui/core/StepLabel'; import Typography from '@material-ui/core/Typography'; import { useJoinQueue } from 'store/asyncActions'; import { useGetTokenByContactNumber } from 'store/asyncActions/getTokenByContactNumber'; +import { useRegisterForNotifications } from 'services/notification/firebase'; import styles from './JoinForm.module.scss'; import Checkbox from '../../common/Checkbox/Checkbox'; import { selectQueueInfo } from '../../../store/queueInfo'; @@ -29,7 +30,9 @@ export function JoinQueueForm({ queueId, isAdminPage, buttonText }) { const [activeStep, setActiveStep] = React.useState(0); const queueInfo = useSelector(selectQueueInfo); const [saveToLocalStorage, setSaveToLocalStorage] = useState(true); + const [notifyDevice, setNotifyDevice] = useState(true); const getTokenByContactNumber = useCallback(useGetTokenByContactNumber(), []); + const registerForNotifications = useCallback(useRegisterForNotifications(), []); const { notifyByEmail } = useSelector(selectQueueInfo); const collectEmail = !!notifyByEmail; @@ -45,6 +48,7 @@ export function JoinQueueForm({ queueId, isAdminPage, buttonText }) { queueId, emailId: collectEmail ? emailId : undefined, goToStatusPage: !isAdminPage, + notifyDevice, }) ); }; @@ -141,6 +145,10 @@ export function JoinQueueForm({ queueId, isAdminPage, buttonText }) { localStorage.removeItem('email'); } + if (notifyDevice) { + registerForNotifications(); + } + joinQueueHandler(); // reset to first step on queue page (pages/Admin/AddMember.jsx) if (isAdminPage) setActiveStep(0); @@ -226,6 +234,14 @@ export function JoinQueueForm({ queueId, isAdminPage, buttonText }) { setSaveToLocalStorage(!saveToLocalStorage); }} /> + { + setNotifyDevice(!notifyDevice); + }} + />

diff --git a/simplq/src/services/notification/firebase.js b/simplq/src/services/notification/firebase.js index a3a1446c..9ded8158 100644 --- a/simplq/src/services/notification/firebase.js +++ b/simplq/src/services/notification/firebase.js @@ -1,4 +1,4 @@ -import { getToken } from 'firebase/messaging'; +import { getMessaging, getToken } from 'firebase/messaging'; import { initializeApp } from 'firebase/app'; import { setErrorPopupMessage } from 'store/appSlice'; import { store } from 'store'; @@ -19,31 +19,29 @@ const firebaseConfig = { measurementId: 'G-8N2SDV8VF5', }; -// Initialize Firebase -initializeApp(firebaseConfig); - /** * React hook that lets you register for notifications. */ -export function useRegisterNotifications() { +export function useRegisterForNotifications() { const linkDevice = useLinkDevice(); - const registerNotifications = () => { - getToken({ vapidKey }) + const registerForNotifications = () => { + // Initialize Firebase + const firebaseApp = initializeApp(firebaseConfig); + const messaging = getMessaging(firebaseApp); + + getToken(messaging, { vapidKey }) .then((deviceId) => { store.dispatch(linkDevice(deviceId)); }) .catch((ex) => { - store.dispatch( - setErrorPopupMessage( - 'Your browser has disabled notifications, please enable from Browser Settings' - ) - ); + store.dispatch(setErrorPopupMessage('An error occurred while setting up notifcations.')); raiseException(ex, 'firebase/registerNotifications'); }); }; - return registerNotifications; + return registerForNotifications; } +// TODO export function useDeregisterNotifications() {} From cd011b8a0b0c958a066e1a07aaeb66ce1c39d915 Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Mon, 1 Nov 2021 12:33:55 +0530 Subject: [PATCH 6/9] restore backend url --- simplq/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplq/.env b/simplq/.env index 673513be..fe6b395a 100644 --- a/simplq/.env +++ b/simplq/.env @@ -1 +1 @@ -BASE_URL="http://localhost:8080/v1" +BASE_URL="https://devbackend.simplq.me/v1" \ No newline at end of file From 494824f8c8e1416358c015df041e23799bc02532 Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Mon, 1 Nov 2021 12:34:41 +0530 Subject: [PATCH 7/9] add missing newline --- simplq/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplq/.env b/simplq/.env index fe6b395a..9e29bfe2 100644 --- a/simplq/.env +++ b/simplq/.env @@ -1 +1 @@ -BASE_URL="https://devbackend.simplq.me/v1" \ No newline at end of file +BASE_URL="https://devbackend.simplq.me/v1" From 4b25f588a9a2c19e22708914c9a175d73971281b Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Mon, 1 Nov 2021 12:41:16 +0530 Subject: [PATCH 8/9] review changes --- simplq/src/services/notification/system.js | 5 ++++- simplq/src/store/asyncActions/linkDevice.js | 6 ------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/simplq/src/services/notification/system.js b/simplq/src/services/notification/system.js index b1968993..99701053 100644 --- a/simplq/src/services/notification/system.js +++ b/simplq/src/services/notification/system.js @@ -68,10 +68,13 @@ export const notify = (messageText) => { }; // fix for Notification object not supported on iOS safari -export const getNotificationStatus = () => { +const getNotificationStatus = () => { try { return Notification.permission; } catch (error) { return 'denied'; } }; + +// Initilise notifications at start +store.dispatch(setNotificationPermission(getNotificationStatus())); diff --git a/simplq/src/store/asyncActions/linkDevice.js b/simplq/src/store/asyncActions/linkDevice.js index bd17ce86..529e745f 100644 --- a/simplq/src/store/asyncActions/linkDevice.js +++ b/simplq/src/store/asyncActions/linkDevice.js @@ -8,12 +8,6 @@ const typePrefix = 'linkDevice/action'; * A hook to access the linkDevice async action creator. * * @returns — linkDevice async action creator - * - * @example - * - * import linkDevice from 'store/tokens' - * - * const linkDevice = useLinkDevice() */ const useLinkDevice = () => { const makeAuthedRequest = useMakeAuthedRequest(); From c782e02fdb17bff0fe8cb9b6cec7fc99c14dbcfc Mon Sep 17 00:00:00 2001 From: Dalton Fury Date: Tue, 2 Nov 2021 15:25:08 +0530 Subject: [PATCH 9/9] add sworker --- simplq/public/firebase-messaging-sw.js | 23 ++++++++++++++++++++ simplq/src/services/notification/firebase.js | 8 +++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/simplq/public/firebase-messaging-sw.js b/simplq/public/firebase-messaging-sw.js index e69de29b..27542159 100644 --- a/simplq/public/firebase-messaging-sw.js +++ b/simplq/public/firebase-messaging-sw.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// Give the service worker access to Firebase Messaging. +// Note that you can only use Firebase Messaging here. Other Firebase libraries +// are not available in the service worker. +importScripts('https://www.gstatic.com/firebasejs/9.1.3/firebase-app-compat.js'); +importScripts('https://www.gstatic.com/firebasejs/9.1.3/firebase-messaging-compat.js'); + +// Initialize the Firebase app in the service worker by passing in +// your app's Firebase config object. +// https://firebase.google.com/docs/web/setup#config-object +firebase.initializeApp({ + apiKey: 'AIzaSyCCW7gmWZli24N61NShh-8ALxVy3WtjqNU', + authDomain: 'simplq-fe712.firebaseapp.com', + projectId: 'simplq-fe712', + storageBucket: 'simplq-fe712.appspot.com', + messagingSenderId: '348531792421', + appId: '1:348531792421:web:c481f1740405522d0f3dcc', + measurementId: 'G-8N2SDV8VF5', +}); + +// Retrieve an instance of Firebase Messaging so that it can handle background +// messages. +const messaging = firebase.messaging(); diff --git a/simplq/src/services/notification/firebase.js b/simplq/src/services/notification/firebase.js index 9ded8158..3c9f7a0d 100644 --- a/simplq/src/services/notification/firebase.js +++ b/simplq/src/services/notification/firebase.js @@ -19,6 +19,10 @@ const firebaseConfig = { measurementId: 'G-8N2SDV8VF5', }; +// Initialize Firebase +const firebaseApp = initializeApp(firebaseConfig); +const messaging = getMessaging(firebaseApp); + /** * React hook that lets you register for notifications. */ @@ -26,10 +30,6 @@ export function useRegisterForNotifications() { const linkDevice = useLinkDevice(); const registerForNotifications = () => { - // Initialize Firebase - const firebaseApp = initializeApp(firebaseConfig); - const messaging = getMessaging(firebaseApp); - getToken(messaging, { vapidKey }) .then((deviceId) => { store.dispatch(linkDevice(deviceId));