@@ -12,7 +12,7 @@ import FileInput from 'components/FileInput/FileInput.react';
1212import GeoPointInput from 'components/GeoPointInput/GeoPointInput.react' ;
1313import Label from 'components/Label/Label.react' ;
1414import Modal from 'components/Modal/Modal.react' ;
15- import NonPrintableHighlighter from 'components/NonPrintableHighlighter/NonPrintableHighlighter.react' ;
15+ import NonPrintableHighlighter , { hasNonPrintableChars , getNonPrintableCharsFromJson , hasNonAlphanumericChars , getNonAlphanumericCharsFromJson , getRegexValidation , getRegexValidationFromJson } from 'components/NonPrintableHighlighter/NonPrintableHighlighter.react' ;
1616import Option from 'components/Dropdown/Option.react' ;
1717import Parse from 'parse' ;
1818import React from 'react' ;
@@ -28,7 +28,6 @@ import LoaderContainer from 'components/LoaderContainer/LoaderContainer.react';
2828import ServerConfigStorage from 'lib/ServerConfigStorage' ;
2929import { CurrentApp } from 'context/currentApp' ;
3030
31- const CONFIG_KEY = 'config.settings' ;
3231const FORMATTING_CONFIG_KEY = 'config.formatting.syntax' ;
3332
3433const PARAM_TYPES = [ 'Boolean' , 'String' , 'Number' , 'Date' , 'Object' , 'Array' , 'GeoPoint' , 'File' ] ;
@@ -51,7 +50,7 @@ const EDITORS = {
5150 < Toggle type = { Toggle . Types . TRUE_FALSE } value = { ! ! value } onChange = { onChange } />
5251 ) ,
5352 String : ( value , onChange , wordWrap , syntaxColors , options = { } ) => (
54- < NonPrintableHighlighter value = { value } detectNonPrintable = { ! ! options . detectNonPrintable } detectNonAlphanumeric = { true } detectRegex = { ! ! options . detectRegex } >
53+ < NonPrintableHighlighter value = { value } detectNonPrintable = { ! ! options . detectNonPrintable } detectNonAlphanumeric = { ! ! options . detectNonAlphanumeric } detectRegex = { ! ! options . detectRegex } >
5554 < TextInput multiline = { true } value = { value || '' } onChange = { onChange } />
5655 </ NonPrintableHighlighter >
5756 ) ,
@@ -60,7 +59,7 @@ const EDITORS = {
6059 ) ,
6160 Date : ( value , onChange ) => < DateTimeInput fixed = { true } value = { value } onChange = { onChange } /> ,
6261 Object : ( value , onChange , wordWrap , syntaxColors , options = { } ) => (
63- < NonPrintableHighlighter value = { value } isJson = { true } detectNonPrintable = { ! ! options . detectNonPrintable } detectNonAlphanumeric = { true } detectRegex = { ! ! options . detectRegex } >
62+ < NonPrintableHighlighter value = { value } isJson = { true } detectNonPrintable = { ! ! options . detectNonPrintable } detectNonAlphanumeric = { ! ! options . detectNonAlphanumeric } detectRegex = { ! ! options . detectRegex } >
6463 < JsonEditor
6564 value = { value || '' }
6665 onChange = { onChange }
@@ -71,7 +70,7 @@ const EDITORS = {
7170 </ NonPrintableHighlighter >
7271 ) ,
7372 Array : ( value , onChange , wordWrap , syntaxColors , options = { } ) => (
74- < NonPrintableHighlighter value = { value } isJson = { true } detectNonPrintable = { ! ! options . detectNonPrintable } detectNonAlphanumeric = { true } detectRegex = { ! ! options . detectRegex } >
73+ < NonPrintableHighlighter value = { value } isJson = { true } detectNonPrintable = { ! ! options . detectNonPrintable } detectNonAlphanumeric = { ! ! options . detectNonAlphanumeric } detectRegex = { ! ! options . detectRegex } >
7574 < JsonEditor
7675 value = { value || '' }
7776 onChange = { onChange }
@@ -129,8 +128,6 @@ export default class ConfigDialog extends React.Component {
129128 wordWrap : false ,
130129 error : null ,
131130 syntaxColors : null ,
132- detectNonPrintable : true ,
133- detectRegex : true ,
134131 } ;
135132 if ( props . param . length > 0 ) {
136133 let initialValue = props . value ;
@@ -147,15 +144,12 @@ export default class ConfigDialog extends React.Component {
147144 wordWrap : false ,
148145 error : initialError ,
149146 syntaxColors : null ,
150- detectNonPrintable : true ,
151- detectRegex : true ,
152147 } ;
153148 }
154149 }
155150
156151 componentDidMount ( ) {
157152 this . loadSyntaxColors ( ) ;
158- this . loadValueAnalysisSettings ( ) ;
159153 }
160154
161155 async loadSyntaxColors ( ) {
@@ -175,24 +169,21 @@ export default class ConfigDialog extends React.Component {
175169 }
176170 }
177171
178- async loadValueAnalysisSettings ( ) {
179- try {
180- const serverStorage = new ServerConfigStorage ( this . context ) ;
181- if ( serverStorage . isServerConfigEnabled ( ) ) {
182- const settings = await serverStorage . getConfig (
183- CONFIG_KEY ,
184- this . context . applicationId
185- ) ;
186- if ( settings ?. detectNonPrintable !== undefined ) {
187- this . setState ( { detectNonPrintable : ! ! settings . detectNonPrintable } ) ;
188- }
189- if ( settings ?. detectRegex !== undefined ) {
190- this . setState ( { detectRegex : ! ! settings . detectRegex } ) ;
191- }
192- }
193- } catch {
194- // Silently fail - keep defaults (true)
172+ getEffectiveDetectionFlags ( ) {
173+ const isExistingParam = this . props . param && this . props . param . length > 0 ;
174+ let detectNonPrintable = this . props . detectNonPrintable ;
175+ if ( detectNonPrintable && isExistingParam && this . props . nonPrintableShowOnlyFor . length > 0 ) {
176+ detectNonPrintable = this . props . nonPrintableShowOnlyFor . includes ( this . props . param ) ;
177+ }
178+ let detectNonAlphanumeric = this . props . detectNonAlphanumeric ;
179+ if ( detectNonAlphanumeric && isExistingParam && this . props . nonAlphanumericShowOnlyFor . length > 0 ) {
180+ detectNonAlphanumeric = this . props . nonAlphanumericShowOnlyFor . includes ( this . props . param ) ;
195181 }
182+ let detectRegex = this . props . detectRegex ;
183+ if ( detectRegex && isExistingParam && this . props . regexShowOnlyFor . length > 0 ) {
184+ detectRegex = this . props . regexShowOnlyFor . includes ( this . props . param ) ;
185+ }
186+ return { detectNonPrintable, detectNonAlphanumeric, detectRegex } ;
196187 }
197188
198189 valid ( ) {
@@ -201,32 +192,41 @@ export default class ConfigDialog extends React.Component {
201192 }
202193 switch ( this . state . type ) {
203194 case 'String' :
204- return ! ! this . state . value ;
195+ if ( ! this . state . value ) {
196+ return false ;
197+ }
198+ break ;
205199 case 'Number' :
206- return ! isNaN ( parseFloat ( this . state . value ) ) ;
200+ if ( isNaN ( parseFloat ( this . state . value ) ) ) {
201+ return false ;
202+ }
203+ break ;
207204 case 'Date' :
208- return ! isNaN ( new Date ( this . state . value ) ) ;
205+ if ( isNaN ( new Date ( this . state . value ) ) ) {
206+ return false ;
207+ }
208+ break ;
209209 case 'Object' :
210210 try {
211211 const obj = JSON . parse ( this . state . value ) ;
212- if ( obj && typeof obj === 'object' ) {
213- return true ;
212+ if ( ! obj || typeof obj !== 'object' || Array . isArray ( obj ) ) {
213+ return false ;
214214 }
215- return false ;
216215 } catch {
217216 return false ;
218217 }
218+ break ;
219219 case 'Array' :
220220 try {
221221 const obj = JSON . parse ( this . state . value ) ;
222- if ( obj && Array . isArray ( obj ) ) {
223- return true ;
222+ if ( ! obj || ! Array . isArray ( obj ) ) {
223+ return false ;
224224 }
225- return false ;
226225 } catch {
227226 return false ;
228227 }
229- case 'GeoPoint' :
228+ break ;
229+ case 'GeoPoint' : {
230230 const val = this . state . value ;
231231 if ( ! val || typeof val !== 'object' ) {
232232 return false ;
@@ -242,14 +242,81 @@ export default class ConfigDialog extends React.Component {
242242 ) {
243243 return false ;
244244 }
245- return true ;
246- case 'File' :
245+ break ;
246+ }
247+ case 'File' : {
247248 const fileVal = this . state . value ;
248- if ( fileVal && fileVal . url ( ) ) {
249- return true ;
249+ if ( ! fileVal || ! fileVal . url ( ) ) {
250+ return false ;
250251 }
251- return false ;
252+ break ;
253+ }
254+ }
255+
256+ // Compute effective detection flags (respecting show-only-for settings)
257+ const { detectNonPrintable, detectNonAlphanumeric, detectRegex } = this . getEffectiveDetectionFlags ( ) ;
258+
259+ // Block save if non-printable characters detected for this param
260+ if (
261+ detectNonPrintable &&
262+ this . props . param . length > 0 &&
263+ this . props . nonPrintableBlockSave . includes ( this . props . param )
264+ ) {
265+ const value = this . state . value ;
266+ if ( value && typeof value === 'string' ) {
267+ if ( this . state . type === 'Object' || this . state . type === 'Array' ) {
268+ if ( getNonPrintableCharsFromJson ( value ) . totalCount > 0 ) {
269+ return false ;
270+ }
271+ } else if ( this . state . type === 'String' ) {
272+ if ( hasNonPrintableChars ( value ) ) {
273+ return false ;
274+ }
275+ }
276+ }
277+ }
278+
279+ // Block save if non-alphanumeric characters detected for this param
280+ if (
281+ detectNonAlphanumeric &&
282+ this . props . param . length > 0 &&
283+ this . props . nonAlphanumericBlockSave . includes ( this . props . param )
284+ ) {
285+ const value = this . state . value ;
286+ if ( value && typeof value === 'string' ) {
287+ if ( this . state . type === 'Object' || this . state . type === 'Array' ) {
288+ if ( getNonAlphanumericCharsFromJson ( value ) . totalCount > 0 ) {
289+ return false ;
290+ }
291+ } else if ( this . state . type === 'String' ) {
292+ if ( hasNonAlphanumericChars ( value ) ) {
293+ return false ;
294+ }
295+ }
296+ }
252297 }
298+
299+ // Block save if regex validation fails for this param
300+ if (
301+ detectRegex &&
302+ this . props . param . length > 0 &&
303+ this . props . regexBlockSave . includes ( this . props . param )
304+ ) {
305+ const value = this . state . value ;
306+ if ( value && typeof value === 'string' ) {
307+ if ( this . state . type === 'Object' || this . state . type === 'Array' ) {
308+ const result = getRegexValidationFromJson ( value ) ;
309+ if ( result . results . some ( r => ! r . isValid ) ) {
310+ return false ;
311+ }
312+ } else if ( this . state . type === 'String' ) {
313+ if ( ! getRegexValidation ( value ) . isValid ) {
314+ return false ;
315+ }
316+ }
317+ }
318+ }
319+
253320 return true ;
254321 }
255322
@@ -346,6 +413,13 @@ export default class ConfigDialog extends React.Component {
346413 this . setState ( { selectedIndex : index , value } ) ;
347414 } ;
348415
416+ // Determine effective detection flags based on show-only-for settings
417+ const {
418+ detectNonPrintable : effectiveDetectNonPrintable ,
419+ detectNonAlphanumeric : effectiveDetectNonAlphanumeric ,
420+ detectRegex : effectiveDetectRegex ,
421+ } = this . getEffectiveDetectionFlags ( ) ;
422+
349423 const dialogContent = (
350424 < div >
351425 < Field
@@ -372,7 +446,7 @@ export default class ConfigDialog extends React.Component {
372446 value => this . setState ( { value, error : null } ) ,
373447 this . state . wordWrap ,
374448 this . state . syntaxColors ,
375- { detectNonPrintable : this . state . detectNonPrintable , detectRegex : this . state . detectRegex }
449+ { detectNonPrintable : effectiveDetectNonPrintable , detectNonAlphanumeric : effectiveDetectNonAlphanumeric , detectRegex : effectiveDetectRegex }
376450 ) }
377451 />
378452
0 commit comments