Skip to content

Commit

Permalink
feat: Added view toggle for password input field (#4303)
Browse files Browse the repository at this point in the history
Signed-off-by: Hrishav <hrishav.kumar@harness.io>
  • Loading branch information
hrishavjha committed Nov 21, 2023
1 parent 8ad33ad commit 11b8597
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 29 deletions.
@@ -0,0 +1,21 @@
.fieldContainer {
gap: 0.15rem;
.inputContainer {
:global {
.bp3-form-group {
margin-bottom: 0 !important;
}
.bp3-input-group .bp3-input:not(:last-child) {
padding-right: 36px !important;
}
}
position: relative;
}
.eyeIcon {
position: absolute;
right: 0.5rem;
top: 50%;
transform: translateY(-50%);
z-index: 1;
}
}
@@ -0,0 +1,11 @@
declare namespace PasswordInputModuleScssNamespace {
export interface IPasswordInputModuleScss {
eyeIcon: string;
fieldContainer: string;
inputContainer: string;
}
}

declare const PasswordInputModuleScssModule: PasswordInputModuleScssNamespace.IPasswordInputModuleScss;

export = PasswordInputModuleScssModule;
45 changes: 45 additions & 0 deletions chaoscenter/web/src/components/PasswordInput/PasswordInput.tsx
@@ -0,0 +1,45 @@
import React from 'react';
import { Icon, IconName } from '@harnessio/icons';
import { FormInput, Layout, Text } from '@harnessio/uicore';
import { Color, FontVariation } from '@harnessio/design-system';
import style from './PasswordInput.module.scss';

interface PassowrdInputProps {
disabled?: boolean;
placeholder?: string;
name: string;
label: string;
}

const PassowrdInput = (props: PassowrdInputProps): React.ReactElement => {
const { disabled, label, name, placeholder } = props;
const [showPassword, setShowPassword] = React.useState(false);
const stateIcon: IconName = showPassword ? 'eye-off' : 'eye-open';

function handleToggleClick(): void {
setShowPassword(!showPassword);
}

return (
<Layout.Vertical className={style.fieldContainer}>
{label && (
<Text font={{ variation: FontVariation.BODY, weight: 'semi-bold' }} color={Color.GREY_600}>
{label}
</Text>
)}
<div className={style.inputContainer}>
<FormInput.Text
name={name}
inputGroup={{
type: showPassword ? 'text' : 'password'
}}
placeholder={placeholder}
disabled={disabled}
/>
<Icon name={stateIcon} size={20} onClick={handleToggleClick} className={style.eyeIcon} />
</div>
</Layout.Vertical>
);
};

export default PassowrdInput;
3 changes: 3 additions & 0 deletions chaoscenter/web/src/components/PasswordInput/index.ts
@@ -0,0 +1,3 @@
import PassowrdInput from './PasswordInput';

export default PassowrdInput;
@@ -0,0 +1,7 @@
.mainWrapper {
:global {
.bp3-form-group {
margin-bottom: 0 !important;
}
}
}
@@ -0,0 +1,9 @@
declare namespace UserNameInputModuleScssNamespace {
export interface IUserNameInputModuleScss {
mainWrapper: string;
}
}

declare const UserNameInputModuleScssModule: UserNameInputModuleScssNamespace.IUserNameInputModuleScss;

export = UserNameInputModuleScssModule;
28 changes: 28 additions & 0 deletions chaoscenter/web/src/components/UserNameInput/UserNameInput.tsx
@@ -0,0 +1,28 @@
import React from 'react';
import { Color, FontVariation } from '@harnessio/design-system';
import { FormInput, Layout, Text } from '@harnessio/uicore';
import style from './UserNameInput.module.scss';

interface UserNameInputProps {
disabled?: boolean;
placeholder?: string;
name: string;
label: string;
}

const UserNameInput = (props: UserNameInputProps): React.ReactElement => {
const { disabled, label, name, placeholder } = props;

return (
<Layout.Vertical style={{ gap: '0.15rem' }} className={style.mainWrapper}>
{label && (
<Text font={{ variation: FontVariation.BODY, weight: 'semi-bold' }} color={Color.GREY_600}>
{label}
</Text>
)}
<FormInput.Text name={name} placeholder={placeholder} disabled={disabled} />
</Layout.Vertical>
);
};

export default UserNameInput;
3 changes: 3 additions & 0 deletions chaoscenter/web/src/components/UserNameInput/index.ts
@@ -0,0 +1,3 @@
import UserNameInput from './UserNameInput';

export default UserNameInput;
1 change: 1 addition & 0 deletions chaoscenter/web/src/strings/strings.en.yaml
Expand Up @@ -1005,6 +1005,7 @@ showDisabledUsers: Include disabled users
showLess: ' Show less'
showingAll: Showing all
showingLastRuns: Showing last 50 runs only
signIn: Sign In
signOut: Sign Out
singleRun: Single Run
source: Source
Expand Down
1 change: 1 addition & 0 deletions chaoscenter/web/src/strings/types.ts
Expand Up @@ -848,6 +848,7 @@ export interface StringsMap {
'showLess': unknown
'showingAll': unknown
'showingLastRuns': unknown
'signIn': unknown
'signOut': unknown
'singleRun': unknown
'source': unknown
Expand Down
72 changes: 43 additions & 29 deletions chaoscenter/web/src/views/Login/LoginPage.tsx
@@ -1,12 +1,14 @@
import React from 'react';
import { FormInput, Formik, Button, Text, Container } from '@harnessio/uicore';
import { Formik, Button, Text, Container, Layout } from '@harnessio/uicore';
import { Icon } from '@harnessio/icons';
import { Color } from '@harnessio/design-system';
import { Form } from 'formik';
import type { UseMutateFunction } from '@tanstack/react-query';
import AuthLayout from '@components/AuthLayout/AuthLayout';
import { useStrings } from '@strings';
import type { ErrorModel, LoginMutationProps, LoginResponse } from '@api/auth';
import PassowrdInput from '@components/PasswordInput';
import UserNameInput from '@components/UserNameInput';

interface LoginForm {
username: string;
Expand All @@ -22,36 +24,48 @@ export default function LoginPageView({ handleLogin, loading }: LoginPageViewPro
const { getString } = useStrings();

return (
<>
<AuthLayout>
<Icon name="chaos-litmuschaos" size={60} margin={{ bottom: 'medium' }} />
<Text font={{ size: 'large', weight: 'bold' }} color={Color.BLACK}>
{getString('welcomeToLitmus')}
</Text>
<Text font={{ size: 'medium' }} color={Color.BLACK} margin={{ top: 'xsmall' }}>
{getString('loginDescription')}
</Text>
<AuthLayout>
<Icon name="chaos-litmuschaos" size={60} margin={{ bottom: 'medium' }} />
<Text font={{ size: 'large', weight: 'bold' }} color={Color.BLACK}>
{getString('welcomeToLitmus')}
</Text>
<Text font={{ size: 'medium' }} color={Color.BLACK} margin={{ top: 'xsmall' }}>
{getString('loginDescription')}
</Text>

<Container margin={{ top: 'xxxlarge' }}>
<Formik<LoginForm>
initialValues={{ username: '', password: '' }}
formName="loginPageForm"
onSubmit={data =>
handleLogin({
body: data
})
}
>
<Form>
<FormInput.Text name="username" label={`Username`} disabled={loading} />
<FormInput.Text name="password" label={'Password'} inputGroup={{ type: 'password' }} disabled={loading} />
<Container margin={{ top: 'xxxlarge' }}>
<Formik<LoginForm>
initialValues={{ username: '', password: '' }}
formName="loginPageForm"
onSubmit={data =>
handleLogin({
body: data
})
}
>
<Form>
<Layout.Vertical style={{ gap: '1.5rem' }}>
<Layout.Vertical style={{ gap: '1rem' }} width={'100%'}>
<UserNameInput
name="username"
label={getString('username')}
placeholder={getString('enterYourUsername')}
disabled={loading}
/>
<PassowrdInput
name="password"
label={getString('password')}
placeholder={getString('enterYourPassword')}
disabled={loading}
/>
</Layout.Vertical>
<Button type="submit" intent="primary" loading={loading} disabled={loading} width="100%">
{'Sign in'}
{getString('signIn')}
</Button>
</Form>
</Formik>
</Container>
</AuthLayout>
</>
</Layout.Vertical>
</Form>
</Formik>
</Container>
</AuthLayout>
);
}

0 comments on commit 11b8597

Please sign in to comment.