github.com/argoproj/argo-cd@v1.8.7/ui/src/app/settings/components/project-details/resource-lists-panel.tsx (about) 1 import {AutocompleteField, FormField, Tooltip} from 'argo-ui'; 2 import * as React from 'react'; 3 import {FormApi} from 'react-form'; 4 5 import {EditablePanel} from '../../../shared/components'; 6 import {GroupKind, Groups, Project, ProjectSpec, ResourceKinds} from '../../../shared/models'; 7 8 function removeEl(items: any[], index: number) { 9 return items.slice(0, index).concat(items.slice(index + 1)); 10 } 11 12 function helpTip(text: string) { 13 return ( 14 <Tooltip content={text}> 15 <span style={{fontSize: 'smaller'}}> 16 {' '} 17 <i className='fa fa-question-circle' /> 18 </span> 19 </Tooltip> 20 ); 21 } 22 23 type field = keyof ProjectSpec; 24 25 const infoByField: {[type: string]: {title: string; helpText: string}} = { 26 clusterResourceWhitelist: { 27 title: 'cluster resource allow list', 28 helpText: 'Cluster-scoped K8s API Groups and Kinds which are permitted to be deployed' 29 }, 30 clusterResourceBlacklist: { 31 title: 'cluster resource deny list', 32 helpText: 'Cluster-scoped K8s API Groups and Kinds which are not permitted to be deployed' 33 }, 34 namespaceResourceWhitelist: { 35 title: 'namespace resource allow list', 36 helpText: 'Namespace-scoped K8s API Groups and Kinds which are permitted to deploy' 37 }, 38 namespaceResourceBlacklist: { 39 title: 'namespace resource deny list', 40 helpText: 'Namespace-scoped K8s API Groups and Kinds which are prohibited from being deployed' 41 } 42 }; 43 44 function viewList(type: field, proj: Project) { 45 const info = infoByField[type]; 46 const list = proj.spec[type] as Array<GroupKind>; 47 return ( 48 <React.Fragment> 49 <p className='project-details__list-title'> 50 {info.title} {helpTip(info.helpText)} 51 </p> 52 {(list || []).length > 0 ? ( 53 <React.Fragment> 54 <div className='row white-box__details-row'> 55 <div className='columns small-4'>Kind</div> 56 <div className='columns small-8'>Group</div> 57 </div> 58 {list.map((resource, i) => ( 59 <div className='row white-box__details-row' key={i}> 60 <div className='columns small-4'>{resource.kind}</div> 61 <div className='columns small-8'>{resource.group}</div> 62 </div> 63 ))} 64 </React.Fragment> 65 ) : ( 66 <p>The {info.title} is empty</p> 67 )} 68 </React.Fragment> 69 ); 70 } 71 72 function editList(type: field, formApi: FormApi) { 73 const info = infoByField[type]; 74 75 return ( 76 <React.Fragment> 77 <p className='project-details__list-title'> 78 {info.title} {helpTip(info.helpText)} 79 </p> 80 <div className='row white-box__details-row'> 81 <div className='columns small-4'>Kind</div> 82 <div className='columns small-8'>Group</div> 83 </div> 84 {(formApi.values.spec[type] || []).map((_: Project, i: number) => ( 85 <div className='row white-box__details-row' key={i}> 86 <div className='columns small-4'> 87 <FormField 88 formApi={formApi} 89 field={`spec.${type}[${i}].kind`} 90 component={AutocompleteField} 91 componentProps={{items: ResourceKinds, filterSuggestions: true}} 92 /> 93 </div> 94 <div className='columns small-8'> 95 <FormField formApi={formApi} field={`spec.${type}[${i}].group`} component={AutocompleteField} componentProps={{items: Groups, filterSuggestions: true}} /> 96 </div> 97 <i className='fa fa-times' onClick={() => formApi.setValue(`spec.${type}`, removeEl(formApi.values.spec[type], i))} /> 98 </div> 99 ))} 100 <button className='argo-button argo-button--short' onClick={() => formApi.setValue(`spec.${type}`, (formApi.values.spec[type] || []).concat({group: '*', kind: '*'}))}> 101 ADD RESOURCE 102 </button> 103 </React.Fragment> 104 ); 105 } 106 107 export const ResourceListsPanel = ({proj, saveProject, title}: {proj: Project; title?: React.ReactNode; saveProject?: (proj: Project) => any}) => ( 108 <EditablePanel 109 save={saveProject} 110 values={proj} 111 view={ 112 <React.Fragment> 113 {title} 114 {Object.keys(infoByField).map(key => ( 115 <React.Fragment key={key}>{viewList(key as field, proj)}</React.Fragment> 116 ))} 117 </React.Fragment> 118 } 119 edit={ 120 saveProject && 121 (formApi => ( 122 <React.Fragment> 123 {title} 124 {Object.keys(infoByField).map(key => ( 125 <React.Fragment key={key}>{editList(key as field, formApi)}</React.Fragment> 126 ))} 127 </React.Fragment> 128 )) 129 } 130 items={[]} 131 /> 132 );