mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Add code block actions plugin extensibility (#24348)
* Add code block actions plugin extensibility * Fixing tests * Fixing linter errors * Move Plugin components left of label --------- Co-authored-by: Christopher Speller <crspeller@gmail.com>
This commit is contained in:
parent
dbb39e44cc
commit
8c8b8b7e79
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,13 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {mount, ReactWrapper, shallow} from 'enzyme';
|
||||
import {mount, ReactWrapper} from 'enzyme';
|
||||
import React from 'react';
|
||||
import {act} from 'react-dom/test-utils';
|
||||
import {IntlProvider} from 'react-intl';
|
||||
import {Provider as ReduxProvider} from 'react-redux';
|
||||
|
||||
import mockStore from 'tests/test_store';
|
||||
|
||||
import CodeBlock from './code_block';
|
||||
|
||||
@ -20,6 +23,11 @@ const actImmediate = (wrapper: ReactWrapper) =>
|
||||
);
|
||||
|
||||
describe('codeBlock', () => {
|
||||
const state = {
|
||||
plugins: {components: {CodeBlockAction: []}},
|
||||
};
|
||||
const store = mockStore(state);
|
||||
|
||||
test('should render typescript code block before syntax highlighting', async () => {
|
||||
const language = 'typescript';
|
||||
const input = `\`\`\`${language}
|
||||
@ -29,12 +37,17 @@ const myFunction = () => {
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
const wrapper = shallow(
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>,
|
||||
const wrapper = mount(
|
||||
<ReduxProvider store={store}>
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>
|
||||
</ReduxProvider>,
|
||||
);
|
||||
await actImmediate(wrapper);
|
||||
|
||||
const languageHeader = wrapper.find('span.post-code__language').text();
|
||||
const lineNumbersDiv = wrapper.find('.post-code__line-numbers').exists();
|
||||
@ -55,12 +68,14 @@ const myFunction = () => {
|
||||
`;
|
||||
|
||||
const wrapper = mount(
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>,
|
||||
<ReduxProvider store={store}>
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>
|
||||
</ReduxProvider>,
|
||||
);
|
||||
await actImmediate(wrapper);
|
||||
|
||||
@ -73,7 +88,7 @@ const myFunction = () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should render html code block with proper indentation before syntax highlighting', () => {
|
||||
test('should render html code block with proper indentation before syntax highlighting', async () => {
|
||||
const language = 'html';
|
||||
const input = `\`\`\`${language}
|
||||
<div className='myClass'>
|
||||
@ -82,12 +97,17 @@ const myFunction = () => {
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
const wrapper = shallow(
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>,
|
||||
const wrapper = mount(
|
||||
<ReduxProvider store={store}>
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>
|
||||
</ReduxProvider>,
|
||||
);
|
||||
await actImmediate(wrapper);
|
||||
|
||||
const languageHeader = wrapper.find('span.post-code__language').text();
|
||||
const lineNumbersDiv = wrapper.find('.post-code__line-numbers').exists();
|
||||
@ -107,12 +127,14 @@ const myFunction = () => {
|
||||
`;
|
||||
|
||||
const wrapper = mount(
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>,
|
||||
<ReduxProvider store={store}>
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>
|
||||
</ReduxProvider>,
|
||||
);
|
||||
await actImmediate(wrapper);
|
||||
|
||||
@ -124,7 +146,7 @@ const myFunction = () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should render unknown language before syntax highlighting', () => {
|
||||
test('should render unknown language before syntax highlighting', async () => {
|
||||
const language = 'unknownLanguage';
|
||||
const input = `\`\`\`${language}
|
||||
this is my unknown language
|
||||
@ -132,12 +154,17 @@ it shouldn't highlight, it's just garbage
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
const wrapper = shallow(
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>,
|
||||
const wrapper = mount(
|
||||
<ReduxProvider store={store}>
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>
|
||||
</ReduxProvider>,
|
||||
);
|
||||
await actImmediate(wrapper);
|
||||
|
||||
const languageHeader = wrapper.find('span.post-code__language').exists();
|
||||
const lineNumbersDiv = wrapper.find('.post-code__line-numbers').exists();
|
||||
@ -156,12 +183,14 @@ it shouldn't highlight, it's just garbage
|
||||
`;
|
||||
|
||||
const wrapper = mount(
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>,
|
||||
<ReduxProvider store={store}>
|
||||
<IntlProvider locale='en'>
|
||||
<CodeBlock
|
||||
code={input}
|
||||
language={language}
|
||||
/>
|
||||
</IntlProvider>
|
||||
</ReduxProvider>,
|
||||
);
|
||||
await actImmediate(wrapper);
|
||||
|
||||
|
@ -3,6 +3,10 @@
|
||||
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
import {GlobalState} from 'types/store';
|
||||
|
||||
import CopyButton from 'components/copy_button';
|
||||
|
||||
import * as SyntaxHighlighting from 'utils/syntax_highlighting';
|
||||
@ -67,10 +71,27 @@ const CodeBlock: React.FC<Props> = ({code, language, searchedContent}: Props) =>
|
||||
htmlContent = `${searchedContent} ${content}`;
|
||||
}
|
||||
|
||||
const codeBlockActions = useSelector((state: GlobalState) => state.plugins.components.CodeBlockAction);
|
||||
const pluginItems = codeBlockActions?.
|
||||
map((item) => {
|
||||
if (!item.component) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const Component = item.component as any;
|
||||
return (
|
||||
<Component
|
||||
key={item.id}
|
||||
code={code}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className='post-code__overlay'>
|
||||
<CopyButton content={code}/>
|
||||
{pluginItems}
|
||||
{header}
|
||||
</div>
|
||||
<div className='hljs'>
|
||||
|
@ -508,6 +508,12 @@ export default class PluginRegistry {
|
||||
return dispatchPluginComponentAction('PostEditorAction', this.id, component);
|
||||
});
|
||||
|
||||
// Register a component to the add to the code block header.
|
||||
// Accepts a React component. Returns a unique identifier.
|
||||
registerCodeBlockActionComponent = reArg(['component'], ({component}: DPluginComponentProp) => {
|
||||
return dispatchPluginComponentAction('CodeBlockAction', this.id, component);
|
||||
});
|
||||
|
||||
// Register a component to the add to the new messages separator.
|
||||
// Accepts a React component. Returns a unique identifier.
|
||||
registerNewMessagesSeparatorActionComponent = reArg(['component'], ({component}: DPluginComponentProp) => {
|
||||
|
@ -183,6 +183,7 @@ const initialComponents: PluginsState['components'] = {
|
||||
PostDropdownMenu: [],
|
||||
PostAction: [],
|
||||
PostEditorAction: [],
|
||||
CodeBlockAction: [],
|
||||
NewMessagesSeparatorAction: [],
|
||||
Product: [],
|
||||
RightHandSidebarComponent: [],
|
||||
|
@ -29,6 +29,7 @@ export type PluginsState = {
|
||||
PostDropdownMenu: PluginComponent[];
|
||||
PostAction: PluginComponent[];
|
||||
PostEditorAction: PluginComponent[];
|
||||
CodeBlockAction: PluginComponent[];
|
||||
NewMessagesSeparatorAction: PluginComponent[];
|
||||
FilePreview: PluginComponent[];
|
||||
MainMenu: PluginComponent[];
|
||||
|
Loading…
Reference in New Issue
Block a user