@@ -49,13 +49,6 @@ def username_pattern(cls, value):
49
49
raise ValueError (config .USERNAME_HELPER_TEXT )
50
50
return value .lower ()
51
51
52
- # @validator('password', 'verify_password', pre=True)
53
- # def coerce_to_secret_str(cls, value):
54
- # # This is somewhat redundant, as Pydantic handles coercion to SecretStr,
55
- # if not isinstance(value, SecretStr):
56
- # return SecretStr(value)
57
- # return value
58
-
59
52
@validator ('password' , 'verify_password' , pre = True , each_item = False )
60
53
def password_pattern (cls , value ):
61
54
# Since value is now of type SecretStr, we need to get its actual value
@@ -80,6 +73,11 @@ def passwords_match(cls, v, values, **kwargs):
80
73
"field_name" : "text_input" ,
81
74
"default" : "Default Text" ,
82
75
"validators" : [],
76
+ # "validators": {
77
+ # "_min_length": None,
78
+ # "_max_length": None,
79
+ # "_regex": None,
80
+ # },
83
81
"required" : False ,
84
82
"options" : None ,
85
83
"description" : "This is a text field" ,
@@ -257,70 +255,90 @@ class Config:
257
255
return model
258
256
259
257
260
- def get_form_html (
261
- form_name :str ,
262
- config_path :str = config .FORM_CONFIG_PATH ,
263
- current_document :dict = None
264
- ) -> List [str ]:
265
- pass
258
+ def get_form_html (form_name :str , config_path :str = config .FORM_CONFIG_PATH , current_document :dict = None ) -> List [str ]:
266
259
"""
267
- Generates a list of HTML form fields based on the input config and form name, supporting default values.
260
+ Generates a list of Bootstrap 5 styled HTML form fields based on the input config and form name,
261
+ supporting default values.
268
262
269
263
Params:
270
264
current_document (dict): optional document containing the form's existing data. If passed, it will override
271
265
the default content of the form config.
272
266
273
- Returns: List[str] of HTML elements for front-end
267
+ Returns: List[str] of HTML elements for the front-end
274
268
"""
275
- form_config = load_form_config (config_path = config . FORM_CONFIG_PATH )
269
+ form_config = load_form_config (config_path = config_path )
276
270
277
271
if form_name not in form_config :
278
- raise Exception (f"Form '{ form_name } ' not found in" )
279
-
272
+ raise Exception (f"Form '{ form_name } ' not found in config" )
280
273
281
274
form_html = []
282
275
283
276
for field_name , field_info in form_config [form_name ].items ():
284
-
285
- if current_document :
286
- default = ""
287
- if field_name in current_document ['data' ].keys ():
288
- default = current_document ['data' ][field_name ]
289
- else :
290
- default = field_info .get ("default" )
277
+ default = current_document ['data' ][field_name ] if current_document and field_name in current_document ['data' ] else field_info .get ("default" )
278
+ field_html = ""
291
279
280
+ description_id = f"{ field_name } HelpInline"
292
281
293
282
if field_info ['input_type' ] in ['text' , 'number' , 'email' , 'date' ]:
294
- field_html = f'<label for="{ field_name } ">{ field_name .capitalize ()} :</label>' \
295
- f'<input type="{ field_info ["input_type" ]} " id="{ field_name } " name="{ field_name } " value="{ default or "" } "><br><br>'
283
+ field_html += f'''
284
+ <fieldset class="form-check" style="padding-top: 10px;">
285
+ <label aria-labelledby="{ description_id } " for="{ field_name } " class="form-check-label">{ field_name .replace ("_" , " " ).capitalize ()} </label>
286
+ <span id="{ description_id } " class="form-text">| { field_info ["description" ]} </span>
287
+ <input type="{ field_info ["input_type" ]} " class="form-control" id="{ field_name } " name="{ field_name } " value="{ default or '' } ">
288
+ <div class="valid-feedback"></div>
289
+ <div class="invalid-feedback"></div>
290
+ </fieldset>'''
291
+
296
292
elif field_info ['input_type' ] == 'textarea' :
297
- field_html = f'<label for="{ field_name } ">{ field_name .capitalize ()} :</label><br>' \
298
- f'<textarea id="{ field_name } " name="{ field_name } " rows="4" cols="50">{ default or "" } </textarea><br><br>'
299
-
293
+ field_html += f'''
294
+ <fieldset class="form-check" style="padding-top: 10px;">
295
+ <label aria-labelledby="{ description_id } " for="{ field_name } " class="form-check-label">{ field_name .replace ("_" , " " ).capitalize ()} </label>
296
+ <span id="{ description_id } " class="form-text">| { field_info ["description" ]} </span>
297
+ <textarea class="form-control" id="{ field_name } " name="{ field_name } " rows="4">{ default or '' } </textarea>
298
+ <div class="valid-feedback"></div>
299
+ <div class="invalid-feedback"></div>
300
+ </fieldset>'''
301
+
300
302
elif field_info ['input_type' ] in ['checkbox' , 'radio' ]:
301
- field_html = f'<label>{ field_name .capitalize ()} :</label><br>'
303
+ field_html += f'''
304
+ <fieldset class="form-check" style="padding-top: 10px;">
305
+ <label aria-labelledby="{ description_id } " for="{ field_name } " class="form-check-label">{ field_name .replace ("_" , " " ).capitalize ()} </label>
306
+ <span id="{ description_id } " class="form-text">| { field_info ["description" ]} </span>
307
+ '''
302
308
for option in field_info ['options' ]:
303
309
checked = "checked" if default and (option == default or option in default ) else ""
304
- field_html += f'<input type="{ field_info ["input_type" ]} " id="{ option } " name="{ field_name } " value="{ option } " { checked } >' \
305
- f'<label for="{ option } ">{ option } </label><br>'
306
- field_html += '<br>'
310
+ field_html += f'''
311
+ <div class="form-check { field_info ["input_type" ]} -form-check">
312
+ <input class="form-check-input" type="{ field_info ["input_type" ]} " id="{ option } " name="{ field_name } " value="{ option } " { checked } >
313
+ <label class="form-check-label" for="{ option } ">{ option } </label>
314
+ </div>
315
+ '''
316
+ field_html += f'''
317
+ </fieldset>
318
+ '''
307
319
308
320
elif field_info ['input_type' ] == 'select' :
309
- field_html = f'<label for="{ field_name } ">{ field_name .capitalize ()} :</label>' \
310
- f'<select id="{ field_name } " name="{ field_name } ">'
321
+ field_html += f'''
322
+ <fieldset class="form-check" style="padding-top: 10px;">
323
+ <label aria-labelledby="{ description_id } " for="{ field_name } " class="form-check-label">{ field_name .replace ("_" , " " ).capitalize ()} </label>
324
+ <span id="{ description_id } " class="form-text">| { field_info ["description" ]} </span>
325
+ <select class="form-control" id="{ field_name } " name="{ field_name } ">'''
311
326
for option in field_info ['options' ]:
312
327
selected = "selected" if default and (option == default or option in default ) else ""
313
328
field_html += f'<option value="{ option } " { selected } >{ option } </option>'
314
- field_html += '</select><br><br>'
315
- else :
316
- continue # Skip if the input type is not recognized
317
-
318
- form_html .append (field_html )
329
+ field_html += '''
330
+ </select>
331
+ </fieldset>'''
332
+
333
+ # Skipping file input for now becase it usually doesn't have a default value and handling
334
+ # might be different based on requirements
335
+
336
+ if field_html :
337
+ form_html .append (field_html )
319
338
320
339
return form_html
321
340
322
341
323
-
324
342
class HelpRequest (BaseModel ):
325
343
"""A quick and dirty pydantic model for help request data"""
326
344
subject : str
0 commit comments