add validationFn to the prompt modal to validate the input

pull/2547/head
yann300 2 years ago
parent 1e7665734f
commit 9367e03483
  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, modalType: ModalTypes.prompt,
okLabel: 'OK', okLabel: 'OK',
cancelLabel: 'Cancel', 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) => { okFn: (value: string) => {
setTimeout(() => resolve(value), 0) setTimeout(() => resolve(value), 0)
}, },

@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react' 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' import { ModalTypes } from '../../types'
interface ModalWrapperProps extends ModalDialogProps { interface ModalWrapperProps extends ModalDialogProps {
@ -29,12 +29,25 @@ const ModalWrapper = (props: ModalWrapperProps) => {
(props.cancelFn) ? props.cancelFn() : props.resolve(false) (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 ( return (
<> <>
{props.message} {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(() => { useEffect(() => {
@ -47,7 +60,7 @@ const ModalWrapper = (props: ModalWrapperProps) => {
...props, ...props,
okFn: onFinishPrompt, okFn: onFinishPrompt,
cancelFn: onCancelFn, cancelFn: onCancelFn,
message: createModalMessage(props.defaultValue) message: createModalMessage(props.defaultValue, { valid: true })
}) })
break break
default: default:
@ -67,8 +80,17 @@ const ModalWrapper = (props: ModalWrapperProps) => {
} }
}, [props]) }, [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 ( return (
<ModalDialog id={props.id} {...state} handleHide={props.handleHide} /> <ModalDialog id={props.id} {...state} handleHide={handleHide} />
) )
} }
export default ModalWrapper export default ModalWrapper

@ -16,11 +16,11 @@ export const ModalProvider = ({ children = [], reducer = modalReducer, initialSt
} }
const modal = (modalData: AppModal) => { 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) => { return new Promise((resolve, reject) => {
dispatch({ dispatch({
type: modalActionTypes.setModal, 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 = () => { const handleHideModal = () => {
dispatch({ dispatch({
type: modalActionTypes.handleHideModal, type: modalActionTypes.handleHideModal,
payload: null payload: null,
}) })
} }

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

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

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

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

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

Loading…
Cancel
Save