Fixing merge
Этот коммит содержится в:
@@ -120,7 +120,10 @@ export default class CenterPanel extends React.Component {
|
||||
id='app-content'
|
||||
className='app__content'
|
||||
>
|
||||
<div id='channel-header'>
|
||||
<div
|
||||
id='channel-header'
|
||||
className='channel-header'
|
||||
>
|
||||
<ChannelHeader
|
||||
user={this.state.user}
|
||||
/>
|
||||
|
||||
101
webapp/components/code_preview.jsx
Обычный файл
101
webapp/components/code_preview.jsx
Обычный файл
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import $ from 'jquery';
|
||||
import * as syntaxHightlighting from 'utils/syntax_hightlighting.jsx';
|
||||
import Constants from 'utils/constants.jsx';
|
||||
import FileInfoPreview from './file_info_preview.jsx';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default class CodePreview extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.updateStateFromProps = this.updateStateFromProps.bind(this);
|
||||
this.handleReceivedError = this.handleReceivedError.bind(this);
|
||||
this.handleReceivedCode = this.handleReceivedCode.bind(this);
|
||||
|
||||
this.state = {
|
||||
code: '',
|
||||
lang: '',
|
||||
loading: true,
|
||||
success: true
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateStateFromProps(this.props);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.fileUrl !== nextProps.fileUrl) {
|
||||
this.updateStateFromProps(nextProps);
|
||||
}
|
||||
}
|
||||
|
||||
updateStateFromProps(props) {
|
||||
var usedLanguage = syntaxHightlighting.getLang(props.filename);
|
||||
|
||||
if (!usedLanguage || props.fileInfo.size > Constants.CODE_PREVIEW_MAX_FILE_SIZE) {
|
||||
this.setState({code: '', lang: '', loading: false, success: false});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({code: '', lang: usedLanguage, loading: true});
|
||||
|
||||
$.ajax({
|
||||
async: true,
|
||||
url: props.fileUrl,
|
||||
type: 'GET',
|
||||
error: this.handleReceivedError,
|
||||
success: this.handleReceivedCode
|
||||
});
|
||||
}
|
||||
|
||||
handleReceivedCode(data) {
|
||||
const parsed = syntaxHightlighting.formatCode(this.state.lang, data, this.props.filename);
|
||||
this.setState({code: parsed, loading: false, success: true});
|
||||
}
|
||||
|
||||
handleReceivedError() {
|
||||
this.setState({loading: false, success: false});
|
||||
}
|
||||
|
||||
static support(filename) {
|
||||
return typeof syntaxHightlighting.getLang(filename) !== 'undefined';
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.loading) {
|
||||
return (
|
||||
<div className='view-image__loading'>
|
||||
<img
|
||||
className='loader-image'
|
||||
src='/static/images/load.gif'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.state.success) {
|
||||
return (
|
||||
<FileInfoPreview
|
||||
filename={this.props.filename}
|
||||
fileUrl={this.props.fileUrl}
|
||||
fileInfo={this.props.fileInfo}
|
||||
formatMessage={this.props.formatMessage}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <div dangerouslySetInnerHTML={{__html: this.state.code}}/>;
|
||||
}
|
||||
}
|
||||
|
||||
CodePreview.propTypes = {
|
||||
filename: React.PropTypes.string.isRequired,
|
||||
fileUrl: React.PropTypes.string.isRequired,
|
||||
fileInfo: React.PropTypes.object.isRequired,
|
||||
formatMessage: React.PropTypes.func.isRequired
|
||||
};
|
||||
@@ -160,7 +160,7 @@ export default class MoreChannels extends React.Component {
|
||||
|
||||
return (
|
||||
<div
|
||||
className='modal fade'
|
||||
className='modal fade more-channel__modal'
|
||||
id='more_channels'
|
||||
ref='modal'
|
||||
tabIndex='-1'
|
||||
|
||||
@@ -38,7 +38,7 @@ class NewChannelModal extends React.Component {
|
||||
}
|
||||
componentDidMount() {
|
||||
if (Utils.isBrowserIE()) {
|
||||
$('body').addClass('browser--IE');
|
||||
$('body').addClass('browser--ie');
|
||||
}
|
||||
}
|
||||
handleSubmit(e) {
|
||||
|
||||
@@ -158,6 +158,7 @@ export default class PopoverListMembers extends React.Component {
|
||||
<Popover
|
||||
ref='memebersPopover'
|
||||
title={title}
|
||||
className='member-list__popover'
|
||||
id='member-list-popover'
|
||||
>
|
||||
<div className='more-modal__list'>{popoverHtml}</div>
|
||||
|
||||
@@ -37,9 +37,9 @@ CommandSuggestion.propTypes = {
|
||||
};
|
||||
|
||||
export default class CommandProvider {
|
||||
handlePretextChanged(suggestionId, pretext) {
|
||||
handlePretextChanged(suggestionId, pretext, channelId) {
|
||||
if (pretext.startsWith('/')) {
|
||||
AsyncClient.getSuggestedCommands(pretext, suggestionId, CommandSuggestion);
|
||||
AsyncClient.getSuggestedCommands(pretext, channelId, suggestionId, CommandSuggestion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ export default class SuggestionBox extends React.Component {
|
||||
|
||||
handlePretextChanged(pretext) {
|
||||
for (const provider of this.props.providers) {
|
||||
provider.handlePretextChanged(this.suggestionId, pretext);
|
||||
provider.handlePretextChanged(this.suggestionId, pretext, this.props.channelId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,6 +160,7 @@ SuggestionBox.propTypes = {
|
||||
value: React.PropTypes.string.isRequired,
|
||||
onUserInput: React.PropTypes.func,
|
||||
providers: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||
channelId: React.PropTypes.string,
|
||||
|
||||
// explicitly name any input event handlers we override and need to manually call
|
||||
onChange: React.PropTypes.func,
|
||||
|
||||
@@ -224,6 +224,7 @@ export default class Textbox extends React.Component {
|
||||
style={{visibility: this.state.preview ? 'hidden' : 'visible'}}
|
||||
listComponent={SuggestionList}
|
||||
providers={this.suggestionProviders}
|
||||
channelId={this.props.channelId}
|
||||
/>
|
||||
<div
|
||||
ref='preview'
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
import LoadingScreen from '../loading_screen.jsx';
|
||||
|
||||
import * as Client from 'utils/client.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
import Constants from 'utils/constants.jsx';
|
||||
|
||||
import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'react-intl';
|
||||
|
||||
const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
|
||||
|
||||
const holders = defineMessages({
|
||||
requestTypePost: {
|
||||
id: 'user.settings.cmds.request_type_post',
|
||||
@@ -59,6 +63,7 @@ export default class ManageCommandCmds extends React.Component {
|
||||
this.getCmds = this.getCmds.bind(this);
|
||||
this.addNewCmd = this.addNewCmd.bind(this);
|
||||
this.emptyCmd = this.emptyCmd.bind(this);
|
||||
this.updateExternalManagement = this.updateExternalManagement.bind(this);
|
||||
this.updateTrigger = this.updateTrigger.bind(this);
|
||||
this.updateURL = this.updateURL.bind(this);
|
||||
this.updateMethod = this.updateMethod.bind(this);
|
||||
@@ -99,7 +104,7 @@ export default class ManageCommandCmds extends React.Component {
|
||||
addNewCmd(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (this.state.cmd.trigger === '' || this.state.cmd.url === '') {
|
||||
if (this.state.cmd.url === '' || (this.state.cmd.trigger === '' && !this.state.external_management)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -189,6 +194,12 @@ export default class ManageCommandCmds extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
updateExternalManagement(e) {
|
||||
var cmd = this.state.cmd;
|
||||
cmd.external_management = e.target.checked;
|
||||
this.setState(cmd);
|
||||
}
|
||||
|
||||
updateTrigger(e) {
|
||||
var cmd = this.state.cmd;
|
||||
cmd.trigger = e.target.value;
|
||||
@@ -270,11 +281,26 @@ export default class ManageCommandCmds extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
let slashCommandAutocompleteDiv;
|
||||
if (Utils.isFeatureEnabled(PreReleaseFeatures.SLASHCMD_AUTOCMP)) {
|
||||
slashCommandAutocompleteDiv = (
|
||||
<div className='padding-top x2'>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.external_management'
|
||||
defaultMessage='External management: '
|
||||
/>
|
||||
</strong><span className='word-break--all'>{cmd.external_management ? this.props.intl.formatMessage(holders.autocompleteYes) : this.props.intl.formatMessage(holders.autocompleteNo)}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
cmds.push(
|
||||
<div
|
||||
key={cmd.id}
|
||||
className='webhook__item webcmd__item'
|
||||
>
|
||||
{slashCommandAutocompleteDiv}
|
||||
{triggerDiv}
|
||||
<div className='padding-top x2 webcmd__url'>
|
||||
<strong>
|
||||
@@ -416,7 +442,170 @@ export default class ManageCommandCmds extends React.Component {
|
||||
</div>
|
||||
);
|
||||
|
||||
const disableButton = this.state.cmd.trigger === '' || this.state.cmd.url === '';
|
||||
const disableButton = this.state.cmd.url === '' || (this.state.cmd.trigger === '' && !this.state.external_management);
|
||||
|
||||
let triggerInput;
|
||||
if (!this.state.cmd.external_management) {
|
||||
triggerInput = (
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.trigger'
|
||||
defaultMessage='Command Trigger Word: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='trigger'
|
||||
className='form-control'
|
||||
value={this.state.cmd.trigger}
|
||||
onChange={this.updateTrigger}
|
||||
placeholder={this.props.intl.formatMessage(holders.addTriggerPlaceholder)}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.trigger_desc'
|
||||
defaultMessage='Examples: /patient, /client, /employee Reserved: /echo, /join, /logout, /me, /shrug'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let slashCommandAutocompleteCheckbox;
|
||||
if (Utils.isFeatureEnabled(PreReleaseFeatures.SLASHCMD_AUTOCMP)) {
|
||||
slashCommandAutocompleteCheckbox = (
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.external_management'
|
||||
defaultMessage='External management: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
type='checkbox'
|
||||
checked={this.state.cmd.external_management}
|
||||
onChange={this.updateExternalManagement}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.slashCmd_autocmp'
|
||||
defaultMessage='Enable external application to offer autocomplete'
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
let autoCompleteSettings;
|
||||
if (!this.state.cmd.external_management) {
|
||||
autoCompleteSettings = (
|
||||
<div>
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete'
|
||||
defaultMessage='Autocomplete: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
type='checkbox'
|
||||
checked={this.state.cmd.auto_complete}
|
||||
onChange={this.updateAutoComplete}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_help'
|
||||
defaultMessage=' Show this command in the autocomplete list.'
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_hint'
|
||||
defaultMessage='Autocomplete Hint: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='autoCompleteHint'
|
||||
className='form-control'
|
||||
value={this.state.cmd.auto_complete_hint}
|
||||
onChange={this.updateAutoCompleteHint}
|
||||
placeholder={this.props.intl.formatMessage(holders.addAutoCompleteHintPlaceholder)}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_hint_desc'
|
||||
defaultMessage='Optional hint in the autocomplete list about parameters needed for command.'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_desc'
|
||||
defaultMessage='Autocomplete Description: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='autoCompleteDesc'
|
||||
className='form-control'
|
||||
value={this.state.cmd.auto_complete_desc}
|
||||
onChange={this.updateAutoCompleteDesc}
|
||||
placeholder={this.props.intl.formatMessage(holders.addAutoCompleteDescPlaceholder)}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_desc_desc'
|
||||
defaultMessage='Optional short description of slash command for the autocomplete list.'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.display_name'
|
||||
defaultMessage='Descriptive Label: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='displayName'
|
||||
className='form-control'
|
||||
value={this.state.cmd.display_name}
|
||||
onChange={this.updateDisplayName}
|
||||
placeholder={this.props.intl.formatMessage(holders.addDisplayNamePlaceholder)}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.cmd_display_name'
|
||||
defaultMessage='Brief description of slash command to show in listings.'
|
||||
/>
|
||||
</div>
|
||||
{addError}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div key='addCommandCmd'>
|
||||
@@ -433,29 +622,8 @@ export default class ManageCommandCmds extends React.Component {
|
||||
<div className='padding-top divider-light'></div>
|
||||
<div className='padding-top'>
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.trigger'
|
||||
defaultMessage='Command Trigger Word: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='trigger'
|
||||
className='form-control'
|
||||
value={this.state.cmd.trigger}
|
||||
onChange={this.updateTrigger}
|
||||
placeholder={this.props.intl.formatMessage(holders.addTriggerPlaceholder)}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.trigger_desc'
|
||||
defaultMessage='Examples: /patient, /client, /employee Reserved: /echo, /join, /logout, /me, /shrug'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{slashCommandAutocompleteCheckbox}
|
||||
{triggerInput}
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
@@ -560,102 +728,7 @@ export default class ManageCommandCmds extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete'
|
||||
defaultMessage='Autocomplete: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
type='checkbox'
|
||||
checked={this.state.cmd.auto_complete}
|
||||
onChange={this.updateAutoComplete}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_help'
|
||||
defaultMessage=' Show this command in the autocomplete list.'
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_hint'
|
||||
defaultMessage='Autocomplete Hint: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='autoCompleteHint'
|
||||
className='form-control'
|
||||
value={this.state.cmd.auto_complete_hint}
|
||||
onChange={this.updateAutoCompleteHint}
|
||||
placeholder={this.props.intl.formatMessage(holders.addAutoCompleteHintPlaceholder)}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_hint_desc'
|
||||
defaultMessage='Optional hint in the autocomplete list about parameters needed for command.'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_desc'
|
||||
defaultMessage='Autocomplete Description: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='autoCompleteDesc'
|
||||
className='form-control'
|
||||
value={this.state.cmd.auto_complete_desc}
|
||||
onChange={this.updateAutoCompleteDesc}
|
||||
placeholder={this.props.intl.formatMessage(holders.addAutoCompleteDescPlaceholder)}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.auto_complete_desc_desc'
|
||||
defaultMessage='Optional short description of slash command for the autocomplete list.'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.display_name'
|
||||
defaultMessage='Descriptive Label: '
|
||||
/>
|
||||
</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='displayName'
|
||||
className='form-control'
|
||||
value={this.state.cmd.display_name}
|
||||
onChange={this.updateDisplayName}
|
||||
placeholder={this.props.intl.formatMessage(holders.addDisplayNamePlaceholder)}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<FormattedMessage
|
||||
id='user.settings.cmds.cmd_display_name'
|
||||
defaultMessage='Brief description of slash command to show in listings.'
|
||||
/>
|
||||
</div>
|
||||
{addError}
|
||||
</div>
|
||||
{autoCompleteSettings}
|
||||
|
||||
<div className='padding-top x2 padding-bottom'>
|
||||
<a
|
||||
|
||||
@@ -51,6 +51,10 @@ const holders = defineMessages({
|
||||
EMBED_TOGGLE: {
|
||||
id: 'user.settings.advance.embed_toggle',
|
||||
defaultMessage: 'Show toggle for all embed previews'
|
||||
},
|
||||
SLASHCMD_AUTOCMP: {
|
||||
id: 'user.settings.advance.slashCmd_autocmp',
|
||||
defaultMessage: 'Enable external application to offer slash command autocomplete'
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ export default class UserSettingsDisplay extends React.Component {
|
||||
const showUsername = (
|
||||
<FormattedMessage
|
||||
id='user.settings.display.showUsername'
|
||||
defaultMessage='Show username (team default)'
|
||||
defaultMessage='Show username (default)'
|
||||
/>
|
||||
);
|
||||
const showNickname = (
|
||||
|
||||
@@ -7,6 +7,7 @@ import * as Client from 'utils/client.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
import AudioVideoPreview from './audio_video_preview.jsx';
|
||||
import Constants from 'utils/constants.jsx';
|
||||
import CodePreview from './code_preview.jsx';
|
||||
import FileInfoPreview from './file_info_preview.jsx';
|
||||
import FileStore from 'stores/file_store.jsx';
|
||||
import ViewImagePopoverBar from './view_image_popover_bar.jsx';
|
||||
@@ -254,6 +255,15 @@ class ViewImageModal extends React.Component {
|
||||
formatMessage={this.props.intl.formatMessage}
|
||||
/>
|
||||
);
|
||||
} else if (CodePreview.support(filename)) {
|
||||
content = (
|
||||
<CodePreview
|
||||
filename={filename}
|
||||
fileUrl={fileUrl}
|
||||
fileInfo={fileInfo}
|
||||
formatMessage={this.props.intl.formatMessage}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
content = (
|
||||
<FileInfoPreview
|
||||
@@ -311,18 +321,19 @@ class ViewImageModal extends React.Component {
|
||||
<Modal
|
||||
show={this.props.show}
|
||||
onHide={this.props.onModalDismissed}
|
||||
className='image_modal'
|
||||
className='modal-image'
|
||||
dialogClassName='modal-image'
|
||||
>
|
||||
<Modal.Body
|
||||
modalClassName='image-body'
|
||||
modalClassName='modal-image__body'
|
||||
onClick={this.props.onModalDismissed}
|
||||
>
|
||||
<div
|
||||
className={'image-wrapper'}
|
||||
className={'modal-image__wrapper'}
|
||||
onClick={this.props.onModalDismissed}
|
||||
>
|
||||
<div
|
||||
className='modal-back'
|
||||
onMouseEnter={this.onMouseEnterImage}
|
||||
onMouseLeave={this.onMouseLeaveImage}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
|
||||
Ссылка в новой задаче
Block a user