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:
parent
c59e2b4d44
commit
033b776c0e
11
app/_locales/en/messages.json
generated
11
app/_locales/en/messages.json
generated
@ -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",
|
||||
"description": "$1 is Learn more link"
|
||||
},
|
||||
"addNewToken": {
|
||||
"message": "Add new token"
|
||||
},
|
||||
"addSuggestedTokens": {
|
||||
"message": "Add suggested tokens"
|
||||
},
|
||||
@ -1370,6 +1373,9 @@
|
||||
"message": "File import not working? Click here!",
|
||||
"description": "Helps user import their account from a JSON file"
|
||||
},
|
||||
"fileTooBig": {
|
||||
"message": "The dropped file is too big."
|
||||
},
|
||||
"flaskSnapSettingsCardButtonCta": {
|
||||
"message": "See details",
|
||||
"description": "Call to action a user can take to see more information about the snap that is installed"
|
||||
@ -3331,6 +3337,9 @@
|
||||
"selectHdPath": {
|
||||
"message": "Select HD path"
|
||||
},
|
||||
"selectJWT": {
|
||||
"message": "Select token"
|
||||
},
|
||||
"selectNFTPrivacyPreference": {
|
||||
"message": "Turn on NFT detection in Settings"
|
||||
},
|
||||
@ -4003,7 +4012,7 @@
|
||||
"message": "Select a quote"
|
||||
},
|
||||
"swapSelectAToken": {
|
||||
"message": "Select a token"
|
||||
"message": "Select token"
|
||||
},
|
||||
"swapSelectQuotePopoverDescription": {
|
||||
"message": "Below are all the quotes gathered from multiple liquidity sources."
|
||||
|
@ -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>
|
||||
`;
|
1
ui/components/institutional/jwt-url-form/index.js
Normal file
1
ui/components/institutional/jwt-url-form/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './jwt-url-form';
|
128
ui/components/institutional/jwt-url-form/jwt-url-form.js
Normal file
128
ui/components/institutional/jwt-url-form/jwt-url-form.js
Normal 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;
|
58
ui/components/institutional/jwt-url-form/jwt-url-form.scss
Normal file
58
ui/components/institutional/jwt-url-form/jwt-url-form.scss
Normal 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;
|
||||
}
|
||||
}
|
@ -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';
|
@ -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();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user