Merge branch 'master' of https://github.com/mattermost/platform into ui-improvements
Этот коммит содержится в:
@@ -8,6 +8,7 @@ const SocketStore = require('../stores/socket_store.jsx');
|
|||||||
const ChannelStore = require('../stores/channel_store.jsx');
|
const ChannelStore = require('../stores/channel_store.jsx');
|
||||||
const UserStore = require('../stores/user_store.jsx');
|
const UserStore = require('../stores/user_store.jsx');
|
||||||
const PostStore = require('../stores/post_store.jsx');
|
const PostStore = require('../stores/post_store.jsx');
|
||||||
|
const PreferenceStore = require('../stores/preference_store.jsx');
|
||||||
const Textbox = require('./textbox.jsx');
|
const Textbox = require('./textbox.jsx');
|
||||||
const MsgTyping = require('./msg_typing.jsx');
|
const MsgTyping = require('./msg_typing.jsx');
|
||||||
const FileUpload = require('./file_upload.jsx');
|
const FileUpload = require('./file_upload.jsx');
|
||||||
@@ -27,7 +28,7 @@ export default class CreateComment extends React.Component {
|
|||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
this.commentMsgKeyPress = this.commentMsgKeyPress.bind(this);
|
this.commentMsgKeyPress = this.commentMsgKeyPress.bind(this);
|
||||||
this.handleUserInput = this.handleUserInput.bind(this);
|
this.handleUserInput = this.handleUserInput.bind(this);
|
||||||
this.handleArrowUp = this.handleArrowUp.bind(this);
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
this.handleUploadStart = this.handleUploadStart.bind(this);
|
this.handleUploadStart = this.handleUploadStart.bind(this);
|
||||||
this.handleFileUploadComplete = this.handleFileUploadComplete.bind(this);
|
this.handleFileUploadComplete = this.handleFileUploadComplete.bind(this);
|
||||||
this.handleUploadError = this.handleUploadError.bind(this);
|
this.handleUploadError = this.handleUploadError.bind(this);
|
||||||
@@ -36,6 +37,7 @@ export default class CreateComment extends React.Component {
|
|||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
this.getFileCount = this.getFileCount.bind(this);
|
this.getFileCount = this.getFileCount.bind(this);
|
||||||
this.handleResize = this.handleResize.bind(this);
|
this.handleResize = this.handleResize.bind(this);
|
||||||
|
this.onPreferenceChange = this.onPreferenceChange.bind(this);
|
||||||
|
|
||||||
PostStore.clearCommentDraftUploads();
|
PostStore.clearCommentDraftUploads();
|
||||||
|
|
||||||
@@ -45,15 +47,23 @@ export default class CreateComment extends React.Component {
|
|||||||
uploadsInProgress: draft.uploadsInProgress,
|
uploadsInProgress: draft.uploadsInProgress,
|
||||||
previews: draft.previews,
|
previews: draft.previews,
|
||||||
submitting: false,
|
submitting: false,
|
||||||
windowWidth: Utils.windowWidth()
|
windowWidth: Utils.windowWidth(),
|
||||||
|
ctrlSend: PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', {value: 'false'}).value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
PreferenceStore.addChangeListener(this.onPreferenceChange);
|
||||||
window.addEventListener('resize', this.handleResize);
|
window.addEventListener('resize', this.handleResize);
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
PreferenceStore.removeChangeListener(this.onPreferenceChange);
|
||||||
window.removeEventListener('resize', this.handleResize);
|
window.removeEventListener('resize', this.handleResize);
|
||||||
}
|
}
|
||||||
|
onPreferenceChange() {
|
||||||
|
this.setState({
|
||||||
|
ctrlSend: PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', {value: 'false'}).value
|
||||||
|
});
|
||||||
|
}
|
||||||
handleResize() {
|
handleResize() {
|
||||||
this.setState({windowWidth: Utils.windowWidth()});
|
this.setState({windowWidth: Utils.windowWidth()});
|
||||||
}
|
}
|
||||||
@@ -140,10 +150,12 @@ export default class CreateComment extends React.Component {
|
|||||||
this.setState({messageText: '', submitting: false, postError: null, previews: [], serverError: null});
|
this.setState({messageText: '', submitting: false, postError: null, previews: [], serverError: null});
|
||||||
}
|
}
|
||||||
commentMsgKeyPress(e) {
|
commentMsgKeyPress(e) {
|
||||||
if (e.which === 13 && !e.shiftKey && !e.altKey) {
|
if (this.state.ctrlSend === 'true' && e.ctrlKey || this.state.ctrlSend === 'false') {
|
||||||
e.preventDefault();
|
if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
|
||||||
ReactDOM.findDOMNode(this.refs.textbox).blur();
|
e.preventDefault();
|
||||||
this.handleSubmit(e);
|
ReactDOM.findDOMNode(this.refs.textbox).blur();
|
||||||
|
this.handleSubmit(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const t = Date.now();
|
const t = Date.now();
|
||||||
@@ -161,7 +173,12 @@ export default class CreateComment extends React.Component {
|
|||||||
$('.post-right__scroll').perfectScrollbar('update');
|
$('.post-right__scroll').perfectScrollbar('update');
|
||||||
this.setState({messageText: messageText});
|
this.setState({messageText: messageText});
|
||||||
}
|
}
|
||||||
handleArrowUp(e) {
|
handleKeyDown(e) {
|
||||||
|
if (this.state.ctrlSend === 'true' && e.keyCode === KeyCodes.ENTER && e.ctrlKey === true) {
|
||||||
|
this.commentMsgKeyPress(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.keyCode === KeyCodes.UP && this.state.messageText === '') {
|
if (e.keyCode === KeyCodes.UP && this.state.messageText === '') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
@@ -313,7 +330,7 @@ export default class CreateComment extends React.Component {
|
|||||||
<Textbox
|
<Textbox
|
||||||
onUserInput={this.handleUserInput}
|
onUserInput={this.handleUserInput}
|
||||||
onKeyPress={this.commentMsgKeyPress}
|
onKeyPress={this.commentMsgKeyPress}
|
||||||
onKeyDown={this.handleArrowUp}
|
onKeyDown={this.handleKeyDown}
|
||||||
messageText={this.state.messageText}
|
messageText={this.state.messageText}
|
||||||
createMessage='Add a comment...'
|
createMessage='Add a comment...'
|
||||||
initialText=''
|
initialText=''
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const ChannelStore = require('../stores/channel_store.jsx');
|
|||||||
const PostStore = require('../stores/post_store.jsx');
|
const PostStore = require('../stores/post_store.jsx');
|
||||||
const UserStore = require('../stores/user_store.jsx');
|
const UserStore = require('../stores/user_store.jsx');
|
||||||
const SocketStore = require('../stores/socket_store.jsx');
|
const SocketStore = require('../stores/socket_store.jsx');
|
||||||
|
const PreferenceStore = require('../stores/preference_store.jsx');
|
||||||
const MsgTyping = require('./msg_typing.jsx');
|
const MsgTyping = require('./msg_typing.jsx');
|
||||||
const Textbox = require('./textbox.jsx');
|
const Textbox = require('./textbox.jsx');
|
||||||
const FileUpload = require('./file_upload.jsx');
|
const FileUpload = require('./file_upload.jsx');
|
||||||
@@ -36,9 +37,10 @@ export default class CreatePost extends React.Component {
|
|||||||
this.removePreview = this.removePreview.bind(this);
|
this.removePreview = this.removePreview.bind(this);
|
||||||
this.onChange = this.onChange.bind(this);
|
this.onChange = this.onChange.bind(this);
|
||||||
this.getFileCount = this.getFileCount.bind(this);
|
this.getFileCount = this.getFileCount.bind(this);
|
||||||
this.handleArrowUp = this.handleArrowUp.bind(this);
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
this.handleResize = this.handleResize.bind(this);
|
this.handleResize = this.handleResize.bind(this);
|
||||||
this.sendMessage = this.sendMessage.bind(this);
|
this.sendMessage = this.sendMessage.bind(this);
|
||||||
|
this.onPreferenceChange = this.onPreferenceChange.bind(this);
|
||||||
|
|
||||||
PostStore.clearDraftUploads();
|
PostStore.clearDraftUploads();
|
||||||
|
|
||||||
@@ -52,8 +54,16 @@ export default class CreatePost extends React.Component {
|
|||||||
submitting: false,
|
submitting: false,
|
||||||
initialText: draft.messageText,
|
initialText: draft.messageText,
|
||||||
windowWidth: Utils.windowWidth(),
|
windowWidth: Utils.windowWidth(),
|
||||||
windowHeight: Utils.windowHeight()
|
windowHeight: Utils.windowHeight(),
|
||||||
|
ctrlSend: PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', {value: 'false'}).value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PreferenceStore.addChangeListener(this.onPreferenceChange);
|
||||||
|
}
|
||||||
|
onPreferenceChange() {
|
||||||
|
this.setState({
|
||||||
|
ctrlSend: PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', {value: 'false'}).value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
handleResize() {
|
handleResize() {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -201,10 +211,12 @@ export default class CreatePost extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
postMsgKeyPress(e) {
|
postMsgKeyPress(e) {
|
||||||
if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
|
if (this.state.ctrlSend === 'true' && e.ctrlKey || this.state.ctrlSend === 'false') {
|
||||||
e.preventDefault();
|
if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
|
||||||
ReactDOM.findDOMNode(this.refs.textbox).blur();
|
e.preventDefault();
|
||||||
this.handleSubmit(e);
|
ReactDOM.findDOMNode(this.refs.textbox).blur();
|
||||||
|
this.handleSubmit(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const t = Date.now();
|
const t = Date.now();
|
||||||
@@ -328,7 +340,12 @@ export default class CreatePost extends React.Component {
|
|||||||
const draft = PostStore.getDraft(channelId);
|
const draft = PostStore.getDraft(channelId);
|
||||||
return draft.previews.length + draft.uploadsInProgress.length;
|
return draft.previews.length + draft.uploadsInProgress.length;
|
||||||
}
|
}
|
||||||
handleArrowUp(e) {
|
handleKeyDown(e) {
|
||||||
|
if (this.state.ctrlSend === 'true' && e.keyCode === KeyCodes.ENTER && e.ctrlKey === true) {
|
||||||
|
this.postMsgKeyPress(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.keyCode === KeyCodes.UP && this.state.messageText === '') {
|
if (e.keyCode === KeyCodes.UP && this.state.messageText === '') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
@@ -393,7 +410,7 @@ export default class CreatePost extends React.Component {
|
|||||||
<Textbox
|
<Textbox
|
||||||
onUserInput={this.handleUserInput}
|
onUserInput={this.handleUserInput}
|
||||||
onKeyPress={this.postMsgKeyPress}
|
onKeyPress={this.postMsgKeyPress}
|
||||||
onKeyDown={this.handleArrowUp}
|
onKeyDown={this.handleKeyDown}
|
||||||
onHeightChange={this.resizePostHolder}
|
onHeightChange={this.resizePostHolder}
|
||||||
messageText={this.state.messageText}
|
messageText={this.state.messageText}
|
||||||
createMessage='Write a message...'
|
createMessage='Write a message...'
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
var Constants = require('../../utils/constants.jsx');
|
|
||||||
|
|
||||||
export default class CodeThemeChooser extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {};
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const theme = this.props.theme;
|
|
||||||
|
|
||||||
const premadeThemes = [];
|
|
||||||
for (const k in Constants.CODE_THEMES) {
|
|
||||||
if (Constants.CODE_THEMES.hasOwnProperty(k)) {
|
|
||||||
let activeClass = '';
|
|
||||||
if (k === theme.codeTheme) {
|
|
||||||
activeClass = 'active';
|
|
||||||
}
|
|
||||||
|
|
||||||
premadeThemes.push(
|
|
||||||
<div
|
|
||||||
className='col-xs-6 col-sm-3 premade-themes'
|
|
||||||
key={'premade-theme-key' + k}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={activeClass}
|
|
||||||
onClick={() => this.props.updateTheme(k)}
|
|
||||||
>
|
|
||||||
<label>
|
|
||||||
<img
|
|
||||||
className='img-responsive'
|
|
||||||
src={'/static/images/themes/code_themes/' + k + '.png'}
|
|
||||||
/>
|
|
||||||
<div className='theme-label'>{Constants.CODE_THEMES[k]}</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='row'>
|
|
||||||
{premadeThemes}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeThemeChooser.propTypes = {
|
|
||||||
theme: React.PropTypes.object.isRequired,
|
|
||||||
updateTheme: React.PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
@@ -10,6 +10,7 @@ var AppearanceTab = require('./user_settings_appearance.jsx');
|
|||||||
var DeveloperTab = require('./user_settings_developer.jsx');
|
var DeveloperTab = require('./user_settings_developer.jsx');
|
||||||
var IntegrationsTab = require('./user_settings_integrations.jsx');
|
var IntegrationsTab = require('./user_settings_integrations.jsx');
|
||||||
var DisplayTab = require('./user_settings_display.jsx');
|
var DisplayTab = require('./user_settings_display.jsx');
|
||||||
|
var AdvancedTab = require('./user_settings_advanced.jsx');
|
||||||
|
|
||||||
export default class UserSettings extends React.Component {
|
export default class UserSettings extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -110,6 +111,17 @@ export default class UserSettings extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (this.props.activeTab === 'advanced') {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<AdvancedTab
|
||||||
|
user={this.state.user}
|
||||||
|
activeSection={this.props.activeSection}
|
||||||
|
updateSection={this.props.updateSection}
|
||||||
|
updateTab={this.props.updateTab}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div/>;
|
return <div/>;
|
||||||
|
|||||||
169
web/react/components/user_settings/user_settings_advanced.jsx
Обычный файл
169
web/react/components/user_settings/user_settings_advanced.jsx
Обычный файл
@@ -0,0 +1,169 @@
|
|||||||
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
const Client = require('../../utils/client.jsx');
|
||||||
|
const SettingItemMin = require('../setting_item_min.jsx');
|
||||||
|
const SettingItemMax = require('../setting_item_max.jsx');
|
||||||
|
const Constants = require('../../utils/constants.jsx');
|
||||||
|
const PreferenceStore = require('../../stores/preference_store.jsx');
|
||||||
|
|
||||||
|
export default class AdvancedSettingsDisplay extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.updateSection = this.updateSection.bind(this);
|
||||||
|
this.updateSetting = this.updateSetting.bind(this);
|
||||||
|
this.handleClose = this.handleClose.bind(this);
|
||||||
|
this.setupInitialState = this.setupInitialState.bind(this);
|
||||||
|
|
||||||
|
this.state = this.setupInitialState();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupInitialState() {
|
||||||
|
const sendOnCtrlEnter = PreferenceStore.getPreference(
|
||||||
|
Constants.Preferences.CATEGORY_ADVANCED_SETTINGS,
|
||||||
|
'send_on_ctrl_enter',
|
||||||
|
{value: 'false'}
|
||||||
|
).value;
|
||||||
|
|
||||||
|
return {
|
||||||
|
settings: {send_on_ctrl_enter: sendOnCtrlEnter}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSetting(setting, value) {
|
||||||
|
const settings = this.state.settings;
|
||||||
|
settings[setting] = value;
|
||||||
|
this.setState(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit(setting) {
|
||||||
|
const preference = PreferenceStore.setPreference(
|
||||||
|
Constants.Preferences.CATEGORY_ADVANCED_SETTINGS,
|
||||||
|
setting,
|
||||||
|
this.state.settings[setting]
|
||||||
|
);
|
||||||
|
|
||||||
|
Client.savePreferences([preference],
|
||||||
|
() => {
|
||||||
|
PreferenceStore.emitChange();
|
||||||
|
this.updateSection('');
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
this.setState({serverError: err.message});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSection(section) {
|
||||||
|
this.props.updateSection(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClose() {
|
||||||
|
this.updateSection('');
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
$('#user_settings').on('hidden.bs.modal', this.handleClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
$('#user_settings').off('hidden.bs.modal', this.handleClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const serverError = this.state.serverError || null;
|
||||||
|
let ctrlSendSection;
|
||||||
|
|
||||||
|
if (this.props.activeSection === 'advancedCtrlSend') {
|
||||||
|
const ctrlSendActive = [
|
||||||
|
this.state.settings.send_on_ctrl_enter === 'true',
|
||||||
|
this.state.settings.send_on_ctrl_enter === 'false'
|
||||||
|
];
|
||||||
|
|
||||||
|
const inputs = [
|
||||||
|
<div key='ctrlSendSetting'>
|
||||||
|
<div className='radio'>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type='radio'
|
||||||
|
checked={ctrlSendActive[0]}
|
||||||
|
onChange={this.updateSetting.bind(this, 'send_on_ctrl_enter', 'true')}
|
||||||
|
/>
|
||||||
|
{'On'}
|
||||||
|
</label>
|
||||||
|
<br/>
|
||||||
|
</div>
|
||||||
|
<div className='radio'>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type='radio'
|
||||||
|
checked={ctrlSendActive[1]}
|
||||||
|
onChange={this.updateSetting.bind(this, 'send_on_ctrl_enter', 'false')}
|
||||||
|
/>
|
||||||
|
{'Off'}
|
||||||
|
</label>
|
||||||
|
<br/>
|
||||||
|
</div>
|
||||||
|
<div><br/>{'If enabled \'Enter\' inserts a new line and \'Ctrl + Enter\' submits the message.'}</div>
|
||||||
|
</div>
|
||||||
|
];
|
||||||
|
|
||||||
|
ctrlSendSection = (
|
||||||
|
<SettingItemMax
|
||||||
|
title='Send messages on Ctrl + Enter'
|
||||||
|
inputs={inputs}
|
||||||
|
submit={() => this.handleSubmit('send_on_ctrl_enter')}
|
||||||
|
server_error={serverError}
|
||||||
|
updateSection={(e) => {
|
||||||
|
this.updateSection('');
|
||||||
|
e.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ctrlSendSection = (
|
||||||
|
<SettingItemMin
|
||||||
|
title='Send messages on Ctrl + Enter'
|
||||||
|
describe={this.state.settings.send_on_ctrl_enter === 'true' ? 'On' : 'Off'}
|
||||||
|
updateSection={() => this.props.updateSection('advancedCtrlSend')}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='modal-header'>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='close'
|
||||||
|
data-dismiss='modal'
|
||||||
|
aria-label='Close'
|
||||||
|
>
|
||||||
|
<span aria-hidden='true'>{'×'}</span>
|
||||||
|
</button>
|
||||||
|
<h4
|
||||||
|
className='modal-title'
|
||||||
|
ref='title'
|
||||||
|
>
|
||||||
|
<i className='modal-back'></i>
|
||||||
|
{'Advanced Settings'}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div className='user-settings'>
|
||||||
|
<h3 className='tab-header'>{'Advanced Settings'}</h3>
|
||||||
|
<div className='divider-dark first'/>
|
||||||
|
{ctrlSendSection}
|
||||||
|
<div className='divider-dark'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvancedSettingsDisplay.propTypes = {
|
||||||
|
user: React.PropTypes.object,
|
||||||
|
updateSection: React.PropTypes.func,
|
||||||
|
updateTab: React.PropTypes.func,
|
||||||
|
activeSection: React.PropTypes.string
|
||||||
|
};
|
||||||
@@ -7,7 +7,6 @@ var Utils = require('../../utils/utils.jsx');
|
|||||||
|
|
||||||
const CustomThemeChooser = require('./custom_theme_chooser.jsx');
|
const CustomThemeChooser = require('./custom_theme_chooser.jsx');
|
||||||
const PremadeThemeChooser = require('./premade_theme_chooser.jsx');
|
const PremadeThemeChooser = require('./premade_theme_chooser.jsx');
|
||||||
const CodeThemeChooser = require('./code_theme_chooser.jsx');
|
|
||||||
const AppDispatcher = require('../../dispatcher/app_dispatcher.jsx');
|
const AppDispatcher = require('../../dispatcher/app_dispatcher.jsx');
|
||||||
const Constants = require('../../utils/constants.jsx');
|
const Constants = require('../../utils/constants.jsx');
|
||||||
const ActionTypes = Constants.ActionTypes;
|
const ActionTypes = Constants.ActionTypes;
|
||||||
@@ -19,14 +18,12 @@ export default class UserSettingsAppearance extends React.Component {
|
|||||||
this.onChange = this.onChange.bind(this);
|
this.onChange = this.onChange.bind(this);
|
||||||
this.submitTheme = this.submitTheme.bind(this);
|
this.submitTheme = this.submitTheme.bind(this);
|
||||||
this.updateTheme = this.updateTheme.bind(this);
|
this.updateTheme = this.updateTheme.bind(this);
|
||||||
this.updateCodeTheme = this.updateCodeTheme.bind(this);
|
|
||||||
this.handleClose = this.handleClose.bind(this);
|
this.handleClose = this.handleClose.bind(this);
|
||||||
this.handleImportModal = this.handleImportModal.bind(this);
|
this.handleImportModal = this.handleImportModal.bind(this);
|
||||||
|
|
||||||
this.state = this.getStateFromStores();
|
this.state = this.getStateFromStores();
|
||||||
|
|
||||||
this.originalTheme = this.state.theme;
|
this.originalTheme = this.state.theme;
|
||||||
this.originalCodeTheme = this.state.theme.codeTheme;
|
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
UserStore.addChangeListener(this.onChange);
|
UserStore.addChangeListener(this.onChange);
|
||||||
@@ -61,10 +58,6 @@ export default class UserSettingsAppearance extends React.Component {
|
|||||||
type = 'custom';
|
type = 'custom';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!theme.codeTheme) {
|
|
||||||
theme.codeTheme = Constants.DEFAULT_CODE_THEME;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {theme, type};
|
return {theme, type};
|
||||||
}
|
}
|
||||||
onChange() {
|
onChange() {
|
||||||
@@ -100,13 +93,6 @@ export default class UserSettingsAppearance extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
updateTheme(theme) {
|
updateTheme(theme) {
|
||||||
theme.codeTheme = this.state.theme.codeTheme;
|
|
||||||
this.setState({theme});
|
|
||||||
Utils.applyTheme(theme);
|
|
||||||
}
|
|
||||||
updateCodeTheme(codeTheme) {
|
|
||||||
var theme = this.state.theme;
|
|
||||||
theme.codeTheme = codeTheme;
|
|
||||||
this.setState({theme});
|
this.setState({theme});
|
||||||
Utils.applyTheme(theme);
|
Utils.applyTheme(theme);
|
||||||
}
|
}
|
||||||
@@ -116,7 +102,6 @@ export default class UserSettingsAppearance extends React.Component {
|
|||||||
handleClose() {
|
handleClose() {
|
||||||
const state = this.getStateFromStores();
|
const state = this.getStateFromStores();
|
||||||
state.serverError = null;
|
state.serverError = null;
|
||||||
state.theme.codeTheme = this.originalCodeTheme;
|
|
||||||
|
|
||||||
Utils.applyTheme(state.theme);
|
Utils.applyTheme(state.theme);
|
||||||
|
|
||||||
@@ -185,13 +170,7 @@ export default class UserSettingsAppearance extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
{custom}
|
{custom}
|
||||||
<hr />
|
<hr />
|
||||||
<strong className='radio'>{'Code Theme'}</strong>
|
{serverError}
|
||||||
<CodeThemeChooser
|
|
||||||
theme={this.state.theme}
|
|
||||||
updateTheme={this.updateCodeTheme}
|
|
||||||
/>
|
|
||||||
<hr />
|
|
||||||
{serverError}
|
|
||||||
<a
|
<a
|
||||||
className='btn btn-sm btn-primary'
|
className='btn btn-sm btn-primary'
|
||||||
href='#'
|
href='#'
|
||||||
|
|||||||
@@ -570,6 +570,7 @@ export default class UserSettingsGeneralTab extends React.Component {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='modal-header'>
|
<div className='modal-header'>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export default class UserSettingsModal extends React.Component {
|
|||||||
tabs.push({name: 'integrations', uiName: 'Integrations', icon: 'glyphicon glyphicon-transfer'});
|
tabs.push({name: 'integrations', uiName: 'Integrations', icon: 'glyphicon glyphicon-transfer'});
|
||||||
}
|
}
|
||||||
tabs.push({name: 'display', uiName: 'Display', icon: 'glyphicon glyphicon-eye-open'});
|
tabs.push({name: 'display', uiName: 'Display', icon: 'glyphicon glyphicon-eye-open'});
|
||||||
|
tabs.push({name: 'advanced', uiName: 'Advanced', icon: 'glyphicon glyphicon-list-alt'});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
"autolinker": "0.18.1",
|
"autolinker": "0.18.1",
|
||||||
"babel-runtime": "5.8.24",
|
"babel-runtime": "5.8.24",
|
||||||
"flux": "2.1.1",
|
"flux": "2.1.1",
|
||||||
"highlight.js": "^8.9.1",
|
|
||||||
"keymirror": "0.1.1",
|
"keymirror": "0.1.1",
|
||||||
"marked": "0.3.5",
|
"marked": "0.3.5",
|
||||||
"object-assign": "3.0.0",
|
"object-assign": "3.0.0",
|
||||||
|
|||||||
@@ -302,16 +302,10 @@ module.exports = {
|
|||||||
uiName: 'Mention Highlight Link'
|
uiName: 'Mention Highlight Link'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
CODE_THEMES: {
|
|
||||||
github: 'GitHub',
|
|
||||||
solarized_light: 'Solarized light',
|
|
||||||
monokai: 'Monokai',
|
|
||||||
solarized_dark: 'Solarized Dark'
|
|
||||||
},
|
|
||||||
DEFAULT_CODE_THEME: 'github',
|
|
||||||
Preferences: {
|
Preferences: {
|
||||||
CATEGORY_DIRECT_CHANNEL_SHOW: 'direct_channel_show',
|
CATEGORY_DIRECT_CHANNEL_SHOW: 'direct_channel_show',
|
||||||
CATEGORY_DISPLAY_SETTINGS: 'display_settings'
|
CATEGORY_DISPLAY_SETTINGS: 'display_settings',
|
||||||
|
CATEGORY_ADVANCED_SETTINGS: 'advanced_settings'
|
||||||
},
|
},
|
||||||
KeyCodes: {
|
KeyCodes: {
|
||||||
UP: 38,
|
UP: 38,
|
||||||
@@ -322,30 +316,5 @@ module.exports = {
|
|||||||
ENTER: 13,
|
ENTER: 13,
|
||||||
ESCAPE: 27,
|
ESCAPE: 27,
|
||||||
SPACE: 32
|
SPACE: 32
|
||||||
},
|
|
||||||
HighlightedLanguages: {
|
|
||||||
diff: 'Diff',
|
|
||||||
apache: 'Apache',
|
|
||||||
makefile: 'Makefile',
|
|
||||||
http: 'HTTP',
|
|
||||||
json: 'JSON',
|
|
||||||
markdown: 'Markdown',
|
|
||||||
javascript: 'JavaScript',
|
|
||||||
css: 'CSS',
|
|
||||||
nginx: 'nginx',
|
|
||||||
objectivec: 'Objective-C',
|
|
||||||
python: 'Python',
|
|
||||||
xml: 'XML',
|
|
||||||
perl: 'Perl',
|
|
||||||
bash: 'Bash',
|
|
||||||
php: 'PHP',
|
|
||||||
coffeescript: 'CoffeeScript',
|
|
||||||
cs: 'C#',
|
|
||||||
cpp: 'C++',
|
|
||||||
sql: 'SQL',
|
|
||||||
go: 'Go',
|
|
||||||
ruby: 'Ruby',
|
|
||||||
java: 'Java',
|
|
||||||
ini: 'ini'
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,34 +6,6 @@ const Utils = require('./utils.jsx');
|
|||||||
|
|
||||||
const marked = require('marked');
|
const marked = require('marked');
|
||||||
|
|
||||||
const highlightJs = require('highlight.js/lib/highlight.js');
|
|
||||||
const highlightJsDiff = require('highlight.js/lib/languages/diff.js');
|
|
||||||
const highlightJsApache = require('highlight.js/lib/languages/apache.js');
|
|
||||||
const highlightJsMakefile = require('highlight.js/lib/languages/makefile.js');
|
|
||||||
const highlightJsHttp = require('highlight.js/lib/languages/http.js');
|
|
||||||
const highlightJsJson = require('highlight.js/lib/languages/json.js');
|
|
||||||
const highlightJsMarkdown = require('highlight.js/lib/languages/markdown.js');
|
|
||||||
const highlightJsJavascript = require('highlight.js/lib/languages/javascript.js');
|
|
||||||
const highlightJsCss = require('highlight.js/lib/languages/css.js');
|
|
||||||
const highlightJsNginx = require('highlight.js/lib/languages/nginx.js');
|
|
||||||
const highlightJsObjectivec = require('highlight.js/lib/languages/objectivec.js');
|
|
||||||
const highlightJsPython = require('highlight.js/lib/languages/python.js');
|
|
||||||
const highlightJsXml = require('highlight.js/lib/languages/xml.js');
|
|
||||||
const highlightJsPerl = require('highlight.js/lib/languages/perl.js');
|
|
||||||
const highlightJsBash = require('highlight.js/lib/languages/bash.js');
|
|
||||||
const highlightJsPhp = require('highlight.js/lib/languages/php.js');
|
|
||||||
const highlightJsCoffeescript = require('highlight.js/lib/languages/coffeescript.js');
|
|
||||||
const highlightJsCs = require('highlight.js/lib/languages/cs.js');
|
|
||||||
const highlightJsCpp = require('highlight.js/lib/languages/cpp.js');
|
|
||||||
const highlightJsSql = require('highlight.js/lib/languages/sql.js');
|
|
||||||
const highlightJsGo = require('highlight.js/lib/languages/go.js');
|
|
||||||
const highlightJsRuby = require('highlight.js/lib/languages/ruby.js');
|
|
||||||
const highlightJsJava = require('highlight.js/lib/languages/java.js');
|
|
||||||
const highlightJsIni = require('highlight.js/lib/languages/ini.js');
|
|
||||||
|
|
||||||
const Constants = require('../utils/constants.jsx');
|
|
||||||
const HighlightedLanguages = Constants.HighlightedLanguages;
|
|
||||||
|
|
||||||
export class MattermostMarkdownRenderer extends marked.Renderer {
|
export class MattermostMarkdownRenderer extends marked.Renderer {
|
||||||
constructor(options, formattingOptions = {}) {
|
constructor(options, formattingOptions = {}) {
|
||||||
super(options);
|
super(options);
|
||||||
@@ -43,43 +15,6 @@ export class MattermostMarkdownRenderer extends marked.Renderer {
|
|||||||
this.text = this.text.bind(this);
|
this.text = this.text.bind(this);
|
||||||
|
|
||||||
this.formattingOptions = formattingOptions;
|
this.formattingOptions = formattingOptions;
|
||||||
|
|
||||||
highlightJs.registerLanguage('diff', highlightJsDiff);
|
|
||||||
highlightJs.registerLanguage('apache', highlightJsApache);
|
|
||||||
highlightJs.registerLanguage('makefile', highlightJsMakefile);
|
|
||||||
highlightJs.registerLanguage('http', highlightJsHttp);
|
|
||||||
highlightJs.registerLanguage('json', highlightJsJson);
|
|
||||||
highlightJs.registerLanguage('markdown', highlightJsMarkdown);
|
|
||||||
highlightJs.registerLanguage('javascript', highlightJsJavascript);
|
|
||||||
highlightJs.registerLanguage('css', highlightJsCss);
|
|
||||||
highlightJs.registerLanguage('nginx', highlightJsNginx);
|
|
||||||
highlightJs.registerLanguage('objectivec', highlightJsObjectivec);
|
|
||||||
highlightJs.registerLanguage('python', highlightJsPython);
|
|
||||||
highlightJs.registerLanguage('xml', highlightJsXml);
|
|
||||||
highlightJs.registerLanguage('perl', highlightJsPerl);
|
|
||||||
highlightJs.registerLanguage('bash', highlightJsBash);
|
|
||||||
highlightJs.registerLanguage('php', highlightJsPhp);
|
|
||||||
highlightJs.registerLanguage('coffeescript', highlightJsCoffeescript);
|
|
||||||
highlightJs.registerLanguage('cs', highlightJsCs);
|
|
||||||
highlightJs.registerLanguage('cpp', highlightJsCpp);
|
|
||||||
highlightJs.registerLanguage('sql', highlightJsSql);
|
|
||||||
highlightJs.registerLanguage('go', highlightJsGo);
|
|
||||||
highlightJs.registerLanguage('ruby', highlightJsRuby);
|
|
||||||
highlightJs.registerLanguage('java', highlightJsJava);
|
|
||||||
highlightJs.registerLanguage('ini', highlightJsIni);
|
|
||||||
}
|
|
||||||
|
|
||||||
code(code, language) {
|
|
||||||
if (!language || highlightJs.listLanguages().indexOf(language) < 0) {
|
|
||||||
let parsed = super.code(code, language);
|
|
||||||
return '<code class="hljs">' + $(parsed).text() + '</code>';
|
|
||||||
}
|
|
||||||
|
|
||||||
let parsed = highlightJs.highlight(language, code);
|
|
||||||
return '<div class="post-body--code">' +
|
|
||||||
'<span class="post-body--code__language">' + HighlightedLanguages[language] + '</span>' +
|
|
||||||
'<code style="white-space: pre;" class="hljs">' + parsed.value + '</code>' +
|
|
||||||
'</div>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
br() {
|
br() {
|
||||||
|
|||||||
@@ -408,11 +408,6 @@ export function toTitleCase(str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function applyTheme(theme) {
|
export function applyTheme(theme) {
|
||||||
if (!theme.codeTheme) {
|
|
||||||
theme.codeTheme = Constants.DEFAULT_CODE_THEME;
|
|
||||||
}
|
|
||||||
updateCodeTheme(theme.codeTheme);
|
|
||||||
|
|
||||||
if (theme.sidebarBg) {
|
if (theme.sidebarBg) {
|
||||||
changeCss('.sidebar--left, .settings-modal .settings-table .settings-links, .sidebar--menu', 'background:' + theme.sidebarBg, 1);
|
changeCss('.sidebar--left, .settings-modal .settings-table .settings-links, .sidebar--menu', 'background:' + theme.sidebarBg, 1);
|
||||||
}
|
}
|
||||||
@@ -599,27 +594,6 @@ export function rgb2hex(rgbIn) {
|
|||||||
return '#' + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
|
return '#' + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateCodeTheme(theme) {
|
|
||||||
const path = '/static/css/highlight/' + theme + '.css';
|
|
||||||
const $link = $('link.code_theme');
|
|
||||||
if (path !== $link.attr('href')) {
|
|
||||||
changeCss('code.hljs', 'visibility: hidden');
|
|
||||||
var xmlHTTP = new XMLHttpRequest();
|
|
||||||
xmlHTTP.open('GET', path, true);
|
|
||||||
xmlHTTP.onload = function onLoad() {
|
|
||||||
$link.attr('href', path);
|
|
||||||
if (isBrowserFirefox()) {
|
|
||||||
$link.one('load', () => {
|
|
||||||
changeCss('code.hljs', 'visibility: visible');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
changeCss('code.hljs', 'visibility: visible');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xmlHTTP.send();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function placeCaretAtEnd(el) {
|
export function placeCaretAtEnd(el) {
|
||||||
el.focus();
|
el.focus();
|
||||||
if (typeof window.getSelection != 'undefined' && typeof document.createRange != 'undefined') {
|
if (typeof window.getSelection != 'undefined' && typeof document.createRange != 'undefined') {
|
||||||
|
|||||||
@@ -466,22 +466,6 @@ body.ios {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.post-body--code {
|
|
||||||
font-size: .97em;
|
|
||||||
position:relative;
|
|
||||||
.post-body--code__language {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
background: #fff;
|
|
||||||
cursor: default;
|
|
||||||
padding: 0.3em 0.5em 0.1em;
|
|
||||||
border-bottom-left-radius: 4px;
|
|
||||||
@include opacity(.3);
|
|
||||||
}
|
|
||||||
code {
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.create-reply-form-wrap {
|
.create-reply-form-wrap {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../../react/node_modules/highlight.js/styles/
|
|
||||||
Двоичные данные
web/static/images/themes/code_themes/github.png
Двоичные данные
web/static/images/themes/code_themes/github.png
Двоичный файл не отображается.
|
До Ширина: | Высота: | Размер: 9.4 KiB |
Двоичные данные
web/static/images/themes/code_themes/monokai.png
Двоичные данные
web/static/images/themes/code_themes/monokai.png
Двоичный файл не отображается.
|
До Ширина: | Высота: | Размер: 9.1 KiB |
Двоичные данные
web/static/images/themes/code_themes/solarized_dark.png
Двоичные данные
web/static/images/themes/code_themes/solarized_dark.png
Двоичный файл не отображается.
|
До Ширина: | Высота: | Размер: 8.0 KiB |
Двоичные данные
web/static/images/themes/code_themes/solarized_light.png
Двоичные данные
web/static/images/themes/code_themes/solarized_light.png
Двоичный файл не отображается.
|
До Ширина: | Высота: | Размер: 8.7 KiB |
@@ -24,7 +24,6 @@
|
|||||||
<link rel="stylesheet" href="/static/css/bootstrap-colorpicker.min.css">
|
<link rel="stylesheet" href="/static/css/bootstrap-colorpicker.min.css">
|
||||||
<link rel="stylesheet" href="/static/css/styles.css">
|
<link rel="stylesheet" href="/static/css/styles.css">
|
||||||
<link rel="stylesheet" href="/static/css/google-fonts.css">
|
<link rel="stylesheet" href="/static/css/google-fonts.css">
|
||||||
<link rel="stylesheet" class="code_theme" href="">
|
|
||||||
|
|
||||||
<link id="favicon" rel="icon" href="/static/images/favicon.ico" type="image/x-icon">
|
<link id="favicon" rel="icon" href="/static/images/favicon.ico" type="image/x-icon">
|
||||||
<link rel="shortcut icon" href="/static/images/favicon.ico" type="image/x-icon">
|
<link rel="shortcut icon" href="/static/images/favicon.ico" type="image/x-icon">
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user