diff --git a/__tests__/__snapshots__/storyshots.test.js.snap b/__tests__/__snapshots__/storyshots.test.js.snap
index a8653fec1..4b76d7a0e 100644
--- a/__tests__/__snapshots__/storyshots.test.js.snap
+++ b/__tests__/__snapshots__/storyshots.test.js.snap
@@ -1,5 +1,122 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`Storyshots Component/QueryInfo Basic 1`] = `
+
{
+ it('should display successful state', () => {
+ expect.assertions(1)
+
+ render(
+
+ )
+
+ expect(screen.getByText('Submitted successfully')).toBeInTheDocument()
+ })
+
+ it('should display loading state', () => {
+ expect.assertions(1)
+
+ render(
+
+ )
+
+ expect(screen.getByText('Loading message...')).toBeInTheDocument()
+ })
+
+ it('should display error state', () => {
+ expect.assertions(1)
+
+ render(
+
+ )
+
+ expect(
+ screen.getByText('An error occurred. Please try again.')
+ ).toBeInTheDocument()
+ })
+
+ it('should render nothing when there is no data, error, and loading', () => {
+ expect.assertions(2)
+
+ render(
+
+ )
+
+ expect(
+ screen.queryByText('Submitted the item successfully!')
+ ).not.toBeInTheDocument()
+ expect(screen.queryByText('Loading message...')).not.toBeInTheDocument()
+ })
+})
diff --git a/components/QueryInfo/QueryInfo.tsx b/components/QueryInfo/QueryInfo.tsx
new file mode 100644
index 000000000..37ebdc71f
--- /dev/null
+++ b/components/QueryInfo/QueryInfo.tsx
@@ -0,0 +1,67 @@
+import { get } from 'lodash'
+import React from 'react'
+import { Spinner } from 'react-bootstrap'
+import styles from '../../scss/queryInfo.module.scss'
+import Alert from '../Alert'
+
+type QueryInfo
= {
+ data: T
+ loading: boolean
+ error: string
+ texts: {
+ loading: string
+ data: string
+ }
+ dismiss?: {
+ onDismissError?: (id: number) => void
+ onDismissData?: (id: number) => void
+ }
+}
+
+const QueryInfo = ({
+ data,
+ loading,
+ error,
+ texts,
+ dismiss
+}: QueryInfo) => {
+ if (loading) {
+ return (
+
+
+ {texts.loading}
+
+ )
+ }
+
+ if (error) {
+ return (
+
+ )
+ }
+
+ if (data) {
+ return (
+
+ )
+ }
+
+ return <>>
+}
+
+export default QueryInfo
diff --git a/components/QueryInfo/index.tsx b/components/QueryInfo/index.tsx
new file mode 100644
index 000000000..b2454455e
--- /dev/null
+++ b/components/QueryInfo/index.tsx
@@ -0,0 +1 @@
+export { default } from './QueryInfo'
diff --git a/components/admin/lessons/AdminLessonInputs/AdminLessonInputs.test.js b/components/admin/lessons/AdminLessonInputs/AdminLessonInputs.test.js
index 4537e0b0d..2316ad86f 100644
--- a/components/admin/lessons/AdminLessonInputs/AdminLessonInputs.test.js
+++ b/components/admin/lessons/AdminLessonInputs/AdminLessonInputs.test.js
@@ -109,7 +109,7 @@ describe('AdminLessonInputs component', () => {
it('Should add module', async () => {
expect.assertions(1)
- const { getByText, getByTestId, container } = render(
+ const { getByText, getByTestId } = render(
{
await waitFor(() =>
expect(
- container.querySelector('.octicon-check-circle')
+ getByText('Added the item Functions successfully!')
).toBeInTheDocument()
)
})
@@ -142,7 +142,7 @@ describe('AdminLessonInputs component', () => {
it('Should update module', async () => {
expect.assertions(1)
- const { getByText, getByTestId, container } = render(
+ const { getByText, getByTestId } = render(
{
await waitFor(() =>
expect(
- container.querySelector('.octicon-check-circle')
+ getByText('Updated the item Functions successfully!')
).toBeInTheDocument()
)
})
@@ -176,7 +176,7 @@ describe('AdminLessonInputs component', () => {
it('Should display error message if inputs are empty', async () => {
expect.assertions(1)
- const { getByText, getByTestId, container } = render(
+ const { getByText, getByTestId } = render(
@@ -189,14 +189,16 @@ describe('AdminLessonInputs component', () => {
await userEvent.click(submit)
await waitFor(() =>
- expect(container.querySelector('.octicon-alert-fill')).toBeInTheDocument()
+ expect(
+ getByText('An error occurred. Please try again.')
+ ).toBeInTheDocument()
)
})
it('Should display error message if network or GraphQL error', async () => {
expect.assertions(1)
- const { getByText, getByTestId, container } = render(
+ const { getByText, getByTestId } = render(
@@ -213,7 +215,9 @@ describe('AdminLessonInputs component', () => {
await userEvent.click(submit)
await waitFor(() =>
- expect(container.querySelector('.octicon-alert-fill')).toBeInTheDocument()
+ expect(
+ getByText('An error occurred. Please try again.')
+ ).toBeInTheDocument()
)
})
@@ -458,7 +462,66 @@ describe('AdminLessonInputs component', () => {
await userEvent.click(submit)
await waitFor(() =>
- expect(getByText('Updated the module successfully!')).toBeInTheDocument()
+ expect(getByText('Updated the item successfully!')).toBeInTheDocument()
+ )
+ })
+
+ it('Should dismiss success message', async () => {
+ expect.assertions(1)
+
+ const { getByText, getByTestId, queryByText, getByLabelText } = render(
+
+ {}}
+ />
+
+ )
+
+ await userEvent.type(getByTestId('input0'), 'Functions', {
+ delay: 1
+ })
+ await userEvent.type(getByTestId('input2'), '1', {
+ delay: 1
+ })
+ await userEvent.type(getByTestId('textbox'), 'Functions are cool', {
+ delay: 1
+ })
+
+ const submit = getByText('ADD MODULE')
+ await userEvent.click(submit)
+
+ await userEvent.click(getByLabelText('Close alert'))
+
+ await waitFor(() =>
+ expect(
+ queryByText('Added the item Functions successfully!')
+ ).not.toBeInTheDocument()
+ )
+ })
+
+ it('Should dismiss error message', async () => {
+ expect.assertions(1)
+
+ const { getByText, getByTestId, queryByText, getByLabelText } = render(
+
+
+
+ )
+
+ await userEvent.clear(getByTestId('input0'))
+ await userEvent.clear(getByTestId('textbox'))
+
+ const submit = getByText('ADD MODULE')
+ await userEvent.click(submit)
+
+ await userEvent.click(getByLabelText('Close alert'))
+
+ await waitFor(() =>
+ expect(
+ queryByText('An error occurred. Please try again.')
+ ).not.toBeInTheDocument()
)
})
})
diff --git a/components/admin/lessons/AdminLessonInputs/AdminLessonInputs.tsx b/components/admin/lessons/AdminLessonInputs/AdminLessonInputs.tsx
index 19fb6b995..36f79f479 100644
--- a/components/admin/lessons/AdminLessonInputs/AdminLessonInputs.tsx
+++ b/components/admin/lessons/AdminLessonInputs/AdminLessonInputs.tsx
@@ -7,15 +7,14 @@ import {
} from '../../../../graphql'
import { formChange } from '../../../../helpers/formChange'
import { FormCard, MD_INPUT, Option, TextField } from '../../../FormCard'
-import { AlertFillIcon, CheckCircleIcon } from '@primer/octicons-react'
import styles from './adminLessonInputs.module.scss'
-import { Spinner } from 'react-bootstrap'
-import { get } from 'lodash'
+import { get, isEqual } from 'lodash'
import {
ApolloError,
OperationVariables,
ApolloQueryResult
} from '@apollo/client'
+import QueryInfo from '../../../QueryInfo'
type Module = { id: number; name: string; content: string; order: number }
@@ -96,6 +95,12 @@ const AdminModuleInputs = ({
})
: useAddModuleMutation({ variables: mutationVariables })
+ const [dataDiff, setDataDiff] = useState(data)
+ useEffect(
+ () => setDataDiff(prev => (isEqual(data, prev) ? undefined : data)),
+ [data]
+ )
+
const [errorMsg, setErrorMsg] = useState(get(error, 'message', ''))
const handleChange = async (value: string, propertyIndex: number) => {
@@ -148,49 +153,33 @@ const AdminModuleInputs = ({
}
}
- const QueryStateMessage = () => {
- if (loading) {
- return (
-
-
- Adding the module...
-
- )
- }
-
- if (errorMsg) {
- return (
-
-
-
Failed to add the module: {errorMsg}
-
- )
- }
+ const dataText = () => {
+ const updateModule = get(data, 'updateModule')
+ const addModule = get(data, 'addModule')
- if (data) {
- const updateModule = get(data, 'updateModule')
- const addModule = get(data, 'addModule')
-
- return (
-
-
-
- {updateModule ? 'Updated' : 'Added'} the module{' '}
-
- {get(addModule, 'name') || get(updateModule, 'name') || ''}
- {' '}
- successfully!
-
-
- )
- }
-
- return <>>
+ return `${updateModule ? 'Updated' : 'Added'} the item ${
+ get(addModule, 'name') || get(updateModule, 'name') || ''
+ } successfully!`
}
return (
-
+ {
+ setErrorMsg('')
+ setDataDiff(undefined)
+ },
+ onDismissData: () => {}
+ }}
+ />
(
+
+)
+
+export const BasicWithDismiss = () => (
+ {}
+ }}
+ />
+)
+
+export const Error = () => (
+
+)
+
+export const ErrorWithDismiss = () => (
+ {}
+ }}
+ />
+)
+
+export const _WithLoading = () => (
+
+)