Skip to content

Commit

Permalink
Merge pull request #2815 from target/feat/slack-dm-ui
Browse files Browse the repository at this point in the history
slack: add UI for Slack DM contact method type (experimental)
  • Loading branch information
mastercactapus authored Feb 23, 2023
2 parents 1dcdf4c + df8ca07 commit 4cbad91
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 8 deletions.
13 changes: 13 additions & 0 deletions notification/slack/cache.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package slack

import (
"sync"
"time"

"github.com/golang/groupcache/lru"
Expand All @@ -9,6 +10,12 @@ import (
type ttlCache[K comparable, V any] struct {
*lru.Cache
ttl time.Duration

// We use a mutex to protect the cache from concurrent access
// as this is not handled by the lru package.
//
// See https://github.com/golang/groupcache/issues/87#issuecomment-338494548
mx sync.Mutex
}

func newTTLCache[K comparable, V any](maxEntries int, ttl time.Duration) *ttlCache[K, V] {
Expand All @@ -24,13 +31,19 @@ type cacheItem[V any] struct {
}

func (c *ttlCache[K, V]) Add(key lru.Key, value V) {
c.mx.Lock()
defer c.mx.Unlock()

c.Cache.Add(key, cacheItem[V]{
value: value,
expires: time.Now().Add(c.ttl),
})
}

func (c *ttlCache[K, V]) Get(key K) (val V, ok bool) {
c.mx.Lock()
defer c.mx.Unlock()

item, ok := c.Cache.Get(key)
if !ok {
return val, false
Expand Down
9 changes: 8 additions & 1 deletion web/src/app/users/UserContactMethodCreateDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useConfigValue } from '../util/RequireConfig'
import { Dialog, DialogTitle, DialogActions, Button } from '@mui/material'
import DialogContentError from '../dialogs/components/DialogContentError'
import { ContactMethodType } from '../../schema'
import { useExpFlag } from '../util/useExpFlag'

type Value = {
name: string
Expand Down Expand Up @@ -40,19 +41,25 @@ export default function UserContactMethodCreateDialog(props: {
title?: string
subtitle?: string
}): JSX.Element {
const [allowSV, allowE, allowW] = useConfigValue(
const [allowSV, allowE, allowW, allowS] = useConfigValue(
'Twilio.Enable',
'SMTP.Enable',
'Webhook.Enable',
'Slack.Enable',
)
const allowSFlag = useExpFlag('slack-dm')

let typeVal: ContactMethodType = 'VOICE'
if (allowSV) {
typeVal = 'SMS'
} else if (allowE) {
typeVal = 'EMAIL'
} else if (allowW) {
typeVal = 'WEBHOOK'
} else if (allowS && allowSFlag) {
typeVal = 'SLACK_DM'
}

// values for contact method form
const [CMValue, setCMValue] = useState<Value>({
name: '',
Expand Down
44 changes: 37 additions & 7 deletions web/src/app/users/UserContactMethodForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MenuItem, Typography } from '@mui/material'
import { ContactMethodType } from '../../schema'
import { useConfigValue } from '../util/RequireConfig'
import { FieldError } from '../util/errutil'
import { useExpFlag } from '../util/useExpFlag'

type Value = {
name: string
Expand Down Expand Up @@ -72,6 +73,22 @@ function renderURLField(edit: boolean): JSX.Element {
)
}

function renderSlackField(edit: boolean): JSX.Element {
return (
<FormField
fullWidth
name='value'
required
label='Slack Member ID'
placeholder='member ID'
component={TextField}
disabled={edit}
// @ts-expect-error TS2322 -- FormField has not been converted to ts, and inferred type is incorrect.
helperText='Go to your Slack profile, click the three dots, and select "Copy member ID".'
/>
)
}

function renderTypeField(type: ContactMethodType, edit: boolean): JSX.Element {
switch (type) {
case 'SMS':
Expand All @@ -81,6 +98,8 @@ function renderTypeField(type: ContactMethodType, edit: boolean): JSX.Element {
return renderEmailField(edit)
case 'WEBHOOK':
return renderURLField(edit)
case 'SLACK_DM':
return renderSlackField(edit)
default:
}

Expand All @@ -105,13 +124,21 @@ export default function UserContactMethodForm(
): JSX.Element {
const { value, edit = false, ...other } = props

const [smsVoiceEnabled, emailEnabled, webhookEnabled, disclaimer] =
useConfigValue(
'Twilio.Enable',
'SMTP.Enable',
'Webhook.Enable',
'General.NotificationDisclaimer',
)
const [
smsVoiceEnabled,
emailEnabled,
webhookEnabled,
slackEnabled,
disclaimer,
] = useConfigValue(
'Twilio.Enable',
'SMTP.Enable',
'Webhook.Enable',
'Slack.Enable',
'General.NotificationDisclaimer',
)

const slackDMEnabled = useExpFlag('slack-dm')

return (
<FormContainer
Expand Down Expand Up @@ -154,6 +181,9 @@ export default function UserContactMethodForm(
{(edit || webhookEnabled) && (
<MenuItem value='WEBHOOK'>WEBHOOK</MenuItem>
)}
{(edit || (slackEnabled && slackDMEnabled)) && (
<MenuItem value='SLACK_DM'>SLACK DM</MenuItem>
)}
</FormField>
</Grid>
<Grid item xs={12}>
Expand Down
5 changes: 5 additions & 0 deletions web/src/app/users/UserContactMethodList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import AppLink from '../util/AppLink'
import { styles as globalStyles } from '../styles/materialStyles'
import { UserContactMethod } from '../../schema'
import UserContactMethodCreateDialog from './UserContactMethodCreateDialog'
import { useExpFlag } from '../util/useExpFlag'

const query = gql`
query cmList($id: ID!) {
Expand Down Expand Up @@ -61,6 +62,7 @@ export default function UserContactMethodList(
const [showEditDialogByID, setShowEditDialogByID] = useState('')
const [showDeleteDialogByID, setShowDeleteDialogByID] = useState('')
const [showSendTestByID, setShowSendTestByID] = useState('')
const hasSlackDM = useExpFlag('slack-dm')

const { loading, error, data } = useQuery(query, {
variables: {
Expand Down Expand Up @@ -102,6 +104,9 @@ export default function UserContactMethodList(
},
]

// don't show send test for slack DMs if disabled
if (cm.type === 'SLACK_DM' && !hasSlackDM) return actions

if (!cm.disabled) {
actions.push({
label: 'Send Test',
Expand Down

0 comments on commit 4cbad91

Please sign in to comment.