GH-6452 Migrate installed_command.jsx to be pure and use Redux (#6903)
* Migrate installed_command.jsx to be pure and use Redux * Add test for InstalledCommand component * Fix failing test and typo * Whoops. Revert back deleted filter * Add filter test * Remove commands related code from /stores/integration_store.jsx
Этот коммит содержится в:
коммит произвёл
Harrison Healey
родитель
b54d134299
Коммит
ea095d6206
@@ -33,7 +33,7 @@ export default class CommandsContainer extends React.PureComponent {
|
||||
users: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Installed splash commands to display
|
||||
* Installed slash commands to display
|
||||
*/
|
||||
commands: PropTypes.array,
|
||||
|
||||
|
||||
@@ -1,43 +1,59 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Link} from 'react-router';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import DeleteIntegration from './delete_integration.jsx';
|
||||
|
||||
export default class InstalledCommand extends React.Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
team: PropTypes.object.isRequired,
|
||||
command: PropTypes.object.isRequired,
|
||||
onRegenToken: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
filter: PropTypes.string,
|
||||
creator: PropTypes.object.isRequired,
|
||||
canChange: PropTypes.bool.isRequired
|
||||
};
|
||||
export default class InstalledCommand extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
||||
/**
|
||||
* The team data
|
||||
*/
|
||||
team: PropTypes.object.isRequired,
|
||||
|
||||
/**
|
||||
* Installed slash command to display
|
||||
*/
|
||||
command: PropTypes.object.isRequired,
|
||||
|
||||
/**
|
||||
* The function to call when Regenerate Token link is clicked
|
||||
*/
|
||||
onRegenToken: PropTypes.func.isRequired,
|
||||
|
||||
/**
|
||||
* The function to call when Delete link is clicked
|
||||
*/
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
|
||||
/**
|
||||
* Set to filter command, comes from BackstageList
|
||||
*/
|
||||
filter: PropTypes.string,
|
||||
|
||||
/**
|
||||
* The creator user data
|
||||
*/
|
||||
creator: PropTypes.object.isRequired,
|
||||
|
||||
/**
|
||||
* Set to show edit link
|
||||
*/
|
||||
canChange: PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleRegenToken = this.handleRegenToken.bind(this);
|
||||
this.handleDelete = this.handleDelete.bind(this);
|
||||
|
||||
this.matchesFilter = this.matchesFilter.bind(this);
|
||||
}
|
||||
|
||||
handleRegenToken(e) {
|
||||
handleRegenToken = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
this.props.onRegenToken(this.props.command);
|
||||
}
|
||||
|
||||
handleDelete() {
|
||||
handleDelete = () => {
|
||||
this.props.onDelete(this.props.command);
|
||||
}
|
||||
|
||||
@@ -60,6 +76,7 @@ export default class InstalledCommand extends React.Component {
|
||||
}
|
||||
|
||||
let name;
|
||||
|
||||
if (command.display_name) {
|
||||
name = command.display_name;
|
||||
} else {
|
||||
|
||||
@@ -30,7 +30,7 @@ export default class InstalledCommands extends React.PureComponent {
|
||||
users: PropTypes.object,
|
||||
|
||||
/**
|
||||
* Installed splash commands to display
|
||||
* Installed slash commands to display
|
||||
*/
|
||||
commands: PropTypes.array,
|
||||
|
||||
@@ -40,7 +40,7 @@ export default class InstalledCommands extends React.PureComponent {
|
||||
loading: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Set to allow changes to installed splash commands
|
||||
* Set to allow changes to installed slash commands
|
||||
*/
|
||||
isAdmin: PropTypes.bool,
|
||||
|
||||
|
||||
@@ -91,36 +91,6 @@ class IntegrationStore extends EventEmitter {
|
||||
return store.getState().entities.integrations.outgoingHooks[id];
|
||||
}
|
||||
|
||||
hasReceivedCommands(teamId) {
|
||||
const commands = store.getState().entities.integrations.commands;
|
||||
|
||||
let hasTeam = false;
|
||||
Object.values(commands).forEach((command) => {
|
||||
if (command.team_id === teamId) {
|
||||
hasTeam = true;
|
||||
}
|
||||
});
|
||||
|
||||
return hasTeam;
|
||||
}
|
||||
|
||||
getCommands(teamId) {
|
||||
const commands = store.getState().entities.integrations.commands;
|
||||
|
||||
const teamCommands = [];
|
||||
Object.values(commands).forEach((command) => {
|
||||
if (command.team_id === teamId) {
|
||||
teamCommands.push(command);
|
||||
}
|
||||
});
|
||||
|
||||
return teamCommands;
|
||||
}
|
||||
|
||||
getCommand(teamId, id) {
|
||||
return store.getState().entities.integrations.commands[id];
|
||||
}
|
||||
|
||||
hasReceivedOAuthApps() {
|
||||
return Object.keys(store.getState().entities.integrations.oauthApps).length > 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`components/integrations/InstalledCommand should filter out command 1`] = `null`;
|
||||
|
||||
exports[`components/integrations/InstalledCommand should match snapshot 1`] = `
|
||||
<div
|
||||
className="backstage-list__item"
|
||||
>
|
||||
<div
|
||||
className="item-details"
|
||||
>
|
||||
<div
|
||||
className="item-details__row"
|
||||
>
|
||||
<span
|
||||
className="item-details__name"
|
||||
>
|
||||
test
|
||||
</span>
|
||||
<span
|
||||
className="item-details__trigger"
|
||||
>
|
||||
- /trigger test
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="item-details__row"
|
||||
>
|
||||
<span
|
||||
className="item-details__description"
|
||||
>
|
||||
test
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="item-details__row"
|
||||
>
|
||||
<span
|
||||
className="item-details__token"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Token: {token}"
|
||||
id="installed_integrations.token"
|
||||
values={
|
||||
Object {
|
||||
"token": "testToken",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="item-details__row"
|
||||
>
|
||||
<span
|
||||
className="item-details__creation"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Created by {creator} on {createAt, date, full}"
|
||||
id="installed_integrations.creation"
|
||||
values={
|
||||
Object {
|
||||
"createAt": "1499722850203",
|
||||
"creator": "test",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="item-actions"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Regenerate Token"
|
||||
id="installed_integrations.regenToken"
|
||||
values={Object {}}
|
||||
/>
|
||||
</a>
|
||||
-
|
||||
<Link
|
||||
onlyActiveOnIndex={false}
|
||||
style={Object {}}
|
||||
to="/test/integrations/commands/edit?id=r5tpgt4iepf45jt768jz84djic"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Edit"
|
||||
id="installed_integrations.edit"
|
||||
values={Object {}}
|
||||
/>
|
||||
</Link>
|
||||
-
|
||||
<DeleteIntegration
|
||||
messageId="installed_commands.delete.confirm"
|
||||
onDelete={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
83
webapp/tests/components/integrations/installed_command.test.jsx
Обычный файл
83
webapp/tests/components/integrations/installed_command.test.jsx
Обычный файл
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {shallow} from 'enzyme';
|
||||
|
||||
import InstalledCommand from 'components/integrations/components/installed_command.jsx';
|
||||
|
||||
describe('components/integrations/InstalledCommand', () => {
|
||||
const emptyFunction = jest.fn();
|
||||
const command = {
|
||||
id: 'r5tpgt4iepf45jt768jz84djic',
|
||||
display_name: 'test',
|
||||
description: 'test',
|
||||
trigger: 'trigger',
|
||||
auto_complete: 'test',
|
||||
auto_complete_hint: 'test',
|
||||
token: 'testToken',
|
||||
create_at: '1499722850203'
|
||||
};
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const wrapper = shallow(
|
||||
<InstalledCommand
|
||||
team={{
|
||||
name: 'test'
|
||||
}}
|
||||
command={command}
|
||||
onRegenToken={emptyFunction}
|
||||
onDelete={emptyFunction}
|
||||
filter={'trigger'}
|
||||
creator={{
|
||||
username: 'test'
|
||||
}}
|
||||
canChange={true}
|
||||
/>
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should call onRegenToken function', () => {
|
||||
const onRegenToken = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<InstalledCommand
|
||||
team={{
|
||||
name: 'test'
|
||||
}}
|
||||
command={command}
|
||||
onRegenToken={onRegenToken}
|
||||
onDelete={emptyFunction}
|
||||
filter={''}
|
||||
creator={{
|
||||
username: 'test'
|
||||
}}
|
||||
canChange={true}
|
||||
/>
|
||||
);
|
||||
wrapper.find('div.item-actions a').first().simulate('click', {preventDefault() {
|
||||
return jest.fn();
|
||||
}});
|
||||
|
||||
expect(onRegenToken).toBeCalled();
|
||||
});
|
||||
|
||||
test('should filter out command', () => {
|
||||
const wrapper = shallow(
|
||||
<InstalledCommand
|
||||
team={{
|
||||
name: 'test'
|
||||
}}
|
||||
command={command}
|
||||
onRegenToken={emptyFunction}
|
||||
onDelete={emptyFunction}
|
||||
filter={'filter'}
|
||||
creator={{
|
||||
username: 'test'
|
||||
}}
|
||||
canChange={true}
|
||||
/>
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
Ссылка в новой задаче
Block a user