Skip to content

Commit

Permalink
Merge pull request #42 from UgnisSoftware/UGN-252
Browse files Browse the repository at this point in the history
Feature UGN-252 show alert when submitting with errors
  • Loading branch information
masiulis authored Mar 1, 2022
2 parents d11abd6 + 6cda33e commit 5505764
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 16 deletions.
5 changes: 5 additions & 0 deletions src/ReactSpreadsheetImport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ export const ReactSpreadsheetImport = (props: RsiProps) => {
</Providers>
)
}

ReactSpreadsheetImport.defaultProps = {
autoMapHeaders: true,
allowInvalidSubmit: true,
}
5 changes: 3 additions & 2 deletions src/components/Alerts/ConfirmCloseAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,21 @@ interface Props {
}

const EXIT_HEADER_TITLE = "Exit import flow"
const EXIT_BODY_TEXT = "Are you sure? Your current information will not be saved."
const CANCEL_BUTTON = "Cancel"
const EXIT_BUTTON = "Exit flow"

export const ConfirmCloseAlert = ({ isOpen, onClose, onConfirm }: Props) => {
const cancelRef = useRef<HTMLButtonElement | null>(null)

return (
<AlertDialog isOpen={isOpen} onClose={onClose} leastDestructiveRef={cancelRef} isCentered>
<AlertDialog isOpen={isOpen} onClose={onClose} leastDestructiveRef={cancelRef} isCentered id="rsi">
<AlertDialogOverlay>
<AlertDialogContent>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
{EXIT_HEADER_TITLE}
</AlertDialogHeader>
<AlertDialogBody>Are you sure? Your current information will not be saved.</AlertDialogBody>
<AlertDialogBody>{EXIT_BODY_TEXT}</AlertDialogBody>
<AlertDialogFooter>
<Button ref={cancelRef} onClick={onClose} variant="secondary">
{CANCEL_BUTTON}
Expand Down
52 changes: 52 additions & 0 deletions src/components/Alerts/SubmitDataAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
AlertDialog,
AlertDialogBody,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogContent,
AlertDialogOverlay,
Button,
} from "@chakra-ui/react"
import { useRef } from "react"
import { useRsi } from "../../hooks/useRsi"

interface Props {
isOpen: boolean
onClose: () => void
onConfirm: () => void
}

const SUBMIT_HEADER_TITLE = "Errors detected"
const SUBMIT_BODY_TEXT =
"There are still some rows that contain errors. Rows with errors will be ignored when submitting."
const SUBMIT_FORBIDDEN_BODY_TEXT = "There are still some rows containing errors."
const CANCEL_BUTTON = "Cancel"
const FINISH_BUTTON = "Submit"

export const SubmitDataAlert = ({ isOpen, onClose, onConfirm }: Props) => {
const { allowInvalidSubmit } = useRsi()
const cancelRef = useRef<HTMLButtonElement | null>(null)

return (
<AlertDialog isOpen={isOpen} onClose={onClose} leastDestructiveRef={cancelRef} isCentered id="rsi">
<AlertDialogOverlay>
<AlertDialogContent>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
{SUBMIT_HEADER_TITLE}
</AlertDialogHeader>
<AlertDialogBody>{allowInvalidSubmit ? SUBMIT_BODY_TEXT : SUBMIT_FORBIDDEN_BODY_TEXT}</AlertDialogBody>
<AlertDialogFooter>
<Button ref={cancelRef} onClick={onClose} variant="secondary">
{CANCEL_BUTTON}
</Button>
{allowInvalidSubmit && (
<Button onClick={onConfirm} ml={3}>
{FINISH_BUTTON}
</Button>
)}
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialogOverlay>
</AlertDialog>
)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { colorSchemeOverrides, themeOverrides } from "../../../theme"
import { headerSelectionTableFields, mockRsiValues } from "../../../stories/mockRsiValues"
import { SelectHeaderStep } from "../SelectHeaderStep"
import { Providers } from "../../../components/Providers"
Expand Down
27 changes: 25 additions & 2 deletions src/steps/ValidationStep/ValidationStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { Meta } from "./types"
import { addErrorsAndRunHooks, addIndexes } from "./utils/dataMutations"
import { generateColumns } from "./components/columns"
import { Table } from "../../components/Table"
import { SubmitDataAlert } from "../../components/Alerts/SubmitDataAlert"

const VALIDATION_HEADER_TITLE = "Review data"
const BUTTON_TITLE = "Confirm"
Expand All @@ -19,13 +20,14 @@ type Props<T> = {
}

export const ValidationStep = <T,>({ initialData }: Props<T>) => {
const { fields, onSubmit, rowHook, tableHook, initialHook = (table) => table } = useRsi()
const { fields, allowInvalidSubmit, onSubmit, rowHook, tableHook, initialHook = (table) => table } = useRsi()

const [data, setData] = useState<(T & Meta)[]>(
useMemo(() => addErrorsAndRunHooks(addIndexes(initialHook(initialData)), fields, rowHook, tableHook), []),
)
const [selectedRows, setSelectedRows] = useState<ReadonlySet<number | string>>(new Set())
const [filterByErrors, setFilterByErrors] = useState(false)
const [showSubmitAlert, setShowSubmitAlert] = useState(false)

const deleteSelectedRows = () => {
if (selectedRows.size) {
Expand Down Expand Up @@ -53,7 +55,7 @@ export const ValidationStep = <T,>({ initialData }: Props<T>) => {

const rowKeyGetter = useCallback((row: T & Meta) => row.__index, [])

const onContinue = () => {
const submitData = () => {
const all = data.map(({ __index, __errors, ...value }) => ({ ...value })) as unknown as T[]
const validData = all.filter((value, index) => {
const originalValue = data[index]
Expand All @@ -65,9 +67,30 @@ export const ValidationStep = <T,>({ initialData }: Props<T>) => {
const invalidData = all.filter((value) => !validData.includes(value))
onSubmit({ validData, invalidData, all })
}
const onContinue = () => {
const invalidData = data.find((value) => {
if (value?.__errors) {
return !!Object.values(value.__errors)?.filter((err) => err.level === "error").length
}
return false
})
if (!invalidData) {
submitData()
} else {
setShowSubmitAlert(true)
}
}

return (
<>
<SubmitDataAlert
isOpen={showSubmitAlert}
onClose={() => setShowSubmitAlert(false)}
onConfirm={() => {
setShowSubmitAlert(false)
submitData()
}}
/>
<ModalBody pb={0}>
<Box display="flex" justifyContent="space-between" alignItems="center" mb="2rem">
<Heading size="lg" color="gray.700">
Expand Down
2 changes: 1 addition & 1 deletion src/steps/ValidationStep/components/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const generateColumns = <T,>(fields: Fields<T>) => [
placeholder=" "
>
{column.fieldType.options.map((option) => (
<option value={option.value}>{option.label}</option>
<option value={option.value} key={option.value}>{option.label}</option>
))}
</Select>
</Box>
Expand Down
8 changes: 7 additions & 1 deletion src/stories/Default.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ export const Basic = () => {
return (
<>
<Button onClick={onOpen}>Open modal</Button>
<ReactSpreadsheetImport {...mockRsiValues} isOpen={isOpen} onClose={onClose} title="Upload file" />
<ReactSpreadsheetImport
{...mockRsiValues}
isOpen={isOpen}
onClose={onClose}
onSubmit={onClose}
title="Upload file"
/>
</>
)
}
1 change: 1 addition & 0 deletions src/stories/mockRsiValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const mockRsiValues: RsiProps = {
console.log(data)
},
isOpen: true,
allowInvalidSubmit: true,
onClose: () => {},
}

Expand Down
14 changes: 5 additions & 9 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ export type RsiProps<T = any> = {
title?: string
// Specifies maximum number of rows for a single import
maxRecords?: number
// Automatically map imported headers to specified fields if possible
// Automatically map imported headers to specified fields if possible. Default: true
autoMapHeaders?: boolean
// Is modal visible
// Is modal visible.
isOpen: boolean
// Allows submitting with errors. Default: true
allowInvalidSubmit?: boolean
// callback when RSI is closed before final submit
onClose: () => void
// Theme configuration passed to underlying Chakra-UI
Expand Down Expand Up @@ -101,10 +103,4 @@ export type Result<T> = {
validData: T[]
invalidData: T[]
all: T[]
}

export type MaybeConfig = {
allowInvalidSubmit?: boolean
displayEncoding?: boolean
allowCustomFields?: boolean
}
}

0 comments on commit 5505764

Please sign in to comment.