From be30cdb51f673889c23f1be9787d3c0bee1100b5 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 28 Sep 2022 11:00:36 +0200 Subject: [PATCH] Update change password dialog (#13888) * Update change password dialog * Improve wording * Update modal for people page * Remove useless async --- .../config/person/dialog-person-detail.ts | 40 +--- .../users/dialog-admin-change-password.ts | 183 ++++++++++++++++++ src/panels/config/users/dialog-user-detail.ts | 49 +---- .../show-dialog-admin-change-password.ts | 19 ++ src/translations/en.json | 10 +- 5 files changed, 220 insertions(+), 81 deletions(-) create mode 100644 src/panels/config/users/dialog-admin-change-password.ts create mode 100644 src/panels/config/users/show-dialog-admin-change-password.ts diff --git a/src/panels/config/person/dialog-person-detail.ts b/src/panels/config/person/dialog-person-detail.ts index c9d0c0c56a..a847150f07 100644 --- a/src/panels/config/person/dialog-person-detail.ts +++ b/src/panels/config/person/dialog-person-detail.ts @@ -5,10 +5,9 @@ import memoizeOne from "memoize-one"; import "../../../components/entity/ha-entities-picker"; import { createCloseHeading } from "../../../components/ha-dialog"; import "../../../components/ha-formfield"; -import "../../../components/ha-textfield"; import "../../../components/ha-picture-upload"; import type { HaPictureUpload } from "../../../components/ha-picture-upload"; -import { adminChangePassword } from "../../../data/auth"; +import "../../../components/ha-textfield"; import { PersonMutableParams } from "../../../data/person"; import { deleteUser, @@ -20,7 +19,6 @@ import { import { showAlertDialog, showConfirmationDialog, - showPromptDialog, } from "../../../dialogs/generic/show-dialog-box"; import { CropOptions } from "../../../dialogs/image-cropper-dialog/show-image-cropper-dialog"; import { PolymerChangedEvent } from "../../../polymer-types"; @@ -28,6 +26,7 @@ import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; import { documentationUrl } from "../../../util/documentation-url"; import { showAddUserDialog } from "../users/show-dialog-add-user"; +import { showAdminChangePasswordDialog } from "../users/show-dialog-admin-change-password"; import { PersonDetailDialogParams } from "./show-dialog-person-detail"; const includeDomains = ["device_tracker"]; @@ -350,40 +349,7 @@ class DialogPersonDetail extends LitElement { }); return; } - const newPassword = await showPromptDialog(this, { - title: this.hass.localize("ui.panel.config.users.editor.change_password"), - inputType: "password", - inputLabel: this.hass.localize( - "ui.panel.config.users.editor.new_password" - ), - }); - if (!newPassword) { - return; - } - const confirmPassword = await showPromptDialog(this, { - title: this.hass.localize("ui.panel.config.users.editor.change_password"), - inputType: "password", - inputLabel: this.hass.localize( - "ui.panel.config.users.add_user.password_confirm" - ), - }); - if (!confirmPassword) { - return; - } - if (newPassword !== confirmPassword) { - showAlertDialog(this, { - title: this.hass.localize( - "ui.panel.config.users.add_user.password_not_match" - ), - }); - return; - } - await adminChangePassword(this.hass, this._user.id, newPassword); - showAlertDialog(this, { - title: this.hass.localize( - "ui.panel.config.users.editor.password_changed" - ), - }); + showAdminChangePasswordDialog(this, { userId: this._user.id }); } private async _updateEntry() { diff --git a/src/panels/config/users/dialog-admin-change-password.ts b/src/panels/config/users/dialog-admin-change-password.ts new file mode 100644 index 0000000000..227d4fb057 --- /dev/null +++ b/src/panels/config/users/dialog-admin-change-password.ts @@ -0,0 +1,183 @@ +import "@material/mwc-button"; +import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { customElement, property, state } from "lit/decorators"; + +import { fireEvent } from "../../../common/dom/fire_event"; +import { createCloseHeading } from "../../../components/ha-dialog"; +import "../../../components/ha-form/ha-form"; +import { SchemaUnion } from "../../../components/ha-form/types"; +import "../../../components/ha-textfield"; +import { adminChangePassword } from "../../../data/auth"; +import { haStyleDialog } from "../../../resources/styles"; +import { HomeAssistant } from "../../../types"; +import { showToast } from "../../../util/toast"; +import { AdminChangePasswordDialogParams } from "./show-dialog-admin-change-password"; + +const SCHEMA = [ + { + name: "new_password", + required: true, + selector: { + text: { + type: "password", + }, + }, + }, + { + name: "password_confirm", + required: true, + selector: { + text: { + type: "password", + }, + }, + }, +] as const; + +type FormData = { new_password?: string; password_confirm?: string }; + +@customElement("dialog-admin-change-password") +class DialogAdminChangePassword extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @state() private _params?: AdminChangePasswordDialogParams; + + @state() private _userId?: string; + + @state() private _data?: FormData; + + @state() private _error?: Record; + + @state() private _submitting = false; + + @state() private _success = false; + + public showDialog(params: AdminChangePasswordDialogParams): void { + this._params = params; + this._userId = params.userId; + } + + public closeDialog(): void { + this._params = undefined; + this._data = undefined; + this._submitting = false; + this._success = false; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + private _computeLabel = (schema: SchemaUnion) => + this.hass.localize(`ui.panel.config.users.change_password.${schema.name}`); + + private _computeError = (error: string) => + this.hass.localize( + `ui.panel.config.users.change_password.${error}` as any + ) || error; + + private _validate() { + if ( + this._data && + this._data.new_password && + this._data.password_confirm && + this._data.new_password !== this._data.password_confirm + ) { + this._error = { + password_confirm: "password_no_match", + }; + } else { + this._error = undefined; + } + } + + protected render(): TemplateResult { + if (!this._params) { + return html``; + } + + const canSubmit = Boolean( + this._data?.new_password && this._data?.password_confirm && !this._error + ); + + return html` + + ${this._success + ? html` +

+ ${this.hass.localize( + "ui.panel.config.users.change_password.password_changed" + )} +

+ + ${this.hass.localize("ui.dialogs.generic.ok")} + + ` + : html` + + + ${this.hass.localize("ui.common.cancel")} + + + ${this.hass.localize( + "ui.panel.config.users.change_password.change" + )} + + `} +
+ `; + } + + private _valueChanged(ev) { + this._data = ev.detail.value; + this._validate(); + } + + private async _changePassword(): Promise { + if (!this._userId || !this._data?.new_password) return; + try { + this._submitting = true; + await adminChangePassword( + this.hass, + this._userId!, + this._data.new_password + ); + this._success = true; + } catch (err: any) { + showToast(this, { + message: err.body?.message || err.message || err, + }); + } finally { + this._submitting = false; + } + } + + static get styles(): CSSResultGroup { + return [haStyleDialog, css``]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-admin-change-password": DialogAdminChangePassword; + } +} diff --git a/src/panels/config/users/dialog-user-detail.ts b/src/panels/config/users/dialog-user-detail.ts index 490839b3cd..da3ced4d61 100644 --- a/src/panels/config/users/dialog-user-detail.ts +++ b/src/panels/config/users/dialog-user-detail.ts @@ -4,26 +4,23 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { computeRTLDirection } from "../../../common/util/compute_rtl"; +import "../../../components/ha-chip"; +import "../../../components/ha-chip-set"; import { createCloseHeading } from "../../../components/ha-dialog"; import "../../../components/ha-formfield"; import "../../../components/ha-help-tooltip"; -import "../../../components/ha-chip-set"; -import "../../../components/ha-chip"; import "../../../components/ha-svg-icon"; -import "../../../components/ha-textfield"; import "../../../components/ha-switch"; -import { adminChangePassword } from "../../../data/auth"; +import "../../../components/ha-textfield"; import { computeUserBadges, SYSTEM_GROUP_ID_ADMIN, SYSTEM_GROUP_ID_USER, } from "../../../data/user"; -import { - showAlertDialog, - showPromptDialog, -} from "../../../dialogs/generic/show-dialog-box"; +import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; +import { showAdminChangePasswordDialog } from "./show-dialog-admin-change-password"; import { UserDetailDialogParams } from "./show-dialog-user-detail"; @customElement("dialog-user-detail") @@ -268,40 +265,8 @@ class DialogUserDetail extends LitElement { }); return; } - const newPassword = await showPromptDialog(this, { - title: this.hass.localize("ui.panel.config.users.editor.change_password"), - inputType: "password", - inputLabel: this.hass.localize( - "ui.panel.config.users.editor.new_password" - ), - }); - if (!newPassword) { - return; - } - const confirmPassword = await showPromptDialog(this, { - title: this.hass.localize("ui.panel.config.users.editor.change_password"), - inputType: "password", - inputLabel: this.hass.localize( - "ui.panel.config.users.add_user.password_confirm" - ), - }); - if (!confirmPassword) { - return; - } - if (newPassword !== confirmPassword) { - showAlertDialog(this, { - title: this.hass.localize( - "ui.panel.config.users.add_user.password_not_match" - ), - }); - return; - } - await adminChangePassword(this.hass, this._params!.entry.id, newPassword); - showAlertDialog(this, { - title: this.hass.localize( - "ui.panel.config.users.editor.password_changed" - ), - }); + + showAdminChangePasswordDialog(this, { userId: this._params!.entry.id }); } private _close(): void { diff --git a/src/panels/config/users/show-dialog-admin-change-password.ts b/src/panels/config/users/show-dialog-admin-change-password.ts new file mode 100644 index 0000000000..df6772a5c1 --- /dev/null +++ b/src/panels/config/users/show-dialog-admin-change-password.ts @@ -0,0 +1,19 @@ +import { fireEvent } from "../../../common/dom/fire_event"; + +export interface AdminChangePasswordDialogParams { + userId: string; +} + +export const loadAdminChangePasswordDialog = () => + import("./dialog-admin-change-password"); + +export const showAdminChangePasswordDialog = ( + element: HTMLElement, + dialogParams: AdminChangePasswordDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "dialog-admin-change-password", + dialogImport: loadAdminChangePasswordDialog, + dialogParams, + }); +}; diff --git a/src/translations/en.json b/src/translations/en.json index 23933d2f6d..adc27b77f7 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2988,8 +2988,6 @@ "name": "Display name", "username": "Username", "change_password": "Change password", - "new_password": "New Password", - "password_changed": "Password was changed successfully", "activate_user": "Activate user", "deactivate_user": "Deactivate user", "delete_user": "Delete user", @@ -3015,6 +3013,14 @@ "password_not_match": "Passwords don't match", "local_only": "Local only", "create": "Create" + }, + "change_password": { + "caption": "Change password", + "new_password": "New Password", + "password_confirm": "Confirm Password", + "change": "Change", + "password_no_match": "Passwords don't match", + "password_changed": "The password has been changed successfully." } }, "application_credentials": {