1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 01:39:44 +01:00

[MMI] adds the jwt-url-form component (#18198)

* MMI adds the Jwt dropdown

* MMI prettier

* review fixes

* adds the component

* adds tests and story file

* lint & prettier fix

* prettier fix

* prettier and clean up

* prettier and clean up
This commit is contained in:
António Regadas 2023-03-20 11:55:53 +00:00 committed by GitHub
parent c59e2b4d44
commit 033b776c0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 344 additions and 1 deletions

View File

@ -257,6 +257,9 @@
"message": "This network connection relies on third parties. This connection may be less reliable or enable third-parties to track activity. $1", "message": "This network connection relies on third parties. This connection may be less reliable or enable third-parties to track activity. $1",
"description": "$1 is Learn more link" "description": "$1 is Learn more link"
}, },
"addNewToken": {
"message": "Add new token"
},
"addSuggestedTokens": { "addSuggestedTokens": {
"message": "Add suggested tokens" "message": "Add suggested tokens"
}, },
@ -1370,6 +1373,9 @@
"message": "File import not working? Click here!", "message": "File import not working? Click here!",
"description": "Helps user import their account from a JSON file" "description": "Helps user import their account from a JSON file"
}, },
"fileTooBig": {
"message": "The dropped file is too big."
},
"flaskSnapSettingsCardButtonCta": { "flaskSnapSettingsCardButtonCta": {
"message": "See details", "message": "See details",
"description": "Call to action a user can take to see more information about the snap that is installed" "description": "Call to action a user can take to see more information about the snap that is installed"
@ -3331,6 +3337,9 @@
"selectHdPath": { "selectHdPath": {
"message": "Select HD path" "message": "Select HD path"
}, },
"selectJWT": {
"message": "Select token"
},
"selectNFTPrivacyPreference": { "selectNFTPrivacyPreference": {
"message": "Turn on NFT detection in Settings" "message": "Turn on NFT detection in Settings"
}, },
@ -4003,7 +4012,7 @@
"message": "Select a quote" "message": "Select a quote"
}, },
"swapSelectAToken": { "swapSelectAToken": {
"message": "Select a token" "message": "Select token"
}, },
"swapSelectQuotePopoverDescription": { "swapSelectQuotePopoverDescription": {
"message": "Below are all the quotes gathered from multiple liquidity sources." "message": "Below are all the quotes gathered from multiple liquidity sources."

View File

@ -0,0 +1,46 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`JwtUrlForm shows JWT text area when no jwt token exists 1`] = `
<div>
<div
class="box jwt-url-form box--margin-bottom-8 box--display-flex box--flex-direction-row box--align-items-flex-start"
>
<div
class="box jwt-url-form__jwt-container box--margin-bottom-6 box--flex-direction-row"
>
<div
class="box box--flex-direction-row"
>
<p
class="box mm-text jwt-url-form__instruction mm-text--body-md mm-text--color-text-default box--flex-direction-row"
>
input text
</p>
<textarea
bordercolor="border-default"
class="jwt-url-form__input-jwt"
data-testid="jwt-input"
id="jwt-box"
/>
</div>
</div>
<div
class="box jwt-url-form__jwt-apiUrlInput box--flex-direction-row"
>
<p
class="box mm-text jwt-url-form__instruction mm-text--body-md mm-text--color-text-default box--flex-direction-row"
/>
<div
class="box box--flex-direction-row"
>
<input
class="jwt-url-form__input"
data-testid="jwt-api-url-input"
id="api-url-box"
value="url"
/>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1 @@
export { default } from './jwt-url-form';

View File

@ -0,0 +1,128 @@
import React, { useState, useRef } from 'react';
import PropTypes from 'prop-types';
import { useI18nContext } from '../../../hooks/useI18nContext';
import {
AlignItems,
DISPLAY,
BorderColor,
} from '../../../helpers/constants/design-system';
import { Text } from '../../component-library';
import JwtDropdown from '../jwt-dropdown';
import Button from '../../ui/button';
import Box from '../../ui/box';
const JwtUrlForm = (props) => {
const t = useI18nContext();
const inputRef = useRef();
const [addNewTokenClicked, setAddNewTokenClicked] = useState(false);
const [fileTooBigError, setFileTooBigError] = useState();
const renderJWTInput = () => {
const showAddNewToken = addNewTokenClicked;
const showJwtDropdown = props.jwtList.length >= 1;
return (
<Box className="jwt-url-form__jwt-container" marginBottom={6}>
{showJwtDropdown && (
<JwtDropdown
data-testid="jwt-dropdown"
currentJwt={props.currentJwt ? props.currentJwt : props.jwtList[0]}
jwtList={props.jwtList}
onChange={(value) => {
props.onJwtChange(value);
setFileTooBigError(false);
}}
/>
)}
{showJwtDropdown && !showAddNewToken && (
<Box
className="jwt-url-form__btn__container"
display={DISPLAY.FLEX}
alignItems={AlignItems.center}
marginTop={2}
>
<Text>{t('or')}</Text>
<Button
type="secondary"
medium="true"
onClick={() => {
props.onJwtChange('');
setAddNewTokenClicked(true);
}}
>
<Text>{t('addNewToken')}</Text>
</Button>
</Box>
)}
{(!showJwtDropdown || showAddNewToken) && (
<Box>
<Text className="jwt-url-form__instruction">
{props.jwtInputText}
</Text>
{fileTooBigError && (
<span className="error">
<Text>{t('fileTooBig')}</Text>
</span>
)}
<textarea
className="jwt-url-form__input-jwt"
data-testid="jwt-input"
borderColor={BorderColor.borderDefault}
id="jwt-box"
onChange={(e) => {
props.onJwtChange(e.target.value);
setFileTooBigError(false);
}}
ref={inputRef.current}
value={props.currentJwt}
autoFocus
/>
</Box>
)}
</Box>
);
};
const renderAPIURLInput = () => {
return (
<Box className="jwt-url-form__jwt-apiUrlInput">
<Text className="jwt-url-form__instruction">{props.urlInputText}</Text>
<Box>
<input
className="jwt-url-form__input"
id="api-url-box"
data-testid="jwt-api-url-input"
onChange={(e) => {
props.onUrlChange(e.target.value);
}}
value={props.apiUrl}
/>
</Box>
</Box>
);
};
return (
<Box
className="jwt-url-form"
display={DISPLAY.FLEX}
alignItems={AlignItems.flexStart}
marginBottom={8}
>
{renderJWTInput()}
{renderAPIURLInput()}
</Box>
);
};
JwtUrlForm.propTypes = {
jwtList: PropTypes.array,
currentJwt: PropTypes.string,
onJwtChange: PropTypes.func,
jwtInputText: PropTypes.string,
apiUrl: PropTypes.string,
urlInputText: PropTypes.string,
onUrlChange: PropTypes.func,
};
export default JwtUrlForm;

View File

@ -0,0 +1,58 @@
.jwt-url-form {
flex-flow: column;
&__jwt-container {
width: 100%;
}
&__jwt-apiUrlInput {
width: 100%;
}
&__btn__container {
flex-flow: column;
width: 100%;
& > span {
padding-bottom: 10px;
}
}
&__instruction {
@include Paragraph;
align-self: flex-start;
display: block;
font-size: 14px;
}
&__input {
@include Paragraph;
height: 54px;
width: 100%;
border-radius: 4px;
background-color: var(--color-background-default);
margin-top: 16px;
padding: 0 10px;
}
&__input-jwt-container {
display: flex;
flex-flow: column;
align-items: center;
width: 100%;
margin-top: 16px;
}
&__input-jwt {
@include Paragraph;
height: 154px;
width: 100%;
border-radius: 4px;
background-color: var(--color-background-default);
color: var(--color-text-default);
padding: 10px;
}
}

View File

@ -0,0 +1,24 @@
import React from 'react';
import JwtUrlForm from '.';
export default {
title: 'Components/Institutional/JwtUrlForm',
component: JwtUrlForm,
args: {
jwtList: ['jwt1', 'jwt2', 'jwt3'],
currentJwt: 'jwt1',
urlInputText: 'url',
apiUrl: 'https://apiurl.io/v1',
jwtInputText: 'some input text',
onJwtChange: () => {
/**/
},
onUrlChange: () => {
/**/
},
},
};
export const DefaultStory = (args) => <JwtUrlForm {...args} />;
DefaultStory.storyName = 'JwtUrlForm';

View File

@ -0,0 +1,77 @@
import React from 'react';
import sinon from 'sinon';
import { fireEvent, screen } from '@testing-library/react';
import configureMockStore from 'redux-mock-store';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import JwtUrlForm from './jwt-url-form';
describe('JwtUrlForm', function () {
const mockStore = {
metamask: {
provider: {
type: 'test',
},
},
};
const store = configureMockStore()(mockStore);
const props = {
jwtList: ['jwt1'],
currentJwt: 'jwt1',
onJwtChange: sinon.spy(),
jwtInputText: 'input text',
apiUrl: 'url',
urlInputText: '',
onUrlChange: sinon.spy(),
};
it('opens JWT Url Form without input for new JWT', () => {
const { container, getByText } = renderWithProvider(
<JwtUrlForm {...props} />,
store,
);
const btn = container.querySelector(
'.jwt-url-form__btn__container .btn-secondary',
);
expect(btn).toHaveClass('button');
expect(getByText('Add new token')).toBeInTheDocument();
});
it('shows JWT textarea with provided input text', () => {
const { container } = renderWithProvider(<JwtUrlForm {...props} />, store);
const btn = container.querySelector(
'.jwt-url-form__btn__container .btn-secondary',
);
fireEvent.click(btn);
expect(screen.getByText('input text')).toBeInTheDocument();
});
it('goes through the api url input', () => {
const { queryByTestId } = renderWithProvider(
<JwtUrlForm {...props} />,
store,
);
const apiUrlinput = queryByTestId('jwt-api-url-input');
fireEvent.change(apiUrlinput, { target: { value: 'url' } });
expect(apiUrlinput.value).toBe('url');
});
it('shows JWT text area when no jwt token exists', () => {
const customProps = {
...props,
currentJwt: '',
jwtList: [],
};
const { container } = renderWithProvider(
<JwtUrlForm {...customProps} />,
store,
);
expect(container).toMatchSnapshot();
});
});