@@ -4,7 +4,7 @@ import { getInstance as getD2 } from 'd2'
44import FormBuilder from 'd2-ui/lib/forms/FormBuilder.component.js'
55import { isUrlArray , isRequired } from 'd2-ui/lib/forms/Validators.js'
66import PropTypes from 'prop-types'
7- import React from 'react'
7+ import React , { useState } from 'react'
88import MultiToggle from '../form-fields/multi-toggle.js'
99import TextField from '../form-fields/text-field.js'
1010import styles from './ClientForm.module.css'
@@ -25,6 +25,11 @@ const validateClientID = async (v) => {
2525}
2626
2727const ClientForm = ( { clientModel, onUpdate, onSave, onCancel } ) => {
28+ const [ formErrors , setFormErrors ] = useState ( {
29+ clientId : false ,
30+ redirectUris : false
31+ } ) ;
32+
2833 // Handle both string and array types for authorizationGrantTypes
2934 let authGrantTypesArray = [ ] ;
3035
@@ -65,6 +70,43 @@ const ClientForm = ({ clientModel, onUpdate, onSave, onCancel }) => {
6570 }
6671 }
6772
73+ const handleSave = ( ) => {
74+ // Check fields and show errors if needed
75+ const clientIdEmpty = ! clientModel . clientId || clientModel . clientId . trim ( ) === '' ;
76+ const redirectUrisEmpty = ! formattedRedirectUris || formattedRedirectUris . trim ( ) === '' ;
77+
78+ setFormErrors ( {
79+ clientId : clientIdEmpty ,
80+ redirectUris : redirectUrisEmpty
81+ } ) ;
82+
83+ // Only save if both fields are valid
84+ if ( ! clientIdEmpty && ! redirectUrisEmpty ) {
85+ onSave ( ) ;
86+ }
87+ } ;
88+
89+ // Handle field updates and clear errors
90+ const handleFieldUpdate = ( fieldName , value ) => {
91+ // Clear the error for this field if it has a value
92+ if ( value ) {
93+ // Check if value is a string before using trim()
94+ const isValid = typeof value === 'string'
95+ ? value . trim ( ) . length > 0
96+ : Boolean ( value ) ;
97+
98+ if ( isValid ) {
99+ setFormErrors ( prev => ( {
100+ ...prev ,
101+ [ fieldName ] : false
102+ } ) ) ;
103+ }
104+ }
105+
106+ // Call the original onUpdate function
107+ onUpdate ( fieldName , value ) ;
108+ } ;
109+
68110 const fields = [
69111 {
70112 name : 'clientId' ,
@@ -74,6 +116,7 @@ const ClientForm = ({ clientModel, onUpdate, onSave, onCancel }) => {
74116 floatingLabelText : i18n . t ( 'Client ID' ) ,
75117 style : formFieldStyle ,
76118 changeEvent : 'onBlur' ,
119+ errorText : formErrors . clientId ? i18n . t ( 'Required' ) : null ,
77120 } ,
78121 validators : [
79122 {
@@ -127,6 +170,7 @@ const ClientForm = ({ clientModel, onUpdate, onSave, onCancel }) => {
127170 multiLine : true ,
128171 style : formFieldStyle ,
129172 changeEvent : 'onBlur' ,
173+ errorText : formErrors . redirectUris ? i18n . t ( 'This field should contain a list of URLs' ) : null ,
130174 } ,
131175 validators : [
132176 {
@@ -141,13 +185,17 @@ const ClientForm = ({ clientModel, onUpdate, onSave, onCancel }) => {
141185 clientModel . id === undefined
142186 ? i18n . t ( 'Create new OAuth2 Client' )
143187 : i18n . t ( 'Edit OAuth2 Client' )
188+
144189 return (
145190 < Modal onClose = { onCancel } >
146191 < ModalTitle > { headerText } </ ModalTitle >
147192 < ModalContent >
148- < FormBuilder fields = { fields } onUpdateField = { onUpdate } />
193+ < FormBuilder
194+ fields = { fields }
195+ onUpdateField = { handleFieldUpdate }
196+ />
149197 < div style = { { marginTop : '1rem' } } >
150- < Button primary onClick = { onSave } >
198+ < Button primary onClick = { handleSave } >
151199 { i18n . t ( 'Save' ) }
152200 </ Button >
153201 < Button
0 commit comments