Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions functions/src/emailNotifications/createEmail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const getResourceLabelFromNotificationType = (type: NotificationType) => {
return 'research'
case 'howto_useful':
case 'howto_mention':
case 'new_comment':
return 'how-to'
}
}
Expand Down
33 changes: 33 additions & 0 deletions functions/src/emailNotifications/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,41 @@
import * as functions from 'firebase-functions'
import { createNotificationEmails } from './createEmail'
import { db } from '../Firebase/firestoreDB'
import { DB_ENDPOINTS, IUserDB } from '../models'

/** Trigger daily process to send any pending email notifications */
exports.sendDaily = functions.pubsub
// Trigger daily at 5pm (https://crontab.guru/#0_17_*_*_*)
.schedule('0 17 * * *')
.onRun(async () => createNotificationEmails())

exports.sendOnce = functions.https.onCall(async (_, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called while authenticated.',
)
}
// Validate user exists and has admin status before triggering function.
const { uid } = context.auth
const user = await db.collection(DB_ENDPOINTS.users).doc(uid).get()
if (user.exists) {
const { userRoles } = user.data() as IUserDB
if (userRoles?.some((role) => ['admin', 'super-admin'].includes(role))) {
try {
await createNotificationEmails()
return 'OK'
} catch (error) {
console.error(error)
throw new functions.https.HttpsError(
'internal',
'There was an error creating emails.',
)
}
}
}
throw new functions.https.HttpsError(
'permission-denied',
'Emails can be triggered by admins only.',
)
})
18 changes: 17 additions & 1 deletion src/modules/admin/pages/adminNotifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import styled from '@emotion/styled'
import { observer } from 'mobx-react'
import { NotificationItem } from 'oa-components'
import { useCallback, useEffect, useState } from 'react'
import { Box, Text } from 'theme-ui'
import { Box, Button, Text } from 'theme-ui'
import { useDB } from 'src/App'
import type { INotification, IPendingEmails } from 'src/models'
import { getFormattedNotificationMessage } from 'src/pages/common/Header/getFormattedNotifications'
import Table from '../components/Table/Table'
import type { ICellRenderProps, ITableProps } from '../components/Table/Table'
import { functions } from 'src/utils/firebase'

type IPendingEmailsDBDoc = Record<string, IPendingEmails>

Expand All @@ -33,6 +34,9 @@ const NotificationListContainer = styled(Box)`
const AdminNotifictions = observer(() => {
const { db } = useDB()
const [emailsPending, setEmailsPending] = useState<IPendingEmails[]>([])
const [triggerEmailState, setTriggerEmailState] = useState<string>(
'Click the button to trigger emails.',
)

// Load list of pending approvals on mount only, dependencies empty to avoid reloading
useEffect(() => {
Expand All @@ -55,6 +59,16 @@ const AdminNotifictions = observer(() => {
})
}, [])

const triggerEmails = async () => {
setTriggerEmailState('Sending...')
try {
await functions.httpsCallable('emailNotifications-sendOnce')()
setTriggerEmailState('Emails sent successfully.')
} catch (error) {
setTriggerEmailState(`Error sending emails: \n ${error}`)
}
}

/** Function applied to render each table row cell */
const RenderContent: React.FC<ICellRenderProps> = (
props: ICellRenderProps,
Expand Down Expand Up @@ -82,6 +96,8 @@ const AdminNotifictions = observer(() => {
<>
<h2>Admin Notifictions</h2>
<h4>Pending Emails</h4>
<Button onClick={triggerEmails}>Trigger Test Emails</Button>
{triggerEmailState && <p>{triggerEmailState}</p>}
<Table
data={emailsPending}
columns={EMAILS_PENDING_COLUMNS}
Expand Down