This is an automated email from the ASF dual-hosted git repository.

shuai pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/answer.git

commit 013df362caa2636b2903a5f93869775fb0b138de
Author: lihui <[email protected]>
AuthorDate: Thu Jan 16 00:03:30 2025 +0800

    feat: add password hide show logic for init server
---
 ui/package.json                                    |  1 +
 ui/pnpm-lock.yaml                                  | 14 +++++-
 .../pages/Install/components/FourthStep/index.tsx  | 56 +++++++++++++++-------
 3 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/ui/package.json b/ui/package.json
index 0e645d2e..da8588e6 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -39,6 +39,7 @@
     "qs": "^6.11.0",
     "react": "^18.2.0",
     "react-bootstrap": "^2.10.0",
+    "react-bootstrap-icons": "^1.11.5",
     "react-dom": "^18.2.0",
     "react-helmet-async": "^1.3.0",
     "react-i18next": "^11.18.3",
diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml
index 32ce67e7..8aa2dffb 100644
--- a/ui/pnpm-lock.yaml
+++ b/ui/pnpm-lock.yaml
@@ -77,6 +77,9 @@ importers:
       react-bootstrap:
         specifier: ^2.10.0
         version: 2.10.0(@types/[email protected])([email protected])([email protected])
+      react-bootstrap-icons:
+        specifier: ^1.11.5
+        version: 1.11.5([email protected])
       react-dom:
         specifier: ^18.2.0
         version: 18.2.0([email protected])
@@ -8176,7 +8179,7 @@ packages:
     dependencies:
       universalify: 2.0.0
     optionalDependencies:
-      graceful-fs: 4.2.10
+      graceful-fs: 4.2.11
 
   /[email protected]:
     resolution: {integrity: 
sha512-pfog5gdDxPdV4eP7Kg87M8/bHgshlZ5pybl+yKxAnCZ5O7lCIn7Ixydj03wOlnDQesky2BPyA91SQ+5Y/mNwzw==}
@@ -9913,6 +9916,15 @@ packages:
       semver: 5.7.1
     dev: true
 
+  /[email protected]([email protected]):
+    resolution: {integrity: 
sha512-eOhtFJMUqw98IJcfKJsSMZkFHCeNPTTwXZAe9V9d4mT22ARmbrISxPO9GmtWWuf72zQctLeZMGodX/q6wrbYYg==}
+    peerDependencies:
+      react: '>=16.8.6'
+    dependencies:
+      prop-types: 15.8.1
+      react: 18.2.0
+    dev: false
+
   
/[email protected](@types/[email protected])([email protected])([email protected]):
     resolution: {integrity: 
sha512-87gRP69VAfeU2yKgp8RI3HvzhPNrnYIV2QNranYXataz3ef+k7OhvKGGdxQLQfUsQ2RTmlY66tn4pdFrZ94hNg==}
     peerDependencies:
diff --git a/ui/src/pages/Install/components/FourthStep/index.tsx 
b/ui/src/pages/Install/components/FourthStep/index.tsx
index 65ffd9d5..066cd079 100644
--- a/ui/src/pages/Install/components/FourthStep/index.tsx
+++ b/ui/src/pages/Install/components/FourthStep/index.tsx
@@ -17,8 +17,9 @@
  * under the License.
  */
 
-import { FC, FormEvent } from 'react';
+import { FC, FormEvent, useState } from 'react';
 import { Form, Button } from 'react-bootstrap';
+import { Eye, EyeSlash } from 'react-bootstrap-icons';
 import { useTranslation } from 'react-i18next';
 
 import type { FormDataType } from '@/common/interface';
@@ -34,6 +35,8 @@ interface Props {
 const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
   const { t } = useTranslation('translation', { keyPrefix: 'install' });
 
+  const [showPassword, setShowPassword] = useState(false);
+
   const checkValidated = (): boolean => {
     let bol = true;
     const { site_name, site_url, contact_email, name, password, email } = data;
@@ -295,21 +298,42 @@ const Index: FC<Props> = ({ visible, data, 
changeCallback, nextCallback }) => {
 
       <Form.Group controlId="password" className="mb-3">
         <Form.Label>{t('admin_password.label')}</Form.Label>
-        <Form.Control
-          required
-          type="password"
-          value={data.password.value}
-          isInvalid={data.password.isInvalid}
-          onChange={(e) => {
-            changeCallback({
-              password: {
-                value: e.target.value,
-                isInvalid: false,
-                errorMsg: '',
-              },
-            });
-          }}
-        />
+        <div className="position-relative">
+          <Form.Control
+            required
+            type={showPassword ? 'text' : 'password'}
+            value={data.password.value}
+            isInvalid={data.password.isInvalid}
+            style={{ paddingRight: '45px' }}
+            onChange={(e) => {
+              changeCallback({
+                password: {
+                  value: e.target.value,
+                  isInvalid: false,
+                  errorMsg: '',
+                },
+              });
+            }}
+          />
+          <button
+            type="button"
+            className="position-absolute top-50 translate-middle-y 
bg-transparent border-0"
+            style={{
+              cursor: 'pointer',
+              right: '12px',
+              padding: '4px',
+            }}
+            aria-label={showPassword ? t('hide_password') : t('show_password')}
+            onMouseDown={() => setShowPassword(true)}
+            onMouseUp={() => setShowPassword(false)}
+            onMouseLeave={() => setShowPassword(false)}>
+            {showPassword ? (
+              <Eye className="text-secondary" size={18} />
+            ) : (
+              <EyeSlash className="text-secondary" size={18} />
+            )}
+          </button>
+        </div>
         <Form.Text>{t('admin_password.text')}</Form.Text>
         <Form.Control.Feedback type="invalid">
           {data.password.errorMsg}

Reply via email to