[MM-56572] Preview doesn't work when editing a channel header (#26158)

This commit is contained in:
M-ZubairAhmed 2024-02-12 14:54:27 +00:00 committed by GitHub
parent 744b059a75
commit 41081b9eee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 93 additions and 64 deletions

View File

@ -65,7 +65,7 @@ exports[`components/EditChannelHeaderModal edit direct message channel 1`] = `
<Connect(Textbox)
channelId="fake-id"
characterLimit={1024}
createMessage="Edit the Channel Header..."
createMessage="Enter the Channel Header"
handlePostError={[Function]}
id="edit_textbox"
onChange={[Function]}
@ -85,7 +85,12 @@ exports[`components/EditChannelHeaderModal edit direct message channel 1`] = `
hasExceededCharacterLimit={false}
hasText={true}
isMarkdownPreviewEnabled={false}
previewMessageLink="Edit Header"
previewMessageLink={
<Memo(MemoizedFormattedMessage)
defaultMessage="Edit"
id="edit_channel_header_modal.previewHeader"
/>
}
showPreview={false}
updatePreview={[Function]}
/>
@ -191,7 +196,7 @@ exports[`components/EditChannelHeaderModal error with intl message 1`] = `
<Connect(Textbox)
channelId="fake-id"
characterLimit={1024}
createMessage="Edit the Channel Header..."
createMessage="Enter the Channel Header"
handlePostError={[Function]}
id="edit_textbox"
onChange={[Function]}
@ -211,7 +216,12 @@ exports[`components/EditChannelHeaderModal error with intl message 1`] = `
hasExceededCharacterLimit={false}
hasText={true}
isMarkdownPreviewEnabled={false}
previewMessageLink="Edit Header"
previewMessageLink={
<Memo(MemoizedFormattedMessage)
defaultMessage="Edit"
id="edit_channel_header_modal.previewHeader"
/>
}
showPreview={false}
updatePreview={[Function]}
/>
@ -335,7 +345,7 @@ exports[`components/EditChannelHeaderModal error without intl message 1`] = `
<Connect(Textbox)
channelId="fake-id"
characterLimit={1024}
createMessage="Edit the Channel Header..."
createMessage="Enter the Channel Header"
handlePostError={[Function]}
id="edit_textbox"
onChange={[Function]}
@ -355,7 +365,12 @@ exports[`components/EditChannelHeaderModal error without intl message 1`] = `
hasExceededCharacterLimit={false}
hasText={true}
isMarkdownPreviewEnabled={false}
previewMessageLink="Edit Header"
previewMessageLink={
<Memo(MemoizedFormattedMessage)
defaultMessage="Edit"
id="edit_channel_header_modal.previewHeader"
/>
}
showPreview={false}
updatePreview={[Function]}
/>
@ -471,7 +486,7 @@ exports[`components/EditChannelHeaderModal should match snapshot, init 1`] = `
<Connect(Textbox)
channelId="fake-id"
characterLimit={1024}
createMessage="Edit the Channel Header..."
createMessage="Enter the Channel Header"
handlePostError={[Function]}
id="edit_textbox"
onChange={[Function]}
@ -491,7 +506,12 @@ exports[`components/EditChannelHeaderModal should match snapshot, init 1`] = `
hasExceededCharacterLimit={false}
hasText={true}
isMarkdownPreviewEnabled={false}
previewMessageLink="Edit Header"
previewMessageLink={
<Memo(MemoizedFormattedMessage)
defaultMessage="Edit"
id="edit_channel_header_modal.previewHeader"
/>
}
showPreview={false}
updatePreview={[Function]}
/>
@ -597,7 +617,7 @@ exports[`components/EditChannelHeaderModal submitted 1`] = `
<Connect(Textbox)
channelId="fake-id"
characterLimit={1024}
createMessage="Edit the Channel Header..."
createMessage="Enter the Channel Header"
handlePostError={[Function]}
id="edit_textbox"
onChange={[Function]}
@ -617,7 +637,12 @@ exports[`components/EditChannelHeaderModal submitted 1`] = `
hasExceededCharacterLimit={false}
hasText={true}
isMarkdownPreviewEnabled={false}
previewMessageLink="Edit Header"
previewMessageLink={
<Memo(MemoizedFormattedMessage)
defaultMessage="Edit"
id="edit_channel_header_modal.previewHeader"
/>
}
showPreview={false}
updatePreview={[Function]}
/>

View File

