diff options
author | Dessalines <tyhou13@gmx.com> | 2020-01-01 15:46:14 -0500 |
---|---|---|
committer | Dessalines <tyhou13@gmx.com> | 2020-01-01 15:46:14 -0500 |
commit | f5a13717eaf10fcacc211950ff88943df9aef4c2 (patch) | |
tree | da7fbbbf5ac80c9fd1cfc6b484afd4030f115ef8 /ui/src/components/user.tsx | |
parent | 4faa46ac29a5693f9f938ae80a22e6c1799c1404 (diff) |
Adding change password and email address from user settings.
- Fixes #384
- Fixes #385
Diffstat (limited to 'ui/src/components/user.tsx')
-rw-r--r-- | ui/src/components/user.tsx | 411 |
1 files changed, 243 insertions, 168 deletions
diff --git a/ui/src/components/user.tsx b/ui/src/components/user.tsx index e97b26f9..99c340c5 100644 --- a/ui/src/components/user.tsx +++ b/ui/src/components/user.tsx @@ -99,7 +99,6 @@ export class User extends Component<any, UserState> { default_sort_type: null, default_listing_type: null, lang: null, - avatar: null, auth: null, }, userSettingsLoading: null, @@ -437,199 +436,240 @@ export class User extends Component<any, UserState> { </h5> <form onSubmit={linkEvent(this, this.handleUserSettingsSubmit)}> <div class="form-group"> - <div class="col-12"> - <label> - <T i18nKey="avatar">#</T> - </label> - <form class="d-inline"> - <label - htmlFor="file-upload" - class="pointer ml-4 text-muted small font-weight-bold" - > - <img - height="80" - width="80" - src={ - this.state.userSettingsForm.avatar - ? this.state.userSettingsForm.avatar - : 'https://via.placeholder.com/300/000?text=Avatar' - } - class="rounded-circle" - /> - </label> - <input - id="file-upload" - type="file" - accept="image/*,video/*" - name="file" - class="d-none" - disabled={!UserService.Instance.user} - onChange={linkEvent(this, this.handleImageUpload)} + <label> + <T i18nKey="avatar">#</T> + </label> + <form class="d-inline"> + <label + htmlFor="file-upload" + class="pointer ml-4 text-muted small font-weight-bold" + > + <img + height="80" + width="80" + src={ + this.state.userSettingsForm.avatar + ? this.state.userSettingsForm.avatar + : 'https://via.placeholder.com/300/000?text=Avatar' + } + class="rounded-circle" /> - </form> - </div> + </label> + <input + id="file-upload" + type="file" + accept="image/*,video/*" + name="file" + class="d-none" + disabled={!UserService.Instance.user} + onChange={linkEvent(this, this.handleImageUpload)} + /> + </form> </div> <div class="form-group"> - <div class="col-12"> - <label> + <label> + <T i18nKey="language">#</T> + </label> + <select + value={this.state.userSettingsForm.lang} + onChange={linkEvent(this, this.handleUserSettingsLangChange)} + class="ml-2 custom-select custom-select-sm w-auto" + > + <option disabled> <T i18nKey="language">#</T> - </label> - <select - value={this.state.userSettingsForm.lang} - onChange={linkEvent( + </option> + <option value="browser"> + <T i18nKey="browser_default">#</T> + </option> + <option disabled>──</option> + {languages.map(lang => ( + <option value={lang.code}>{lang.name}</option> + ))} + </select> + </div> + <div class="form-group"> + <label> + <T i18nKey="theme">#</T> + </label> + <select + value={this.state.userSettingsForm.theme} + onChange={linkEvent(this, this.handleUserSettingsThemeChange)} + class="ml-2 custom-select custom-select-sm w-auto" + > + <option disabled> + <T i18nKey="theme">#</T> + </option> + {themes.map(theme => ( + <option value={theme}>{theme}</option> + ))} + </select> + </div> + <form className="form-group"> + <label> + <T i18nKey="sort_type" class="mr-2"> + # + </T> + </label> + <ListingTypeSelect + type_={this.state.userSettingsForm.default_listing_type} + onChange={this.handleUserSettingsListingTypeChange} + /> + </form> + <form className="form-group"> + <label> + <T i18nKey="type" class="mr-2"> + # + </T> + </label> + <SortSelect + sort={this.state.userSettingsForm.default_sort_type} + onChange={this.handleUserSettingsSortTypeChange} + /> + </form> + <div class="form-group row"> + <label class="col-lg-3 col-form-label"> + <T i18nKey="email">#</T> + </label> + <div class="col-lg-9"> + <input + type="email" + class="form-control" + placeholder={i18n.t('optional')} + value={this.state.userSettingsForm.email} + onInput={linkEvent( this, - this.handleUserSettingsLangChange + this.handleUserSettingsEmailChange )} - class="ml-2 custom-select custom-select-sm w-auto" - > - <option disabled> - <T i18nKey="language">#</T> - </option> - <option value="browser"> - <T i18nKey="browser_default">#</T> - </option> - <option disabled>──</option> - {languages.map(lang => ( - <option value={lang.code}>{lang.name}</option> - ))} - </select> + minLength={3} + /> </div> </div> - <div class="form-group"> - <div class="col-12"> - <label> - <T i18nKey="theme">#</T> - </label> - <select - value={this.state.userSettingsForm.theme} - onChange={linkEvent( + <div class="form-group row"> + <label class="col-lg-5 col-form-label"> + <T i18nKey="new_password">#</T> + </label> + <div class="col-lg-7"> + <input + type="password" + class="form-control" + value={this.state.userSettingsForm.new_password} + onInput={linkEvent( this, - this.handleUserSettingsThemeChange + this.handleUserSettingsNewPasswordChange )} - class="ml-2 custom-select custom-select-sm w-auto" - > - <option disabled> - <T i18nKey="theme">#</T> - </option> - {themes.map(theme => ( - <option value={theme}>{theme}</option> - ))} - </select> + /> </div> </div> - <form className="form-group"> - <div class="col-12"> - <label> - <T i18nKey="sort_type" class="mr-2"> - # - </T> - </label> - <ListingTypeSelect - type_={this.state.userSettingsForm.default_listing_type} - onChange={this.handleUserSettingsListingTypeChange} + <div class="form-group row"> + <label class="col-lg-5 col-form-label"> + <T i18nKey="verify_password">#</T> + </label> + <div class="col-lg-7"> + <input + type="password" + class="form-control" + value={this.state.userSettingsForm.new_password_verify} + onInput={linkEvent( + this, + this.handleUserSettingsNewPasswordVerifyChange + )} /> </div> - </form> - <form className="form-group"> - <div class="col-12"> - <label> - <T i18nKey="type" class="mr-2"> - # - </T> - </label> - <SortSelect - sort={this.state.userSettingsForm.default_sort_type} - onChange={this.handleUserSettingsSortTypeChange} + </div> + <div class="form-group row"> + <label class="col-lg-5 col-form-label"> + <T i18nKey="old_password">#</T> + </label> + <div class="col-lg-7"> + <input + type="password" + class="form-control" + value={this.state.userSettingsForm.old_password} + onInput={linkEvent( + this, + this.handleUserSettingsOldPasswordChange + )} /> </div> - </form> + </div> {WebSocketService.Instance.site.enable_nsfw && ( <div class="form-group"> - <div class="col-12"> - <div class="form-check"> - <input - class="form-check-input" - type="checkbox" - checked={this.state.userSettingsForm.show_nsfw} - onChange={linkEvent( - this, - this.handleUserSettingsShowNsfwChange - )} - /> - <label class="form-check-label"> - <T i18nKey="show_nsfw">#</T> - </label> - </div> + <div class="form-check"> + <input + class="form-check-input" + type="checkbox" + checked={this.state.userSettingsForm.show_nsfw} + onChange={linkEvent( + this, + this.handleUserSettingsShowNsfwChange + )} + /> + <label class="form-check-label"> + <T i18nKey="show_nsfw">#</T> + </label> </div> </div> )} <div class="form-group"> - <div class="col-12"> - <button - type="submit" - class="btn btn-block btn-secondary mr-4" - > - {this.state.userSettingsLoading ? ( - <svg class="icon icon-spinner spin"> - <use xlinkHref="#icon-spinner"></use> - </svg> - ) : ( - capitalizeFirstLetter(i18n.t('save')) - )} - </button> - </div> + <button type="submit" class="btn btn-block btn-secondary mr-4"> + {this.state.userSettingsLoading ? ( + <svg class="icon icon-spinner spin"> + <use xlinkHref="#icon-spinner"></use> + </svg> + ) : ( + capitalizeFirstLetter(i18n.t('save')) + )} + </button> </div> <hr /> <div class="form-group mb-0"> - <div class="col-12"> - <button - class="btn btn-block btn-danger" - onClick={linkEvent( - this, - this.handleDeleteAccountShowConfirmToggle - )} - > - <T i18nKey="delete_account">#</T> - </button> - {this.state.deleteAccountShowConfirm && ( - <> - <div class="my-2 alert alert-danger" role="alert"> - <T i18nKey="delete_account_confirm">#</T> - </div> - <input - type="password" - value={this.state.deleteAccountForm.password} - onInput={linkEvent( - this, - this.handleDeleteAccountPasswordChange - )} - class="form-control my-2" - /> - <button - class="btn btn-danger mr-4" - disabled={!this.state.deleteAccountForm.password} - onClick={linkEvent(this, this.handleDeleteAccount)} - > - {this.state.deleteAccountLoading ? ( - <svg class="icon icon-spinner spin"> - <use xlinkHref="#icon-spinner"></use> - </svg> - ) : ( - capitalizeFirstLetter(i18n.t('delete')) - )} - </button> - <button - class="btn btn-secondary" - onClick={linkEvent( - this, - this.handleDeleteAccountShowConfirmToggle - )} - > - <T i18nKey="cancel">#</T> - </button> - </> + <button + class="btn btn-block btn-danger" + onClick={linkEvent( + this, + this.handleDeleteAccountShowConfirmToggle )} - </div> + > + <T i18nKey="delete_account">#</T> + </button> + {this.state.deleteAccountShowConfirm && ( + <> + <div class="my-2 alert alert-danger" role="alert"> + <T i18nKey="delete_account_confirm">#</T> + </div> + <input + type="password" + value={this.state.deleteAccountForm.password} + onInput={linkEvent( + this, + this.handleDeleteAccountPasswordChange + )} + class="form-control my-2" + /> + <button + class="btn btn-danger mr-4" + disabled={!this.state.deleteAccountForm.password} + onClick={linkEvent(this, this.handleDeleteAccount)} + > + {this.state.deleteAccountLoading ? ( + <svg class="icon icon-spinner spin"> + <use xlinkHref="#icon-spinner"></use> + </svg> + ) : ( + capitalizeFirstLetter(i18n.t('delete')) + )} + </button> + <button + class="btn btn-secondary" + onClick={linkEvent( + this, + this.handleDeleteAccountShowConfirmToggle + )} + > + <T i18nKey="cancel">#</T> + </button> + </> + )} </div> </form> </div> @@ -786,6 +826,38 @@ export class User extends Component<any, UserState> { this.setState(this.state); } + handleUserSettingsEmailChange(i: User, event: any) { + i.state.userSettingsForm.email = event.target.value; + if (i.state.userSettingsForm.email == '' && !i.state.user.email) { + i.state.userSettingsForm.email = undefined; + } + i.setState(i.state); + } + + handleUserSettingsNewPasswordChange(i: User, event: any) { + i.state.userSettingsForm.new_password = event.target.value; + if (i.state.userSettingsForm.new_password == '') { + i.state.userSettingsForm.new_password = undefined; + } + i.setState(i.state); + } + + handleUserSettingsNewPasswordVerifyChange(i: User, event: any) { + i.state.userSettingsForm.new_password_verify = event.target.value; + if (i.state.userSettingsForm.new_password_verify == '') { + i.state.userSettingsForm.new_password_verify = undefined; + } + i.setState(i.state); + } + + handleUserSettingsOldPasswordChange(i: User, event: any) { + i.state.userSettingsForm.old_password = event.target.value; + if (i.state.userSettingsForm.old_password == '') { + i.state.userSettingsForm.old_password = undefined; + } + i.setState(i.state); + } + handleImageUpload(i: User, event: any) { event.preventDefault(); let file = event.target.files[0]; @@ -856,6 +928,8 @@ export class User extends Component<any, UserState> { if (msg.error) { alert(i18n.t(msg.error)); this.state.deleteAccountLoading = false; + this.state.avatarLoading = false; + this.state.userSettingsLoading = false; if (msg.error == 'couldnt_find_that_username_or_email') { this.context.router.history.push('/'); } @@ -882,6 +956,7 @@ export class User extends Component<any, UserState> { UserService.Instance.user.default_listing_type; this.state.userSettingsForm.lang = UserService.Instance.user.lang; this.state.userSettingsForm.avatar = UserService.Instance.user.avatar; + this.state.userSettingsForm.email = this.state.user.email; } document.title = `/u/${this.state.user.name} - ${WebSocketService.Instance.site.name}`; window.scrollTo(0, 0); |