github.com/argoproj/argo-cd/v3@v3.2.1/ui/src/app/user-info/components/user-info-overview/user-info-overview.tsx (about) 1 import * as React from 'react'; 2 3 import {FormField, NotificationType, SlidingPanel} from 'argo-ui/src/index'; 4 import * as PropTypes from 'prop-types'; 5 import {Form, FormApi, FormValue, Nested, Text} from 'react-form'; 6 import {RouteComponentProps} from 'react-router'; 7 import {DataLoader, ErrorNotification, Page, Spinner} from '../../../shared/components'; 8 import {AppContext} from '../../../shared/context'; 9 import {services} from '../../../shared/services'; 10 11 import './user-info-overview.scss'; 12 13 export class UserInfoOverview extends React.Component<RouteComponentProps<any>, {connecting: boolean}> { 14 public static contextTypes = { 15 router: PropTypes.object, 16 apis: PropTypes.object, 17 history: PropTypes.object 18 }; 19 20 private formApiPassword: FormApi; 21 22 constructor(props: RouteComponentProps<any>) { 23 super(props); 24 this.state = {connecting: false}; 25 } 26 27 public render() { 28 return ( 29 <DataLoader key='userInfo' load={() => services.users.get()}> 30 {userInfo => ( 31 <Page 32 title='User Info' 33 toolbar={{ 34 breadcrumbs: [{title: 'User Info'}], 35 actionMenu: 36 userInfo.loggedIn && userInfo.iss === 'argocd' 37 ? { 38 items: [ 39 { 40 iconClassName: 'fa fa-lock', 41 title: 'Update Password', 42 action: () => (this.showChangePassword = true) 43 } 44 ] 45 } 46 : {items: []} 47 }}> 48 <div> 49 <div className='user-info'> 50 <div className='argo-container'> 51 <div className='user-info-overview__panel white-box'> 52 {userInfo.loggedIn ? ( 53 <React.Fragment key='userInfoInner'> 54 <p key='username'>Username: {userInfo.username}</p> 55 <p key='iss'>Issuer: {userInfo.iss}</p> 56 {userInfo.groups && ( 57 <React.Fragment key='userInfo4'> 58 <p>Groups:</p> 59 <ul> 60 {userInfo.groups.map(group => ( 61 <li key={group}>{group}</li> 62 ))} 63 </ul> 64 </React.Fragment> 65 )} 66 </React.Fragment> 67 ) : ( 68 <p key='loggedOutMessage'>You are not logged in</p> 69 )} 70 </div> 71 </div> 72 </div> 73 {userInfo.loggedIn && userInfo.iss === 'argocd' ? ( 74 <SlidingPanel 75 isShown={this.showChangePassword} 76 onClose={() => (this.showChangePassword = false)} 77 header={ 78 <div> 79 <button 80 className='argo-button argo-button--base' 81 onClick={() => { 82 this.formApiPassword.submitForm(null); 83 }}> 84 <Spinner show={this.state.connecting} style={{marginRight: '5px'}} /> 85 Save New Password 86 </button>{' '} 87 <button onClick={() => (this.showChangePassword = false)} className='argo-button argo-button--base-o'> 88 Cancel 89 </button> 90 </div> 91 }> 92 <h4>Update account password</h4> 93 <Form 94 onSubmit={params => this.changePassword(userInfo.username, params.currentPassword, params.newPassword)} 95 getApi={api => (this.formApiPassword = api)} 96 defaultValues={{type: 'git'}} 97 validateError={(params: {currentPassword: string; newPassword: string; confirmNewPassword: string}) => ({ 98 currentPassword: !params.currentPassword && 'Current password is required.', 99 newPassword: 100 (!params.newPassword && 'New password is required.') || 101 (params.newPassword !== params.confirmNewPassword && 'Confirm your new password.'), 102 confirmNewPassword: (!params.confirmNewPassword || params.confirmNewPassword !== params.newPassword) && 'Confirm your new password.' 103 })}> 104 {formApi => ( 105 <form onSubmit={formApi.submitForm} role='form' className='change-password width-control'> 106 <div className='argo-form-row'> 107 <FormField 108 formApi={formApi} 109 label='Current Password' 110 field='currentPassword' 111 component={Text} 112 componentProps={{type: 'password'}} 113 /> 114 </div> 115 <div className='argo-form-row'> 116 <FormField formApi={formApi} label='New Password' field='newPassword' component={Text} componentProps={{type: 'password'}} /> 117 </div> 118 <div className='argo-form-row'> 119 <FormField 120 formApi={formApi} 121 label='Confirm New Password' 122 field='confirmNewPassword' 123 component={Text} 124 componentProps={{type: 'password'}} 125 /> 126 </div> 127 </form> 128 )} 129 </Form> 130 </SlidingPanel> 131 ) : ( 132 <div /> 133 )} 134 </div> 135 </Page> 136 )} 137 </DataLoader> 138 ); 139 } 140 141 private async changePassword(username: string, currentPassword: Nested<FormValue> | FormValue, newPassword: Nested<FormValue> | FormValue) { 142 try { 143 await services.accounts.changePassword(username, currentPassword, newPassword); 144 this.appContext.apis.notifications.show({type: NotificationType.Success, content: 'Your password has been successfully updated.'}); 145 this.showChangePassword = false; 146 } catch (e) { 147 this.appContext.apis.notifications.show({ 148 content: <ErrorNotification title='Unable to update your password.' e={e} />, 149 type: NotificationType.Error 150 }); 151 } 152 } 153 154 // Whether to show the HTTPS repository connection dialogue on the page 155 private get showChangePassword() { 156 return new URLSearchParams(this.props.location.search).get('changePassword') === 'true'; 157 } 158 159 private set showChangePassword(val: boolean) { 160 this.clearChangePasswordForm(); 161 this.appContext.router.history.push(`${this.props.match.url}?changePassword=${val}`); 162 } 163 164 // Empty all fields in HTTPS repository form 165 private clearChangePasswordForm() { 166 this.formApiPassword.resetAll(); 167 } 168 169 private get appContext(): AppContext { 170 return this.context as AppContext; 171 } 172 }