add validationFn to the prompt modal to validate the input

pull/5370/head
yann300 2 years ago
parent 0d30912455
commit f3350afe6a
  1. 14
      apps/remix-ide/src/app/tabs/abstract-provider.tsx
  2. 34
      libs/remix-ui/app/src/lib/remix-app/components/modals/modal-wrapper.tsx
  3. 6
      libs/remix-ui/app/src/lib/remix-app/context/provider.tsx
  4. 6
      libs/remix-ui/app/src/lib/remix-app/interface/index.ts
  5. 1
      libs/remix-ui/app/src/lib/remix-app/reducer/modals.ts
  6. 1
      libs/remix-ui/app/src/lib/remix-app/state/modals.ts
  7. 10
      libs/remix-ui/modal-dialog/src/lib/remix-ui-modal-dialog.tsx
  8. 7
      libs/remix-ui/modal-dialog/src/lib/types/index.ts

@ -58,6 +58,20 @@ export abstract class AbstractProvider extends Plugin {
modalType: ModalTypes.prompt,
okLabel: 'OK',
cancelLabel: 'Cancel',
validationFn: (value) => {
if (!value) return { valid: false, message: "value is empty" }
if (value.startsWith('https://') || value.startsWith('http://')) {
return {
valid: true,
message: ''
}
} else {
return {
valid: false,
message: 'the provided value should contain the protocol ( e.g starts with http:// or https:// )'
}
}
},
okFn: (value: string) => {
setTimeout(() => resolve(value), 0)
},

@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react'
import { ModalDialog, ModalDialogProps } from '@remix-ui/modal-dialog'
import { ModalDialog, ModalDialogProps, ValidationResult } from '@remix-ui/modal-dialog'
import { ModalTypes } from '../../types'
interface ModalWrapperProps extends ModalDialogProps {
@ -29,12 +29,25 @@ const ModalWrapper = (props: ModalWrapperProps) => {
(props.cancelFn) ? props.cancelFn() : props.resolve(false)
}
const createModalMessage = (defaultValue: string) => {
const onInputChanged = (event) => {
if (props.validationFn) {
const validation = props.validationFn(event.target.value)
setState({
...props,
message: createModalMessage(props.defaultValue, validation),
validation
})
}
}
const createModalMessage = (defaultValue: string, validation: ValidationResult) => {
return (
<>
{props.message}
<input type={props.modalType === ModalTypes.password ? 'password' : 'text'} defaultValue={defaultValue} data-id="modalDialogCustomPromp" ref={ref} className="form-control" /></>
)
<input onChange={onInputChanged} type={props.modalType === ModalTypes.password ? 'password' : 'text'} defaultValue={defaultValue} data-id="modalDialogCustomPromp" ref={ref} className="form-control" />
{!validation.valid && <span className='text-warning'>{validation.message}</span>}
</>
)
}
useEffect(() => {
@ -47,7 +60,7 @@ const ModalWrapper = (props: ModalWrapperProps) => {
...props,
okFn: onFinishPrompt,
cancelFn: onCancelFn,
message: createModalMessage(props.defaultValue)
message: createModalMessage(props.defaultValue, { valid: true })
})
break
default:
@ -67,8 +80,17 @@ const ModalWrapper = (props: ModalWrapperProps) => {
}
}, [props])
// reset the message and input if any, so when the modal is shown again it doesn't show the previous value.
const handleHide = () => {
setState({
...props,
message: ''
})
props.handleHide()
}
return (
<ModalDialog id={props.id} {...state} handleHide={props.handleHide} />
<ModalDialog id={props.id} {...state} handleHide={handleHide} />
)
}
export default ModalWrapper

@ -16,11 +16,11 @@ export const ModalProvider = ({ children = [], reducer = modalReducer, initialSt
}
const modal = (modalData: AppModal) => {
const { id, title, message, okLabel, okFn, cancelLabel, cancelFn, modalType, defaultValue, hideFn, data } = modalData
const { id, title, message, validationFn, okLabel, okFn, cancelLabel, cancelFn, modalType, defaultValue, hideFn, data } = modalData
return new Promise((resolve, reject) => {
dispatch({
type: modalActionTypes.setModal,
payload: { id, title, message, okLabel, okFn, cancelLabel, cancelFn, modalType: modalType || ModalTypes.default, defaultValue: defaultValue, hideFn, resolve, next: onNextFn, data }
payload: { id, title, message, okLabel, validationFn, okFn, cancelLabel, cancelFn, modalType: modalType || ModalTypes.default, defaultValue: defaultValue, hideFn, resolve, next: onNextFn, data }
})
})
}
@ -32,7 +32,7 @@ export const ModalProvider = ({ children = [], reducer = modalReducer, initialSt
const handleHideModal = () => {
dispatch({
type: modalActionTypes.handleHideModal,
payload: null
payload: null,
})
}

@ -1,10 +1,16 @@
import { ModalTypes } from '../types'
export type ValidationResult = {
valid: boolean,
message?: string
}
export interface AppModal {
id: string
timestamp?: number
hide?: boolean
title: string
validationFn?: (value: string) => ValidationResult
// eslint-disable-next-line no-undef
message: string | JSX.Element
okLabel: string

@ -11,6 +11,7 @@ export const modalReducer = (state: ModalState = ModalInitialState, action: Moda
id: action.payload.id || timestamp.toString(),
hide: false,
title: action.payload.title,
validationFn: action.payload.validationFn,
message: action.payload.message,
okLabel: action.payload.okLabel,
okFn: action.payload.okFn,

@ -8,6 +8,7 @@ export const ModalInitialState: ModalState = {
hide: true,
title: '',
message: '',
validationFn: () => { return {valid: true, message: ''} },
okLabel: '',
okFn: () => { },
cancelLabel: '',

@ -96,18 +96,20 @@ export const ModalDialog = (props: ModalDialogProps) => {
</div>
<div className="modal-footer" data-id={`${props.id}ModalDialogModalFooter-react`}>
{/* todo add autofocus ^^ */}
{ props.okLabel && <span
{ props.okLabel && <button
data-id={`${props.id}-modal-footer-ok-react`}
className={'modal-ok btn btn-sm ' + (state.toggleBtn ? 'btn-dark' : 'btn-light')}
disabled={props.validation && !props.validation.valid}
onClick={() => {
if (props.validation && !props.validation.valid) return
if (props.okFn) props.okFn()
handleHide()
}}
>
{props.okLabel ? props.okLabel : 'OK'}
</span>
</button>
}
{ props.cancelLabel && <span
{ props.cancelLabel && <button
data-id={`${props.id}-modal-footer-cancel-react`}
className={'modal-cancel btn btn-sm ' + (state.toggleBtn ? 'btn-light' : 'btn-dark')}
data-dismiss="modal"
@ -117,7 +119,7 @@ export const ModalDialog = (props: ModalDialogProps) => {
}}
>
{props.cancelLabel ? props.cancelLabel : 'Cancel'}
</span>
</button>
}
</div>
</div>

@ -1,8 +1,15 @@
export type ValidationResult = {
valid: boolean,
message?: string
}
/* eslint-disable no-undef */
export interface ModalDialogProps {
id: string
timestamp?: number,
title?: string,
validation?: ValidationResult
validationFn?: (value: string) => ValidationResult
message?: string | JSX.Element,
okLabel?: string,
okFn?: (value?:any) => void,

Loading…
Cancel
Save