@@ -6,7 +6,10 @@ import { useParams } from 'next/navigation';
66import {
77 Checkbox ,
88 Combobox ,
9+ FormLayout ,
10+ Labelled ,
911 Select ,
12+ Spinner ,
1013 Text ,
1114 TextField ,
1215 toast ,
@@ -302,6 +305,14 @@ export default function AIModelDetailsPage() {
302305 const handleSave = ( overrideData ?: any ) => {
303306 setStatus ( 'saving' ) ;
304307 const dataToUse = overrideData || formData ;
308+
309+ // Ensure access type is always 'open' (required field)
310+ if ( dataToUse . accessType !== 'open' ) {
311+ toast ( 'Open access is required for all models' ) ;
312+ setStatus ( 'unsaved' ) ;
313+ return ;
314+ }
315+
305316 const updateData : any = {
306317 description : dataToUse . description ,
307318 modelType : dataToUse . modelType ,
@@ -399,35 +410,41 @@ export default function AIModelDetailsPage() {
399410 ] ;
400411
401412 if ( AIModelData . isLoading ) {
402- return < div className = "p-6" > Loading...</ div > ;
413+ return (
414+ < div className = "flex items-center justify-center p-6" >
415+ < Spinner size = { 32 } />
416+ </ div >
417+ ) ;
403418 }
404419
405420 return (
406421 < div className = "flex flex-col gap-4 py-6" >
407422 { /* Model Type & Domain - side by side */ }
408- < div className = "grid grid-cols-2 gap-4" >
409- < Select
410- name = "modelType"
411- label = "Model Type"
412- options = { modelTypeOptions }
413- value = { formData . modelType }
414- onChange = { ( value ) => {
415- handleInputChange ( 'modelType' , value ) ;
416- handleSave ( { ...formData , modelType : value } ) ;
417- } }
418- required
419- />
420- < Select
421- name = "domain"
422- label = "Domain"
423- options = { domainOptions }
424- value = { formData . domain }
425- onChange = { ( value ) => {
426- handleInputChange ( 'domain' , value ) ;
427- handleSave ( { ...formData , domain : value } ) ;
428- } }
429- />
430- </ div >
423+ < FormLayout >
424+ < FormLayout . Group >
425+ < Select
426+ name = "modelType"
427+ label = "Model Type"
428+ options = { modelTypeOptions }
429+ value = { formData . modelType }
430+ onChange = { ( value ) => {
431+ handleInputChange ( 'modelType' , value ) ;
432+ handleSave ( { ...formData , modelType : value } ) ;
433+ } }
434+ required
435+ />
436+ < Select
437+ name = "domain"
438+ label = "Domain"
439+ options = { domainOptions }
440+ value = { formData . domain }
441+ onChange = { ( value ) => {
442+ handleInputChange ( 'domain' , value ) ;
443+ handleSave ( { ...formData , domain : value } ) ;
444+ } }
445+ />
446+ </ FormLayout . Group >
447+ </ FormLayout >
431448
432449 { /* Description */ }
433450 < RichTextEditor
@@ -440,26 +457,28 @@ export default function AIModelDetailsPage() {
440457 />
441458
442459 { /* Target Users & Intended Use - side by side */ }
443- < div className = "grid grid-cols-2 gap-4" >
444- < TextField
445- name = "targetUsers"
446- label = "Target Users"
447- value = { formData . targetUsers }
448- onChange = { ( value ) => handleInputChange ( 'targetUsers' , value ) }
449- onBlur = { ( ) => handleSave ( ) }
450- multiline = { 3 }
451- required
452- />
453- < TextField
454- name = "intendedUse"
455- label = "Intended Use"
456- value = { formData . intendedUse }
457- onChange = { ( value ) => handleInputChange ( 'intendedUse' , value ) }
458- onBlur = { ( ) => handleSave ( ) }
459- multiline = { 3 }
460- required
461- />
462- </ div >
460+ < FormLayout >
461+ < FormLayout . Group >
462+ < TextField
463+ name = "targetUsers"
464+ label = "Target Users"
465+ value = { formData . targetUsers }
466+ onChange = { ( value ) => handleInputChange ( 'targetUsers' , value ) }
467+ onBlur = { ( ) => handleSave ( ) }
468+ multiline = { 3 }
469+ required
470+ />
471+ < TextField
472+ name = "intendedUse"
473+ label = "Intended Use"
474+ value = { formData . intendedUse }
475+ onChange = { ( value ) => handleInputChange ( 'intendedUse' , value ) }
476+ onBlur = { ( ) => handleSave ( ) }
477+ multiline = { 3 }
478+ required
479+ />
480+ </ FormLayout . Group >
481+ </ FormLayout >
463482
464483 { /* Sectors */ }
465484 < Combobox
@@ -503,114 +522,127 @@ export default function AIModelDetailsPage() {
503522 />
504523
505524 { /* Maximum Tokens & Languages - side by side */ }
506- < div className = "grid grid-cols-2 gap-4" >
507- < Select
508- name = "maxTokens"
509- label = "Maximum Tokens"
510- options = { maxTokensOptions }
511- value = { formData . maxTokens }
512- onChange = { ( value ) => {
513- handleInputChange ( 'maxTokens' , value ) ;
514- handleSave ( { ...formData , maxTokens : value } ) ;
515- } }
516- required
517- />
518- < Combobox
519- displaySelected
520- name = "supportedLanguages"
521- list = { languageOptions }
522- label = "Languages"
523- key = { `languages-${ formData . supportedLanguages . length } ` }
524- selectedValue = { formData . supportedLanguages }
525- onChange = { ( value ) => {
526- handleInputChange ( 'supportedLanguages' , value ) ;
527- handleSave ( { ...formData , supportedLanguages : value } ) ;
528- } }
529- required
530- />
531- </ div >
525+ < FormLayout >
526+ < FormLayout . Group >
527+ < Select
528+ name = "maxTokens"
529+ label = "Maximum Tokens"
530+ options = { maxTokensOptions }
531+ value = { formData . maxTokens }
532+ onChange = { ( value ) => {
533+ handleInputChange ( 'maxTokens' , value ) ;
534+ handleSave ( { ...formData , maxTokens : value } ) ;
535+ } }
536+ required
537+ />
538+ < Combobox
539+ displaySelected
540+ name = "supportedLanguages"
541+ list = { languageOptions }
542+ label = "Languages"
543+ key = { `languages-${ formData . supportedLanguages . length } ` }
544+ selectedValue = { formData . supportedLanguages }
545+ onChange = { ( value ) => {
546+ handleInputChange ( 'supportedLanguages' , value ) ;
547+ handleSave ( { ...formData , supportedLanguages : value } ) ;
548+ } }
549+ required
550+ />
551+ </ FormLayout . Group >
552+ </ FormLayout >
532553
533554 { /* Model Website & Locations/Geography - side by side */ }
534- < div className = "grid grid-cols-2 gap-4" >
535- < TextField
536- name = "modelWebsite"
537- label = "Model Website"
538- value = { formData . modelWebsite }
539- onChange = { ( value ) => handleInputChange ( 'modelWebsite' , value ) }
540- onBlur = { handleWebsiteBlur }
541- placeholder = "www.model.com"
542- required
543- />
544- < Combobox
545- displaySelected
546- name = "geographies"
547- list = {
548- getGeographiesList . data ?. geographies ?. map ( ( item : any ) => ( {
549- label : `${ item . name } ${ item . parentId ? ` (${ item . parentId . name } )` : '' } ` ,
550- value : item . id ,
551- } ) ) || [ ]
552- }
553- key = { `geographies-${ getGeographiesList . data ?. geographies ?. length || 0 } -${ formData . geographies . length } ` }
554- label = "Locations / Geography"
555- selectedValue = { formData . geographies }
556- onChange = { ( value ) => {
557- handleInputChange ( 'geographies' , value ) ;
558- handleSave ( { ...formData , geographies : value } ) ;
559- } }
560- />
561- </ div >
555+ < FormLayout >
556+ < FormLayout . Group >
557+ < TextField
558+ name = "modelWebsite"
559+ label = "Model Website"
560+ value = { formData . modelWebsite }
561+ onChange = { ( value ) => handleInputChange ( 'modelWebsite' , value ) }
562+ onBlur = { handleWebsiteBlur }
563+ placeholder = "www.model.com"
564+ required
565+ />
566+ < Combobox
567+ displaySelected
568+ name = "geographies"
569+ list = {
570+ getGeographiesList . data ?. geographies ?. map ( ( item : any ) => ( {
571+ label : `${ item . name } ${ item . parentId ? ` (${ item . parentId . name } )` : '' } ` ,
572+ value : item . id ,
573+ } ) ) || [ ]
574+ }
575+ key = { `geographies-${ getGeographiesList . data ?. geographies ?. length || 0 } -${ formData . geographies . length } ` }
576+ label = "Locations / Geography"
577+ selectedValue = { formData . geographies }
578+ onChange = { ( value ) => {
579+ handleInputChange ( 'geographies' , value ) ;
580+ handleSave ( { ...formData , geographies : value } ) ;
581+ } }
582+ />
583+ </ FormLayout . Group >
584+ </ FormLayout >
562585
563586 { /* Usage License & Access Type - side by side */ }
564- < div className = "grid grid-cols-2 gap-4" >
565- < Select
566- name = "usageLicense"
567- label = "Usage License"
568- options = { licenseOptions }
569- value = { formData . usageLicense }
570- onChange = { ( value ) => {
571- handleInputChange ( 'usageLicense' , value ) ;
572- handleSave ( { ...formData , usageLicense : value } ) ;
573- } }
574- />
575- < div >
576- < label className = "mb-2 block text-sm font-medium" >
577- Select Access Type
578- </ label >
579- < div className = "flex gap-6" >
580- < Checkbox
581- name = "accessType"
582- checked = { formData . accessType === 'open' }
583- onChange = { ( ) => {
584- handleInputChange ( 'accessType' , 'open' ) ;
585- handleSave ( { ...formData , accessType : 'open' } ) ;
586- } }
587- >
588- < div className = "flex flex-col gap-1" >
589- < Text > Open Access</ Text >
590- < Text >
591- Model can be viewed and used by everyone
592- </ Text >
593- </ div >
594- </ Checkbox >
595- < Checkbox
596- name = "isRestricted"
597- checked = { false }
598- defaultChecked = { false }
599- disabled
600- >
601- < div className = "flex flex-col gap-1" title = "Coming Soon" >
602- < Text className = "text-textDisabled" >
603- Restricted Access
604- </ Text >
605- < Text className = "text-iconDisabled" >
606- Users would require to request access to the model.
607- Recommended for sensitive models.
608- </ Text >
609- </ div >
610- </ Checkbox >
611- </ div >
612- </ div >
613- </ div >
587+ < FormLayout >
588+ < FormLayout . Group >
589+ < Select
590+ name = "usageLicense"
591+ label = "Usage License"
592+ options = { licenseOptions }
593+ value = { formData . usageLicense }
594+ onChange = { ( value ) => {
595+ handleInputChange ( 'usageLicense' , value ) ;
596+ handleSave ( { ...formData , usageLicense : value } ) ;
597+ } }
598+ />
599+ < Labelled
600+ id = "accessType"
601+ label = "Select Access Type"
602+ requiredIndicator
603+ error = {
604+ formData . accessType !== 'open'
605+ ? 'Open access is required for all models'
606+ : undefined
607+ }
608+ >
609+ < div className = "flex gap-6" >
610+ < Checkbox
611+ name = "accessType"
612+ checked = { formData . accessType === 'open' }
613+ onChange = { ( ) => {
614+ handleInputChange ( 'accessType' , 'open' ) ;
615+ handleSave ( { ...formData , accessType : 'open' } ) ;
616+ } }
617+ required
618+ >
619+ < div className = "flex flex-col gap-1" >
620+ < Text > Open Access</ Text >
621+ < Text >
622+ Model can be viewed and used by everyone
623+ </ Text >
624+ </ div >
625+ </ Checkbox >
626+ < Checkbox
627+ name = "isRestricted"
628+ checked = { false }
629+ defaultChecked = { false }
630+ disabled
631+ >
632+ < div className = "flex flex-col gap-1" title = "Coming Soon" >
633+ < Text className = "text-textDisabled" >
634+ Restricted Access
635+ </ Text >
636+ < Text className = "text-iconDisabled" >
637+ Users would require to request access to the model.
638+ Recommended for sensitive models.
639+ </ Text >
640+ </ div >
641+ </ Checkbox >
642+ </ div >
643+ </ Labelled >
644+ </ FormLayout . Group >
645+ </ FormLayout >
614646 </ div >
615647 ) ;
616648}
0 commit comments