Skip to content

Commit

Permalink
fix logic
Browse files Browse the repository at this point in the history
Signed-off-by: James Talton <jtalton@redhat.com>
  • Loading branch information
jamestalton committed Jan 13, 2022
1 parent 61a169e commit 0d365d3
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 75 deletions.
4 changes: 2 additions & 2 deletions src/FormWizard.tsx
Expand Up @@ -41,7 +41,7 @@ import { FormWizardContext, InputEditMode, InputMode } from './contexts/FormWiza
import { FormWizardItemContext } from './contexts/FormWizardItemContext'
import { FormWizardValidationContext } from './contexts/FormWizardValidationContext'
import './FormWizard.css'
import { isFormWizardHiddenProps, wizardInputHasValidationErrors } from './inputs/FormWizardInput'
import { isHidden, wizardInputHasValidationErrors } from './inputs/FormWizardInput'

Handlebars.registerHelper('if_eq', function (this: unknown, arg1: string, arg2: string, options: HelperOptions) {
return arg1 == arg2 ? options.fn(this) : options.inverse(this)
Expand Down Expand Up @@ -271,7 +271,7 @@ export function FormWizardWizardMode(props: { data: object; children: ReactNode;
Children.forEach(props.children, (child) => {
if (!isValidElement(child)) return
if (child.type !== FormWizardStep) return
if (isFormWizardHiddenProps(child.props, item)) return
if (isHidden(child, item)) return

const stepHasValidationErrors = wizardInputHasValidationErrors(child, item)

Expand Down
4 changes: 2 additions & 2 deletions src/FormWizardSection.tsx
Expand Up @@ -3,7 +3,7 @@ import { Fragment, ReactNode, useContext } from 'react'
import { FormWizardLabelHelp } from './components/FormWizardLabelHelp'
import { FormWizardContext, InputMode } from './contexts/FormWizardContext'
import { FormWizardItemContext } from './contexts/FormWizardItemContext'
import { inputHasValue, isFormWizardHiddenProps } from './inputs/FormWizardInput'
import { inputHasValue, useInputHidden } from './inputs/FormWizardInput'

interface FormWizardSectionProps {
label: string
Expand All @@ -27,7 +27,7 @@ export function FormWizardSection(props: FormWizardSectionProps) {
}
}

const hidden = isFormWizardHiddenProps(props, item)
const hidden = useInputHidden(props)
if (hidden) return <Fragment />

if (formWizardContext.mode === InputMode.Details) {
Expand Down
28 changes: 28 additions & 0 deletions src/contexts/ShowValidationProvider.tsx
@@ -0,0 +1,28 @@
import { createContext, ReactNode, useContext, useState } from 'react'

/*
Show validation is used to indicate is that controls shoud show validation.
Initially it is false, but on a wizard step upon clicking next validation should show for that step.
When a wizard gets to the review step, validation errors for the whole wizard should show.
*/

const SetShowValidationContext = createContext<(show: boolean) => void>(() => null)
export function useSetShowValidation() {
return useContext(SetShowValidationContext)
}

const ShowValidationContext = createContext(false)
export function useShowValidation() {
return useContext(ShowValidationContext)
}

export function ShowValidationProvider(props: { children?: ReactNode }) {
const [showValidation, setShowValidation] = useState(false)
const parentShowValidationContext = useContext(ShowValidationContext)
const activeShowValidation = showValidation || parentShowValidationContext
return (
<SetShowValidationContext.Provider value={setShowValidation}>
<ShowValidationContext.Provider value={activeShowValidation}>{props.children}</ShowValidationContext.Provider>
</SetShowValidationContext.Provider>
)
}
132 changes: 61 additions & 71 deletions src/inputs/FormWizardInput.ts
Expand Up @@ -6,6 +6,8 @@ import { FormWizardContext, IFormWizardContext } from '../contexts/FormWizardCon
import { FormWizardItemContext } from '../contexts/FormWizardItemContext'
import { FormWizardValidationContext } from '../contexts/FormWizardValidationContext'

export type HiddenFn = (item: any) => boolean

export type InputCommonProps<ValueT = any> = {
id: string
path?: string
Expand All @@ -14,7 +16,6 @@ export type InputCommonProps<ValueT = any> = {
required?: boolean
readonly?: boolean
disabled?: boolean

label: string
labelHelp?: string
labelHelpTitle?: string
Expand Down Expand Up @@ -70,48 +71,82 @@ export function useInputValidation(props: Pick<InputCommonProps, 'id' | 'path' |

export function useInputHidden(props: { hidden?: (item: any) => boolean }) {
const item = useContext(FormWizardItemContext)
const hidden = props.hidden ? props.hidden(item) : false
return hidden
return props.hidden ? props.hidden(item) : false
}

export function isFormWizardHiddenProps(props: unknown, item: unknown) {
if (!props) return false

const hidden = (props as InputCommonProps).hidden
if (typeof hidden === 'boolean') return hidden
export function isHidden(reactElement: ReactElement, item: any) {
const hidden = (reactElement.props as { hidden?: HiddenFn }).hidden
if (typeof hidden === 'function') {
try {
const result = hidden(item)
if (typeof result === 'boolean') return result
if (result === true) return true
} catch {
// Do nothing
}
}

const children = (props as { children?: ReactNode }).children

if (typeof children === 'function') {
// DO NOTHING
} else if (children) {
let allChildrenHidden = true
Children.forEach(children, (child) => {
if (!allChildrenHidden) return
if (!isValidElement(child)) {
allChildrenHidden = false
return
let allChildrenHidden = true
switch (reactElement.type) {
case FormWizardArrayInput: {
const items = wizardArrayItems(reactElement.props, item)
for (const item of items) {
Children.forEach(reactElement.props.children, (child) => {
if (!allChildrenHidden) return
if (!isValidElement(child)) {
allChildrenHidden = false
return
}
if (!isHidden(child, item)) {
allChildrenHidden = false
}
})
}
if (!isFormWizardHiddenProps(child.props, item)) {
break
}
case FormWizardSelector: {
const selectorItem = wizardSelectorItem(reactElement.props, item)
if (selectorItem) {
Children.forEach(reactElement.props.children, (child) => {
if (!allChildrenHidden) return
if (!isValidElement(child)) {
allChildrenHidden = false
return
}
if (!isHidden(child, selectorItem)) {
allChildrenHidden = false
}
})
}
break
}
default: {
if (reactElement.props.children === 'function') {
allChildrenHidden = false
} else if (reactElement.props.children === undefined) {
allChildrenHidden = false
} else {
Children.forEach(reactElement.props.children, (child) => {
if (!allChildrenHidden) return
if (!isValidElement(child)) {
allChildrenHidden = false
return
}
if (!isHidden(child, item)) {
allChildrenHidden = false
}
})
}
})
return allChildrenHidden
break
}
}
return false

return allChildrenHidden
}

export function wizardInputHasValidationErrors(reactElement: ReactElement, item: any): boolean {
if (isHidden(reactElement, item)) return false

const { props } = reactElement
if (isFormWizardHiddenProps(props, item)) return false

switch (reactElement.type) {
case FormWizardArrayInput:
Expand Down Expand Up @@ -166,51 +201,6 @@ export function wizardInputHasValidationErrors(reactElement: ReactElement, item:
return false
}

export function hasValidationErrorsProps(props: InputCommonProps, item: unknown): boolean {
if (!props) return false
if (isFormWizardHiddenProps(props, item)) return false

const id = props.id
const path = props.path ?? id

if (path) {
if (item && typeof item === 'object') {
const value = get(item, path) as unknown

const required = props.required
if (required && !value) {
return true
}

const validation = props.validation
if (typeof validation === 'function') {
try {
const result = validation(value)
if (typeof result === 'string') return true
} catch {
// Do nothing
}
}
}
}

const children = (props as { children?: ReactNode }).children
if (children) {
let anyChildrenHasValidationErrors = false
Children.forEach(children, (child) => {
if (anyChildrenHasValidationErrors) return
if (!isValidElement(child)) return
if (isFormWizardHiddenProps(child.props, item)) return
if (hasValidationErrorsProps(child.props as InputCommonProps, item)) {
anyChildrenHasValidationErrors = true
}
})
return anyChildrenHasValidationErrors
}

return false
}

export function inputHasValue(props: unknown, item: unknown) {
const path = (props as InputCommonProps).path
if (path !== undefined) {
Expand All @@ -236,7 +226,7 @@ export function inputHasValue(props: unknown, item: unknown) {
Children.forEach(children, (child) => {
if (anyChildHasValue) return
if (!isValidElement(child)) return
if (isFormWizardHiddenProps(child.props, item)) return
if (isHidden(child, item)) return
if (inputHasValue(child.props, item)) {
anyChildHasValue = true
}
Expand Down

0 comments on commit 0d365d3

Please sign in to comment.