@ -6,9 +6,11 @@ import React from 'react';
import type {Channel, ChannelType} from '@mattermost/types/channels';
import EditChannelHeaderModal from 'components/edit_channel_header_modal/edit_channel_header_modal';
import {EditChannelHeaderModal} from 'components/edit_channel_header_modal/edit_channel_header_modal';
import type {EditChannelHeaderModal as EditChannelHeaderModalClass} from 'components/edit_channel_header_modal/edit_channel_header_modal';
import Textbox from 'components/textbox';
import {type MockIntl} from 'tests/helpers/intl-test-helper';
import {testComponentForLineBreak} from 'tests/helpers/line_break_helpers';
import Constants from 'utils/constants';
import * as Utils from 'utils/utils';
@ -51,6 +53,9 @@ describe('components/EditChannelHeaderModal', () => {
setShowPreview: jest.fn(),
patchChannel: jest.fn().mockResolvedValue({}),
},
intl: {
formatMessage: ({defaultMessage}) => defaultMessage,
} as MockIntl,
};
test('should match snapshot, init', () => {
@ -105,11 +110,13 @@ describe('components/EditChannelHeaderModal', () => {
describe('handleSave', () => {
test('on no change, should hide the modal without trying to patch a channel', async () => {
const wrapper = shallow<EditChannelHeaderModal>(
const wrapper = shallow(
<EditChannelHeaderModal {...baseProps}/>,
);
await wrapper.instance().handleSave();
const instance = wrapper.instance() as EditChannelHeaderModalClass;
await instance.handleSave();
expect(wrapper.state('show')).toBe(false);
@ -119,13 +126,15 @@ describe('components/EditChannelHeaderModal', () => {
test('on error, should not close modal and set server error state', async () => {
baseProps.actions.patchChannel.mockResolvedValueOnce({error: serverError});
const wrapper = shallow<EditChannelHeaderModal>(
const wrapper = shallow(
<EditChannelHeaderModal {...baseProps}/>,
);
const instance = wrapper.instance() as EditChannelHeaderModalClass;
wrapper.setState({header: 'New header'});
await wrapper.instance().handleSave();
await instance.handleSave();
expect(wrapper.state('show')).toBe(true);
expect(wrapper.state('serverError')).toBe(serverError);
@ -134,13 +143,15 @@ describe('components/EditChannelHeaderModal', () => {
});
test('on success, should close modal', async () => {
const wrapper = shallow<EditChannelHeaderModal>(
const wrapper = shallow(
<EditChannelHeaderModal {...baseProps}/>,
);
const instance = wrapper.instance() as EditChannelHeaderModalClass;
wrapper.setState({header: 'New header'});
await wrapper.instance().handleSave();
await instance.handleSave();
expect(wrapper.state('show')).toBe(false);

View File

@ -3,13 +3,12 @@
import React from 'react';
import {Modal} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import type {WrappedComponentProps} from 'react-intl';
import {FormattedMessage, injectIntl} from 'react-intl';
import type {Channel} from '@mattermost/types/channels';
import type {ServerError} from '@mattermost/types/errors';
import type {ActionResult} from 'mattermost-redux/types/actions';
import Textbox, {TextboxLinks} from 'components/textbox';
import type {TextboxElement} from 'components/textbox';
import type TextboxClass from 'components/textbox/textbox';
@ -17,30 +16,15 @@ import type TextboxClass from 'components/textbox/textbox';
import Constants from 'utils/constants';
import {isKeyPressed} from 'utils/keyboard';
import {isMobile} from 'utils/user_agent';
import {insertLineBreakFromKeyEvent, isUnhandledLineBreakKeyCombo, localizeMessage} from 'utils/utils';
import {insertLineBreakFromKeyEvent, isUnhandledLineBreakKeyCombo} from 'utils/utils';
import type {PropsFromRedux} from './index';
const KeyCodes = Constants.KeyCodes;
const headerMaxLength = 1024;
type Props = {
/*
* Object with info about current channel ,
*/
channel: Channel;
/*
* boolean should be `ctrl` button pressed to send
*/
ctrlSend: boolean;
/*
* Should preview be showed
*/
shouldShowPreview: boolean;
markdownPreviewFeatureIsEnabled: boolean;
type OwnProps = {
/**
* Called when the modal has been hidden and should be removed.
@ -48,21 +32,12 @@ type Props = {
onExited: () => void;
/*
* Collection of redux actions
* Object with info about current channel ,
*/
actions: {
channel: Channel;
};
/*
* patch channel redux-action
*/
patchChannel: (channelId: string, patch: Partial<Channel>) => Promise<ActionResult>;
/*
* Set show preview for textbox
*/
setShowPreview: (showPreview: boolean) => void;
};
}
type Props = OwnProps & PropsFromRedux & WrappedComponentProps;
type State = {
header?: string;
@ -72,7 +47,7 @@ type State = {
postError?: React.ReactNode;
}
export default class EditChannelHeaderModal extends React.PureComponent<Props, State> {
export class EditChannelHeaderModal extends React.PureComponent<Props, State> {
private editChannelHeaderTextboxRef: React.RefObject<TextboxClass>;
constructor(props: Props) {
@ -266,7 +241,7 @@ export default class EditChannelHeaderModal extends React.PureComponent<Props, S
onKeyDown={this.handleKeyDown}
supportsCommands={false}
suggestionListPosition='bottom'
createMessage={localizeMessage('edit_channel_header.editHeader', 'Edit the Channel Header...')}
createMessage={this.props.intl.formatMessage({id: 'edit_channel_header_modal.placeholder', defaultMessage: 'Enter the Channel Header'})}
handlePostError={this.handlePostError}
channelId={this.props.channel.id!}
id='edit_textbox'
@ -283,7 +258,12 @@ export default class EditChannelHeaderModal extends React.PureComponent<Props, S
updatePreview={this.setShowPreview}
hasText={this.state.header ? this.state.header.length > 0 : false}
hasExceededCharacterLimit={this.state.header ? this.state.header.length > headerMaxLength : false}
previewMessageLink={localizeMessage('edit_channel_header.previewHeader', 'Edit Header')}
previewMessageLink={
<FormattedMessage
id='edit_channel_header_modal.previewHeader'
defaultMessage='Edit'
/>
}
/>
</div>
{this.renderError()}
@ -316,3 +296,5 @@ export default class EditChannelHeaderModal extends React.PureComponent<Props, S
);
}
}
export default injectIntl(EditChannelHeaderModal);

View File

@ -1,6 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import type {ConnectedProps} from 'react-redux';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import type {Dispatch} from 'redux';
@ -36,4 +37,8 @@ function mapDispatchToProps(dispatch: Dispatch) {
};
}
const connector = connect(mapStateToProps, mapDispatchToProps);
export type PropsFromRedux = ConnectedProps<typeof connector>;
export default connect(mapStateToProps, mapDispatchToProps)(EditChannelHeaderModal);

View File

@ -2,14 +2,14 @@
// See LICENSE.txt for license information.
import React from 'react';
import type {MouseEvent} from 'react';
import type {MouseEvent, ReactNode} from 'react';
import {FormattedMessage} from 'react-intl';
import ExternalLink from 'components/external_link';
type Props = {
showPreview?: boolean;
previewMessageLink?: string;
previewMessageLink?: ReactNode;
hasText?: boolean;
hasExceededCharacterLimit?: boolean;
isMarkdownPreviewEnabled: boolean;
@ -38,11 +38,7 @@ function TextboxLinks({
}
if (previewMessageLink) {
editHeader = (
<span>
{previewMessageLink}
</span>
);
editHeader = previewMessageLink;
} else {
editHeader = (
<FormattedMessage

View File

@ -3512,11 +3512,11 @@
"edit_channel_header_modal.cancel": "Cancel",
"edit_channel_header_modal.description": "Edit the text appearing next to the channel name in the header.",
"edit_channel_header_modal.error": "The text entered exceeds the character limit. The channel header is limited to {maxLength} characters.",
"edit_channel_header_modal.placeholder": "Edit the Channel Header...",
"edit_channel_header_modal.previewHeader": "Edit",
"edit_channel_header_modal.save": "Save",
"edit_channel_header_modal.title": "Edit Header for {channel}",
"edit_channel_header_modal.title_dm": "Edit Header",
"edit_channel_header.editHeader": "Edit the Channel Header...",
"edit_channel_header.previewHeader": "Edit Header",
"edit_channel_private_purpose_modal.body": "This text appears in the \"View Info\" modal of the private channel.",
"edit_channel_purpose_modal.body": "Describe how this channel should be used. This text appears in the channel list in the \"More...\" menu and helps others decide whether to join.",
"edit_channel_purpose_modal.cancel": "Cancel",

View File

@ -70,6 +70,16 @@
}
}
.textarea-wrapper-preview {
.custom-textarea.textbox-preview-area {
display: block;
}
.textbox-edit-area {
display: none;
}
}
.edit-post-footer {
position: relative;
display: inline-block;