github.com/argoproj/argo-cd/v2@v2.10.9/ui/src/app/settings/components/projects-list/projects-list.tsx (about) 1 import {FormField, NotificationType, SlidingPanel} from 'argo-ui'; 2 import * as React from 'react'; 3 import {Form, FormApi, Text} from 'react-form'; 4 5 import {DataLoader, EmptyState, ErrorNotification, Page, Query} from '../../../shared/components'; 6 import {Consumer} from '../../../shared/context'; 7 import {Project} from '../../../shared/models'; 8 import {services} from '../../../shared/services'; 9 10 export class ProjectsList extends React.Component { 11 private formApi: FormApi; 12 13 public render() { 14 return ( 15 <Consumer> 16 {ctx => ( 17 <Page 18 title='Projects' 19 toolbar={{ 20 breadcrumbs: [{title: 'Settings', path: '/settings'}, {title: 'Projects'}], 21 actionMenu: { 22 className: 'fa fa-plus', 23 items: [{title: 'New Project', iconClassName: 'fa fa-plus', action: () => ctx.navigation.goto('.', {add: true}, {replace: true})}] 24 } 25 }}> 26 <div className='projects argo-container'> 27 <DataLoader load={() => services.projects.list()}> 28 {projects => 29 (projects.length > 0 && ( 30 <div className='argo-table-list argo-table-list--clickable'> 31 <div className='argo-table-list__head'> 32 <div className='row'> 33 <div className='columns small-3'>NAME</div> 34 <div className='columns small-6'>DESCRIPTION</div> 35 </div> 36 </div> 37 {projects.map(proj => ( 38 <div className='argo-table-list__row' key={proj.metadata.name} onClick={() => ctx.navigation.goto(`./${proj.metadata.name}`)}> 39 <div className='row'> 40 <div className='columns small-3'> 41 <i className='fa fa-object-group' /> {proj.metadata.name} 42 </div> 43 <div className='columns small-6'>{proj.spec.description}</div> 44 </div> 45 </div> 46 ))} 47 </div> 48 )) || ( 49 <EmptyState icon='fa fa-object-group'> 50 <h4>No projects yet</h4> 51 <h5>Create new projects to group your applications</h5> 52 <button className='argo-button argo-button--base' onClick={() => ctx.navigation.goto('.', {add: true}, {replace: true})}> 53 New project 54 </button> 55 </EmptyState> 56 ) 57 } 58 </DataLoader> 59 </div> 60 <Query> 61 {params => ( 62 <SlidingPanel 63 isShown={params.get('add') === 'true'} 64 onClose={() => ctx.navigation.goto('.', {add: null}, {replace: true})} 65 isMiddle={true} 66 header={ 67 <div> 68 <button onClick={() => this.formApi.submitForm(null)} className='argo-button argo-button--base'> 69 Create 70 </button>{' '} 71 <button onClick={() => ctx.navigation.goto('.', {add: null}, {replace: true})} className='argo-button argo-button--base-o'> 72 Cancel 73 </button> 74 </div> 75 }> 76 <Form 77 defaultValues={{metadata: {}, spec: {}}} 78 getApi={api => (this.formApi = api)} 79 validateError={(p: Project) => ({ 80 'metadata.name': !p.metadata.name && 'Project Name is required' 81 })} 82 onSubmit={async (proj: Project) => { 83 try { 84 await services.projects.create(proj); 85 ctx.navigation.goto(`./${proj.metadata.name}`, {add: null}, {replace: true}); 86 } catch (e) { 87 ctx.notifications.show({ 88 content: <ErrorNotification title='Unable to create project' e={e} />, 89 type: NotificationType.Error 90 }); 91 } 92 }}> 93 {api => ( 94 <form onSubmit={api.submitForm} role='form' className='width-control'> 95 <div className='white-box'> 96 <p>GENERAL</p> 97 <div className='argo-form-row'> 98 <FormField formApi={api} label='Project Name' field='metadata.name' component={Text} /> 99 </div> 100 <div className='argo-form-row'> 101 <FormField formApi={api} label='Description' field='spec.description' component={Text} /> 102 </div> 103 </div> 104 </form> 105 )} 106 </Form> 107 </SlidingPanel> 108 )} 109 </Query> 110 </Page> 111 )} 112 </Consumer> 113 ); 114 } 115 }