Doug Lauder
2023-03-22 17:22:27 -04:00
коммит произвёл GitHub
родитель b61c096497
Коммит c943ed6859
13276 изменённых файлов: 1695615 добавлений и 223189 удалений

Просмотреть файл

@@ -0,0 +1,125 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/integrations/EditCommand should have match renderExtra 1`] = `
<ConfirmModal
confirmButtonClass="btn btn-primary"
confirmButtonText={
<Memo(MemoizedFormattedMessage)
defaultMessage="Update"
id="update_command.update"
/>
}
message={
<Memo(MemoizedFormattedMessage)
defaultMessage="Your changes may break the existing slash command. Are you sure you would like to update it?"
id="update_command.question"
/>
}
modalClass=""
onCancel={[Function]}
onConfirm={[Function]}
show={false}
title={
<Memo(MemoizedFormattedMessage)
defaultMessage="Edit Slash Command"
id="update_command.confirm"
/>
}
/>
`;
exports[`components/integrations/EditCommand should match snapshot 1`] = `
<AbstractCommand
action={[Function]}
footer={
Object {
"defaultMessage": "Update",
"id": "edit_command.update",
}
}
header={
Object {
"defaultMessage": "Edit",
"id": "integrations.edit",
}
}
initialCommand={
Object {
"auto_complete": true,
"auto_complete_desc": "auto_complete_desc",
"auto_complete_hint": "auto_complete_hint",
"create_at": 1499722850203,
"creator_id": "88oybd1dwfdoxpkpw1h5kpbyco",
"delete_at": 0,
"description": "description",
"display_name": "display_name",
"icon_url": "https://google.com/icon",
"id": "r5tpgt4iepf45jt768jz84djic",
"method": "G",
"team_id": "m5gix3oye3du8ghk4ko6h9cq7y",
"token": "jb6oyqh95irpbx8fo9zmndkp1r",
"trigger": "trigger",
"update_at": 1504468859001,
"url": "https://google.com/command",
"username": "username",
}
}
loading={
Object {
"defaultMessage": "Updating...",
"id": "edit_command.updating",
}
}
renderExtra={
<ConfirmModal
confirmButtonClass="btn btn-primary"
confirmButtonText={
<Memo(MemoizedFormattedMessage)
defaultMessage="Update"
id="update_command.update"
/>
}
message={
<Memo(MemoizedFormattedMessage)
defaultMessage="Your changes may break the existing slash command. Are you sure you would like to update it?"
id="update_command.question"
/>
}
modalClass=""
onCancel={[Function]}
onConfirm={[Function]}
show={false}
title={
<Memo(MemoizedFormattedMessage)
defaultMessage="Edit Slash Command"
id="update_command.confirm"
/>
}
/>
}
serverError=""
team={
Object {
"allow_open_invite": false,
"allowed_domains": "",
"company_name": "",
"create_at": 0,
"delete_at": 0,
"description": "",
"display_name": "name",
"email": "",
"group_constrained": false,
"id": "m5gix3oye3du8ghk4ko6h9cq7y",
"invite_id": "",
"name": "test",
"scheme_id": "id",
"type": "O",
"update_at": 0,
}
}
/>
`;
exports[`components/integrations/EditCommand should match snapshot when EnableCommands is false 1`] = `<LoadingScreen />`;
exports[`components/integrations/EditCommand should match snapshot, loading 1`] = `<LoadingScreen />`;

Просмотреть файл

@@ -0,0 +1,145 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {shallow} from 'enzyme';
import {Team} from '@mattermost/types/teams';
import {Command} from '@mattermost/types/integrations';
import {TestHelper} from 'utils/test_helper';
import EditCommand from 'components/integrations/edit_command/edit_command';
describe('components/integrations/EditCommand', () => {
const getCustomTeamCommands = jest.fn(
() => {
return new Promise<Command[]>((resolve) => {
process.nextTick(() => resolve([]));
});
},
);
const commands = {
r5tpgt4iepf45jt768jz84djic: TestHelper.getCommandMock({
id: 'r5tpgt4iepf45jt768jz84djic',
display_name: 'display_name',
description: 'description',
trigger: 'trigger',
auto_complete: true,
auto_complete_hint: 'auto_complete_hint',
auto_complete_desc: 'auto_complete_desc',
token: 'jb6oyqh95irpbx8fo9zmndkp1r',
create_at: 1499722850203,
creator_id: '88oybd1dwfdoxpkpw1h5kpbyco',
delete_at: 0,
icon_url: 'https://google.com/icon',
method: 'G',
team_id: 'm5gix3oye3du8ghk4ko6h9cq7y',
update_at: 1504468859001,
url: 'https://google.com/command',
username: 'username',
}),
};
const team: Team = TestHelper.getTeamMock({
name: 'test',
id: 'm5gix3oye3du8ghk4ko6h9cq7y',
});
const editCommandRequest = {
status: 'not_started',
error: null,
};
const baseProps = {
team,
commandId: 'r5tpgt4iepf45jt768jz84djic',
commands,
editCommandRequest,
actions: {
getCustomTeamCommands,
editCommand: jest.fn(),
},
enableCommands: true,
};
test('should match snapshot', () => {
const wrapper = shallow(
<EditCommand {...baseProps}/>,
);
wrapper.setState({originalCommand: commands.r5tpgt4iepf45jt768jz84djic});
expect(wrapper).toMatchSnapshot();
expect(baseProps.actions.getCustomTeamCommands).toHaveBeenCalled();
expect(baseProps.actions.getCustomTeamCommands).toHaveBeenCalledWith(team.id);
});
test('should match snapshot, loading', () => {
const wrapper = shallow(
<EditCommand {...baseProps}/>,
);
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot when EnableCommands is false', () => {
const actions = {
getCustomTeamCommands: jest.fn(),
editCommand: jest.fn(),
};
const props = {...baseProps, actions, enableCommands: false};
const wrapper = shallow(
<EditCommand {...props}/>,
);
expect(wrapper).toMatchSnapshot();
expect(actions.getCustomTeamCommands).not.toHaveBeenCalled();
});
test('should have match state when handleConfirmModal is called', () => {
const props = {...baseProps, getCustomTeamCommands};
const wrapper = shallow<EditCommand>(
<EditCommand {...props}/>,
);
wrapper.setState({showConfirmModal: false});
wrapper.instance().handleConfirmModal();
expect(wrapper.state('showConfirmModal')).toEqual(true);
});
test('should have match state when confirmModalDismissed is called', () => {
const props = {...baseProps, getCustomTeamCommands};
const wrapper = shallow<EditCommand>(
<EditCommand {...props}/>,
);
wrapper.setState({showConfirmModal: true});
wrapper.instance().confirmModalDismissed();
expect(wrapper.state('showConfirmModal')).toEqual(false);
});
test('should have match renderExtra', () => {
const props = {...baseProps, getCustomTeamCommands};
const wrapper = shallow<EditCommand>(
<EditCommand {...props}/>,
);
expect(wrapper.instance().renderExtra()).toMatchSnapshot();
});
test('should have match when editCommand is called', () => {
const props = {...baseProps, getCustomTeamCommands};
const wrapper = shallow<EditCommand>(
<EditCommand {...props}/>,
);
wrapper.setState({originalCommand: commands.r5tpgt4iepf45jt768jz84djic});
const instance = wrapper.instance();
instance.handleConfirmModal = jest.fn();
instance.submitCommand = jest.fn();
wrapper.instance().editCommand(commands.r5tpgt4iepf45jt768jz84djic);
expect(instance.handleConfirmModal).not.toBeCalled();
expect(instance.submitCommand).toBeCalled();
});
});

Просмотреть файл

@@ -0,0 +1,182 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {FormattedMessage} from 'react-intl';
import {Team} from '@mattermost/types/teams';
import {Command} from '@mattermost/types/integrations';
import {RelationOneToOne} from '@mattermost/types/utilities';
import {getHistory} from 'utils/browser_history';
import {t} from 'utils/i18n';
import LoadingScreen from 'components/loading_screen';
import ConfirmModal from 'components/confirm_modal';
import AbstractCommand from '../abstract_command.jsx';
const HEADER = {id: t('integrations.edit'), defaultMessage: 'Edit'};
const FOOTER = {id: t('edit_command.update'), defaultMessage: 'Update'};
const LOADING = {id: t('edit_command.updating'), defaultMessage: 'Updating...'};
type Props = {
/**
* The current team
*/
team: Team;
/**
* The id of the command to edit
*/
commandId: string | null;
/**
* Installed slash commands to display
*/
commands: RelationOneToOne<Command, Command>;
actions: {
/**
* The function to call to fetch team commands
*/
getCustomTeamCommands: (teamId: string) => Promise<Command[]>;
/**
* The function to call to edit command
*/
editCommand: (command?: Command) => Promise<{data?: Command; error?: Error}>;
};
/**
* Whether or not commands are enabled.
*/
enableCommands: boolean;
}
type State = {
originalCommand: Command | null;
showConfirmModal: boolean;
serverError: string;
}
export default class EditCommand extends React.PureComponent<Props, State> {
private newCommand?: Command;
public constructor(props: Props) {
super(props);
this.newCommand = undefined;
this.state = {
originalCommand: null,
showConfirmModal: false,
serverError: '',
};
}
public componentDidMount(): void {
if (this.props.enableCommands) {
this.props.actions.getCustomTeamCommands(this.props.team.id).then(
() => {
this.setState({
originalCommand: Object.values(this.props.commands).filter((command) => command.id === this.props.commandId)[0],
});
},
);
}
}
public editCommand = async (command: Command): Promise<void> => {
this.newCommand = command;
if (this.state.originalCommand?.id) {
command.id = this.state.originalCommand.id;
}
if (this.state.originalCommand?.url !== this.newCommand.url ||
this.state.originalCommand?.trigger !== this.newCommand.trigger ||
this.state.originalCommand?.method !== this.newCommand.method) {
this.handleConfirmModal();
} else {
await this.submitCommand();
}
}
public handleConfirmModal = (): void => {
this.setState({showConfirmModal: true});
}
public confirmModalDismissed = (): void => {
this.setState({showConfirmModal: false});
}
public submitCommand = async (): Promise<void> => {
this.setState({serverError: ''});
const {data, error} = await this.props.actions.editCommand(this.newCommand);
if (data) {
getHistory().push(`/${this.props.team.name}/integrations/commands`);
return;
}
this.setState({showConfirmModal: false});
if (error) {
this.setState({serverError: error.message});
}
}
public renderExtra = (): JSX.Element => {
const confirmButton = (
<FormattedMessage
id='update_command.update'
defaultMessage='Update'
/>
);
const confirmTitle = (
<FormattedMessage
id='update_command.confirm'
defaultMessage='Edit Slash Command'
/>
);
const confirmMessage = (
<FormattedMessage
id='update_command.question'
defaultMessage='Your changes may break the existing slash command. Are you sure you would like to update it?'
/>
);
return (
<ConfirmModal
title={confirmTitle}
message={confirmMessage}
confirmButtonText={confirmButton}
show={this.state.showConfirmModal}
onConfirm={this.submitCommand}
onCancel={this.confirmModalDismissed}
/>
);
}
public render(): JSX.Element {
if (!this.state.originalCommand) {
return <LoadingScreen/>;
}
return (
<AbstractCommand
team={this.props.team}
header={HEADER}
footer={FOOTER}
loading={LOADING}
renderExtra={this.renderExtra()}
action={this.editCommand}
serverError={this.state.serverError}
initialCommand={this.state.originalCommand}
/>
);
}
}

Просмотреть файл

@@ -0,0 +1,46 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {connect} from 'react-redux';
import {bindActionCreators, Dispatch, ActionCreatorsMapObject} from 'redux';
import {editCommand, getCustomTeamCommands} from 'mattermost-redux/actions/integrations';
import {getCommands} from 'mattermost-redux/selectors/entities/integrations';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {GlobalState} from '@mattermost/types/store';
import {GenericAction, ActionFunc} from 'mattermost-redux/types/actions';
import {Command} from '@mattermost/types/integrations';
import EditCommand from './edit_command';
type Props = {
location: Location;
}
type Actions = {
getCustomTeamCommands: (teamId: string) => Promise<Command[]>;
editCommand: (command?: Command) => Promise<{data?: Command; error?: Error}>;
}
function mapStateToProps(state: GlobalState, ownProps: Props) {
const config = getConfig(state);
const commandId = (new URLSearchParams(ownProps.location.search)).get('id');
const enableCommands = config.EnableCommands === 'true';
return {
commandId,
commands: getCommands(state),
enableCommands,
};
}
function mapDispatchToProps(dispatch: Dispatch<GenericAction>) {
return {
actions: bindActionCreators<ActionCreatorsMapObject<ActionFunc>, Actions>({
getCustomTeamCommands,
editCommand,
}, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(EditCommand);