github.com/argoproj/argo-cd@v1.8.7/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: {className: 'fa fa-plus', items: [{title: 'New Project', action: () => ctx.navigation.goto('.', {add: true})}]} 22 }}> 23 <div className='projects argo-container'> 24 <DataLoader load={() => services.projects.list()}> 25 {projects => 26 (projects.length > 0 && ( 27 <div className='argo-table-list argo-table-list--clickable'> 28 <div className='argo-table-list__head'> 29 <div className='row'> 30 <div className='columns small-3'>NAME</div> 31 <div className='columns small-6'>DESCRIPTION</div> 32 </div> 33 </div> 34 {projects.map(proj => ( 35 <div className='argo-table-list__row' key={proj.metadata.name} onClick={() => ctx.navigation.goto(`./${proj.metadata.name}`)}> 36 <div className='row'> 37 <div className='columns small-3'> 38 <i className='fa fa-object-group' /> {proj.metadata.name} 39 </div> 40 <div className='columns small-6'>{proj.spec.description}</div> 41 </div> 42 </div> 43 ))} 44 </div> 45 )) || ( 46 <EmptyState icon='fa fa-object-group'> 47 <h4>No projects yet</h4> 48 <h5>Create new projects to group your applications</h5> 49 <button className='argo-button argo-button--base' onClick={() => ctx.navigation.goto('.', {add: true})}> 50 New project 51 </button> 52 </EmptyState> 53 ) 54 } 55 </DataLoader> 56 </div> 57 <Query> 58 {params => ( 59 <SlidingPanel 60 isShown={params.get('add') === 'true'} 61 onClose={() => ctx.navigation.goto('.', {add: null})} 62 isMiddle={true} 63 header={ 64 <div> 65 <button onClick={() => ctx.navigation.goto('.', {add: null})} className='argo-button argo-button--base-o'> 66 Cancel 67 </button>{' '} 68 <button onClick={() => this.formApi.submitForm(null)} className='argo-button argo-button--base'> 69 Create 70 </button> 71 </div> 72 }> 73 <Form 74 defaultValues={{metadata: {}, spec: {}}} 75 getApi={api => (this.formApi = api)} 76 validateError={(p: Project) => ({ 77 'metadata.name': !p.metadata.name && 'Project name is required' 78 })} 79 onSubmit={async (proj: Project) => { 80 try { 81 await services.projects.create(proj); 82 ctx.navigation.goto(`./${proj.metadata.name}`, {add: null}); 83 } catch (e) { 84 ctx.notifications.show({ 85 content: <ErrorNotification title='Unable to create project' e={e} />, 86 type: NotificationType.Error 87 }); 88 } 89 }}> 90 {api => ( 91 <form onSubmit={api.submitForm} role='form' className='width-control'> 92 <div className='white-box'> 93 <p>GENERAL</p> 94 <div className='argo-form-row'> 95 <FormField formApi={api} label='Name' field='metadata.name' component={Text} /> 96 </div> 97 <div className='argo-form-row'> 98 <FormField formApi={api} label='Description' field='spec.description' component={Text} /> 99 </div> 100 </div> 101 </form> 102 )} 103 </Form> 104 </SlidingPanel> 105 )} 106 </Query> 107 </Page> 108 )} 109 </Consumer> 110 ); 111 } 112 }