Skip to content

Commit

Permalink
Merge pull request #2423 from target/ts-conversion-CreateAlertDialog
Browse files Browse the repository at this point in the history
ui/alerts: convert CreateAlertDialog, CreateAlertForm, and useCreateAlerts to ts
  • Loading branch information
tony-tvu authored Jun 17, 2022
2 parents 7f03c45 + b306611 commit c9e3a2c
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
import React, { useState, useEffect } from 'react'
import p from 'prop-types'
import {
Button,
Grid,
Stepper,
Step,
StepLabel,
Typography,
Theme,
} from '@mui/material'
import makeStyles from '@mui/styles/makeStyles'
import { makeStyles } from '@mui/styles'
import OpenInNewIcon from '@mui/icons-material/OpenInNew'
import _ from 'lodash'

import { useCreateAlerts } from './useCreateAlerts'
import { fieldErrors, allErrors } from '../../util/errutil'
import { fieldErrors } from '../../util/errutil'
import FormDialog from '../../dialogs/FormDialog'
import { CreateAlertForm } from './StepContent/CreateAlertForm'
import { CreateAlertReview } from './StepContent/CreateAlertReview'
import AppLink from '../../util/AppLink'

const pluralize = (num) => (num !== 1 ? 's' : '')
export interface Value {
summary: string
details: string
serviceIDs: string[]
}

const pluralize = (num: number): string => (num !== 1 ? 's' : '')

const useStyles = makeStyles((theme) => ({
const useStyles = makeStyles((theme: Theme) => ({
dialog: {
[theme.breakpoints.up('md')]: {
height: '65vh',
Expand All @@ -32,10 +38,13 @@ const useStyles = makeStyles((theme) => ({
},
}))

export default function CreateAlertDialog(props) {
export default function CreateAlertDialog(props: {
onClose: () => void
serviceID: string
}): JSX.Element {
const classes = useStyles()
const [step, setStep] = useState(0)
const [value, setValue] = useState({
const [value, setValue] = useState<Value>({
summary: '',
details: '',
serviceIDs: props.serviceID ? [props.serviceID] : [],
Expand All @@ -60,7 +69,7 @@ export default function CreateAlertDialog(props) {
? ['Alert Info', 'Confirm']
: ['Alert Info', 'Service Selection', 'Confirm']

const onNext = () => {
const onNext = (): void => {
if (currentStep === 0 && props.serviceID) {
setStep(currentStep + 2)
} else if (currentStep < 2) {
Expand All @@ -76,8 +85,8 @@ export default function CreateAlertDialog(props) {
.map((a) => a.id)
.value()

const failedServices = allErrors(error).map((e) => ({
id: getSvcID(e.path),
const failedServices = fieldErrors(error).map((e) => ({
id: getSvcID(e.path ? e.path[1] : ''),
message: e.message,
}))

Expand Down Expand Up @@ -143,7 +152,7 @@ export default function CreateAlertDialog(props) {
<CreateAlertForm
activeStep={currentStep}
value={value}
onChange={(newValue) => setValue(newValue)}
onChange={(newValue: Value) => setValue(newValue)}
disabled={loading}
errors={fieldErrors(error)}
/>
Expand All @@ -156,8 +165,3 @@ export default function CreateAlertDialog(props) {
/>
)
}

CreateAlertDialog.propTypes = {
onClose: p.func.isRequired,
serviceID: p.string,
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react'
import { FormContainer, FormField } from '../../../forms'
import { CreateAlertInfo } from './CreateAlertInfo'
import { CreateAlertServiceSelect } from './CreateAlertServiceSelect'
import { CreateAlertConfirm } from './CreateAlertConfirm'
import { Value } from '../CreateAlertDialog'

// TODO: extend FormContainer once that file has been converted to typescript
interface CreateAlertFormProps {
activeStep: number
value: Value

errors: Error[]

onChange?: (newValue: Value) => void
disabled?: boolean

mapValue?: () => void
mapOnChangeValue?: () => void

// Enables functionality to remove an incoming value at it's index from
// an array field if the new value is falsey.
removeFalseyIdxs?: boolean
}

// TODO: remove this interface once FormContainer.js has been converted to TS
interface Error {
message: string
field: string
helpLink?: string
}

export function CreateAlertForm({
activeStep,
...otherProps
}: CreateAlertFormProps): JSX.Element {
return (
<FormContainer optionalLabels {...otherProps}>
{activeStep === 0 && <CreateAlertInfo />}
{activeStep === 1 && (
<FormField
required
render={(props) => <CreateAlertServiceSelect {...props} />}
name='serviceIDs'
/>
)}
{activeStep === 2 && <CreateAlertConfirm />}
</FormContainer>
)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import { gql, useMutation } from '@apollo/client'

import {
DocumentNode,
gql,
MutationFunction,
MutationResult,
useMutation,
} from '@apollo/client'
import { fieldAlias, mergeFields, mapInputVars } from '../../util/graphql'
import { GraphQLClientWithErrors } from '../../apollo'
import { Value } from './CreateAlertDialog'

interface Variable {
summary: string
details: string
serviceID: string
}

const baseMutation = gql`
mutation CreateAlertMutation($input: CreateAlertInput!) {
Expand All @@ -11,23 +23,28 @@ const baseMutation = gql`
}
`

const getAliasedMutation = (mutation, index) =>
const getAliasedMutation = (
mutation: DocumentNode,
index: string | number,
): DocumentNode =>
mapInputVars(fieldAlias(mutation, 'alias' + index), {
input: 'input' + index,
})

// useCreateAlerts will return mutation, status and a function for mapping
// field/paths from the response to the respective service ID.
export const useCreateAlerts = (value) => {
export const useCreateAlerts = (
value: Value,
): [MutationFunction, MutationResult, (alias: string | number) => string] => {
// 1. build mutation
let m = getAliasedMutation(baseMutation, 0)
for (let i = 1; i < value.serviceIDs.length; i++) {
m = mergeFields(m, getAliasedMutation(baseMutation, i))
}

// 2. build variables, alias -> service ID map
const variables = {}
const aliasIDMap = {}
const variables: { [key: string]: Variable } = {}
const aliasIDMap: { [key: string]: string } = {}
value.serviceIDs.forEach((svcID, i) => {
aliasIDMap['alias' + i] = svcID
variables[`input${i}`] = {
Expand All @@ -43,5 +60,5 @@ export const useCreateAlerts = (value) => {
client: GraphQLClientWithErrors,
})

return [mutate, status, (alias) => aliasIDMap[alias]]
return [mutate, status, (alias: string | number) => aliasIDMap[alias]]
}
3 changes: 3 additions & 0 deletions web/src/app/dialogs/FormDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ FormDialog.propTypes = {

// make dialog fill vertical space
fullHeight: p.bool,

// gets spread to material-ui
PaperProps: p.object,
}

FormDialog.defaultProps = {
Expand Down
2 changes: 1 addition & 1 deletion web/src/app/util/errutil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export function fieldErrors(err?: ApolloError): FieldError[] {
}

// allErrors will return a flat list of all errors in the graphQL error.
export function allErrors(err?: ApolloError): Error[] {
export function allErrors(err?: ApolloError): (FieldError | Error)[] {
if (!err) return []
return nonFieldErrors(err).concat(fieldErrors(err))
}
Expand Down

0 comments on commit c9e3a2c

Please sign in to comment.