#24744 Converted ./components/spinner_button.tsx from Class Component to Function Component (#24804)
* Converted [./components/spinner_button.tsx] to functional component * Converted [./components/spinner_button.tsx] to functional component * [./components/spinner_button.tsx]: wrapped the component with react.memo + removed default props + use multi-lines in args * [./components/spinner_button.tsx]: - fix lint errors in spinner button - fix error in missing prop on spinnerButton component * [./components/spinner_button.tsx]: - convert class component to functional component - fix lint errors in spinner button * fix:[spinner_button]: fix lint errors * - fix: [add_emoji.tsx]: add an id selector to the SpinnerButton to fix issue in unit test for this file. - fix: [add_emoji.test.tsx]: find the saveButton with id selector instead of using element directly (was causing test fai) - update test snapshots * fix[add_emoji]: replaced id with data-testid to be used in unit test --------- Co-authored-by: Noha M <33437197+NohaaAa@users.noreply.github.com> Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
@@ -202,7 +202,7 @@ exports[`AppsFormComponent should set match snapshot 1`] = `
|
|||||||
id="interactive_dialog.cancel"
|
id="interactive_dialog.cancel"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
autoFocus={false}
|
autoFocus={false}
|
||||||
className="btn btn-primary save-button"
|
className="btn btn-primary save-button"
|
||||||
id="appsModalSubmit"
|
id="appsModalSubmit"
|
||||||
@@ -215,7 +215,7 @@ exports[`AppsFormComponent should set match snapshot 1`] = `
|
|||||||
defaultMessage="Submit"
|
defaultMessage="Submit"
|
||||||
id="interactive_dialog.submit"
|
id="interactive_dialog.submit"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -121,8 +121,9 @@ exports[`components/emoji/components/AddEmoji should match snapshot 1`] = `
|
|||||||
id="add_emoji.cancel"
|
id="add_emoji.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
|
data-testid="save-button"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
spinning={false}
|
spinning={false}
|
||||||
spinningText="Saving..."
|
spinningText="Saving..."
|
||||||
@@ -132,7 +133,7 @@ exports[`components/emoji/components/AddEmoji should match snapshot 1`] = `
|
|||||||
defaultMessage="Save"
|
defaultMessage="Save"
|
||||||
id="add_emoji.save"
|
id="add_emoji.save"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -296,8 +297,9 @@ exports[`components/emoji/components/AddEmoji should select a file and match sna
|
|||||||
id="add_emoji.cancel"
|
id="add_emoji.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
|
data-testid="save-button"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
spinning={false}
|
spinning={false}
|
||||||
spinningText="Saving..."
|
spinningText="Saving..."
|
||||||
@@ -307,7 +309,7 @@ exports[`components/emoji/components/AddEmoji should select a file and match sna
|
|||||||
defaultMessage="Save"
|
defaultMessage="Save"
|
||||||
id="add_emoji.save"
|
id="add_emoji.save"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -435,8 +437,9 @@ exports[`components/emoji/components/AddEmoji should update emoji name and match
|
|||||||
id="add_emoji.cancel"
|
id="add_emoji.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
|
data-testid="save-button"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
spinning={false}
|
spinning={false}
|
||||||
spinningText="Saving..."
|
spinningText="Saving..."
|
||||||
@@ -446,7 +449,7 @@ exports[`components/emoji/components/AddEmoji should update emoji name and match
|
|||||||
defaultMessage="Save"
|
defaultMessage="Save"
|
||||||
id="add_emoji.save"
|
id="add_emoji.save"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ describe('components/emoji/components/AddEmoji', () => {
|
|||||||
const file = new Blob([image], {type: 'image/png'});
|
const file = new Blob([image], {type: 'image/png'});
|
||||||
wrapper.setState({image: file as File, imageUrl: image});
|
wrapper.setState({image: file as File, imageUrl: image});
|
||||||
|
|
||||||
const saveButton = wrapper.find('SpinnerButton').first();
|
const saveButton = wrapper.find({'data-testid': 'save-button'}).first();
|
||||||
const nameInput = wrapper.find('#name');
|
const nameInput = wrapper.find('#name');
|
||||||
nameInput.simulate('change', {target: {name: 'name', value: emojiName}});
|
nameInput.simulate('change', {target: {name: 'name', value: emojiName}});
|
||||||
|
|
||||||
|
|||||||
@@ -385,6 +385,7 @@ export default class AddEmoji extends React.PureComponent<AddEmojiProps, AddEmoj
|
|||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<SpinnerButton
|
||||||
|
data-testid='save-button'
|
||||||
className='btn btn-primary'
|
className='btn btn-primary'
|
||||||
type='submit'
|
type='submit'
|
||||||
spinning={this.state.saving}
|
spinning={this.state.saving}
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
|
|||||||
id="add_command.cancel"
|
id="add_command.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveCommand"
|
id="saveCommand"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -431,7 +431,7 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="Footer"
|
id="Footer"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
<div>
|
<div>
|
||||||
renderExtra
|
renderExtra
|
||||||
</div>
|
</div>
|
||||||
@@ -859,7 +859,7 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
|
|||||||
id="add_command.cancel"
|
id="add_command.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveCommand"
|
id="saveCommand"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -870,7 +870,7 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
|
|||||||
<span>
|
<span>
|
||||||
Footer as string
|
Footer as string
|
||||||
</span>
|
</span>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
<div>
|
<div>
|
||||||
renderExtra
|
renderExtra
|
||||||
</div>
|
</div>
|
||||||
@@ -1302,7 +1302,7 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
|
|||||||
id="add_command.cancel"
|
id="add_command.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveCommand"
|
id="saveCommand"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -1314,7 +1314,7 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="Footer"
|
id="Footer"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
<div>
|
<div>
|
||||||
renderExtra
|
renderExtra
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ exports[`components/integrations/AbstractIncomingWebhook should call action func
|
|||||||
id="add_incoming_webhook.cancel"
|
id="add_incoming_webhook.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveWebhook"
|
id="saveWebhook"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -254,7 +254,7 @@ exports[`components/integrations/AbstractIncomingWebhook should call action func
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="footer_id"
|
id="footer_id"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -503,7 +503,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot 1
|
|||||||
id="add_incoming_webhook.cancel"
|
id="add_incoming_webhook.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveWebhook"
|
id="saveWebhook"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -515,7 +515,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot 1
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="footer_id"
|
id="footer_id"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -767,7 +767,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
|
|||||||
id="add_incoming_webhook.cancel"
|
id="add_incoming_webhook.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveWebhook"
|
id="saveWebhook"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -779,7 +779,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="footer_id"
|
id="footer_id"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -995,7 +995,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
|
|||||||
id="add_incoming_webhook.cancel"
|
id="add_incoming_webhook.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveWebhook"
|
id="saveWebhook"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -1007,7 +1007,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="footer_id"
|
id="footer_id"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -1223,7 +1223,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
|
|||||||
id="add_incoming_webhook.cancel"
|
id="add_incoming_webhook.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveWebhook"
|
id="saveWebhook"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -1235,7 +1235,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="footer_id"
|
id="footer_id"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -1484,7 +1484,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
|
|||||||
id="add_incoming_webhook.cancel"
|
id="add_incoming_webhook.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveWebhook"
|
id="saveWebhook"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -1496,7 +1496,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="footer_id"
|
id="footer_id"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ https://test.com/callback2"
|
|||||||
id="installed_oauth_apps.cancel"
|
id="installed_oauth_apps.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveOauthApp"
|
id="saveOauthApp"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -295,7 +295,7 @@ https://test.com/callback2"
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="Footer"
|
id="Footer"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
<div>
|
<div>
|
||||||
renderExtra
|
renderExtra
|
||||||
</div>
|
</div>
|
||||||
@@ -590,7 +590,7 @@ exports[`components/integrations/AbstractOAuthApp should match snapshot, display
|
|||||||
id="installed_oauth_apps.cancel"
|
id="installed_oauth_apps.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveOauthApp"
|
id="saveOauthApp"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -602,7 +602,7 @@ exports[`components/integrations/AbstractOAuthApp should match snapshot, display
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="Footer"
|
id="Footer"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
<div>
|
<div>
|
||||||
renderExtra
|
renderExtra
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ callbackUrl2.com
|
|||||||
id="add_outgoing_webhook.cancel"
|
id="add_outgoing_webhook.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveWebhook"
|
id="saveWebhook"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -340,7 +340,7 @@ callbackUrl2.com
|
|||||||
defaultMessage="Footer"
|
defaultMessage="Footer"
|
||||||
id="footer_id"
|
id="footer_id"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ exports[`components/integrations/bots/AddBot blank 1`] = `
|
|||||||
id="bots.manage.add.cancel"
|
id="bots.manage.add.cancel"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SpinnerButton
|
<Memo(SpinnerButton)
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="saveBot"
|
id="saveBot"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@@ -354,7 +354,7 @@ exports[`components/integrations/bots/AddBot blank 1`] = `
|
|||||||
defaultMessage="Create Bot Account"
|
defaultMessage="Create Bot Account"
|
||||||
id="bots.manage.add.create"
|
id="bots.manage.add.create"
|
||||||
/>
|
/>
|
||||||
</SpinnerButton>
|
</Memo(SpinnerButton)>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ describe('components/SpinnerButton', () => {
|
|||||||
id='my-button-id'
|
id='my-button-id'
|
||||||
className='btn btn-success'
|
className='btn btn-success'
|
||||||
spinningText='Test'
|
spinningText='Test'
|
||||||
|
spinning={false}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,37 +1,35 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import React, {PureComponent} from 'react';
|
import React from 'react';
|
||||||
import type {ButtonHTMLAttributes, ReactNode} from 'react';
|
import type {ReactNode} from 'react';
|
||||||
|
|
||||||
import LoadingWrapper from 'components/widgets/loading/loading_wrapper';
|
import LoadingWrapper from 'components/widgets/loading/loading_wrapper';
|
||||||
|
|
||||||
type Props = {
|
type Props = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
spinning: boolean;
|
spinning: boolean;
|
||||||
spinningText: ReactNode;
|
spinningText: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class SpinnerButton extends PureComponent<Props & ButtonHTMLAttributes<HTMLButtonElement>> {
|
const SpinnerButton = ({
|
||||||
public static defaultProps: Partial<Props> = {
|
spinning = false,
|
||||||
spinning: false,
|
spinningText,
|
||||||
};
|
children,
|
||||||
|
...props
|
||||||
public render(): JSX.Element {
|
}: Props) => {
|
||||||
const {spinning, spinningText, children, ...props} = this.props;
|
return (
|
||||||
|
<button
|
||||||
return (
|
disabled={spinning}
|
||||||
<button
|
{...props}
|
||||||
disabled={spinning}
|
>
|
||||||
{...props}
|
<LoadingWrapper
|
||||||
|
loading={spinning}
|
||||||
|
text={spinningText}
|
||||||
>
|
>
|
||||||
<LoadingWrapper
|
{children}
|
||||||
loading={spinning}
|
</LoadingWrapper>
|
||||||
text={spinningText}
|
</button>
|
||||||
>
|
);
|
||||||
{children}
|
};
|
||||||
</LoadingWrapper>
|
export default React.memo(SpinnerButton);
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user