summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/react/components/delete_post_modal.jsx1
-rw-r--r--web/react/components/navbar.jsx2
-rw-r--r--web/react/components/textbox.jsx23
-rw-r--r--web/react/components/user_settings/user_settings_advanced.jsx144
-rw-r--r--web/react/stores/post_store.jsx14
-rw-r--r--web/react/utils/constants.jsx7
-rw-r--r--web/react/utils/utils.jsx4
-rw-r--r--web/sass-files/sass/partials/_base.scss2
-rw-r--r--web/sass-files/sass/partials/_post.scss5
9 files changed, 170 insertions, 32 deletions
diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx
index 3c4b17905..5e89a0893 100644
--- a/web/react/components/delete_post_modal.jsx
+++ b/web/react/components/delete_post_modal.jsx
@@ -152,6 +152,7 @@ export default class DeletePostModal extends React.Component {
type='button'
className='btn btn-danger'
onClick={this.handleDelete}
+ autoFocus='autofocus'
>
{'Delete'}
</button>
diff --git a/web/react/components/navbar.jsx b/web/react/components/navbar.jsx
index 03cc75a08..6c3bfc7db 100644
--- a/web/react/components/navbar.jsx
+++ b/web/react/components/navbar.jsx
@@ -174,7 +174,7 @@ export default class Navbar extends React.Component {
<a
role='menuitem'
href='#'
- onClick={() => this.setState({showInviteModal: false})}
+ onClick={() => this.setState({showInviteModal: true})}
>
{'Add Members'}
</a>
diff --git a/web/react/components/textbox.jsx b/web/react/components/textbox.jsx
index e2868e946..10b3c0069 100644
--- a/web/react/components/textbox.jsx
+++ b/web/react/components/textbox.jsx
@@ -11,6 +11,7 @@ import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
const KeyCodes = Constants.KeyCodes;
+const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
export default class Textbox extends React.Component {
constructor(props) {
@@ -303,7 +304,19 @@ export default class Textbox extends React.Component {
}
render() {
- const previewLinkVisible = this.props.messageText.length > 0;
+ let previewLink = null;
+ if (Utils.isFeatureEnabled(PreReleaseFeatures.MARKDOWN_PREVIEW)) {
+ const previewLinkVisible = this.props.messageText.length > 0;
+ previewLink = (
+ <a
+ style={{visibility: previewLinkVisible ? 'visible' : 'hidden'}}
+ onClick={this.showPreview}
+ className='textbox-preview-link'
+ >
+ {this.state.preview ? 'Edit message' : 'Preview'}
+ </a>
+ );
+ }
return (
<div
@@ -342,19 +355,13 @@ export default class Textbox extends React.Component {
dangerouslySetInnerHTML={{__html: this.state.preview ? TextFormatting.formatText(this.props.messageText) : ''}}
>
</div>
+ {previewLink}
<a
onClick={this.showHelp}
className='textbox-help-link'
>
{'Help'}
</a>
- <a
- style={{visibility: previewLinkVisible ? 'visible' : 'hidden'}}
- onClick={this.showPreview}
- className='textbox-preview-link'
- >
- {this.state.preview ? 'Edit' : 'Preview'}
- </a>
</div>
);
}
diff --git a/web/react/components/user_settings/user_settings_advanced.jsx b/web/react/components/user_settings/user_settings_advanced.jsx
index ac82595f5..b4d34c658 100644
--- a/web/react/components/user_settings/user_settings_advanced.jsx
+++ b/web/react/components/user_settings/user_settings_advanced.jsx
@@ -6,6 +6,7 @@ import SettingItemMin from '../setting_item_min.jsx';
import SettingItemMax from '../setting_item_max.jsx';
import Constants from '../../utils/constants.jsx';
import PreferenceStore from '../../stores/preference_store.jsx';
+const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
export default class AdvancedSettingsDisplay extends React.Component {
constructor(props) {
@@ -13,21 +14,33 @@ export default class AdvancedSettingsDisplay extends React.Component {
this.updateSection = this.updateSection.bind(this);
this.updateSetting = this.updateSetting.bind(this);
- this.setupInitialState = this.setupInitialState.bind(this);
+ this.toggleFeature = this.toggleFeature.bind(this);
+ this.saveEnabledFeatures = this.saveEnabledFeatures.bind(this);
- this.state = this.setupInitialState();
- }
+ const preReleaseFeaturesKeys = Object.keys(PreReleaseFeatures);
+ const advancedSettings = PreferenceStore.getPreferences(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS);
+ const settings = {
+ send_on_ctrl_enter: PreferenceStore.getPreference(
+ Constants.Preferences.CATEGORY_ADVANCED_SETTINGS,
+ 'send_on_ctrl_enter',
+ {value: 'false'}
+ ).value
+ };
- setupInitialState() {
- const sendOnCtrlEnter = PreferenceStore.getPreference(
- Constants.Preferences.CATEGORY_ADVANCED_SETTINGS,
- 'send_on_ctrl_enter',
- {value: 'false'}
- ).value;
+ let enabledFeatures = 0;
+ advancedSettings.forEach((setting) => {
+ preReleaseFeaturesKeys.forEach((key) => {
+ const feature = PreReleaseFeatures[key];
+ if (setting.name === Constants.FeatureTogglePrefix + feature.label) {
+ settings[setting.name] = setting.value;
+ if (setting.value === 'true') {
+ enabledFeatures++;
+ }
+ }
+ });
+ });
- return {
- settings: {send_on_ctrl_enter: sendOnCtrlEnter}
- };
+ this.state = {preReleaseFeatures: PreReleaseFeatures, settings, preReleaseFeaturesKeys, enabledFeatures};
}
updateSetting(setting, value) {
@@ -36,14 +49,45 @@ export default class AdvancedSettingsDisplay extends React.Component {
this.setState(settings);
}
- handleSubmit(setting) {
- const preference = PreferenceStore.setPreference(
- Constants.Preferences.CATEGORY_ADVANCED_SETTINGS,
- setting,
- this.state.settings[setting]
- );
+ toggleFeature(feature, checked) {
+ const settings = this.state.settings;
+ settings[Constants.FeatureTogglePrefix + feature] = String(checked);
+
+ let enabledFeatures = 0;
+ Object.keys(this.state.settings).forEach((setting) => {
+ if (setting.lastIndexOf(Constants.FeatureTogglePrefix) === 0 && this.state.settings[setting] === 'true') {
+ enabledFeatures++;
+ }
+ });
+
+ this.setState({settings, enabledFeatures});
+ }
+
+ saveEnabledFeatures() {
+ const features = [];
+ Object.keys(this.state.settings).forEach((setting) => {
+ if (setting.lastIndexOf(Constants.FeatureTogglePrefix) === 0) {
+ features.push(setting);
+ }
+ });
+
+ this.handleSubmit(features);
+ }
- Client.savePreferences([preference],
+ handleSubmit(settings) {
+ const preferences = [];
+
+ (Array.isArray(settings) ? settings : [settings]).forEach((setting) => {
+ preferences.push(
+ PreferenceStore.setPreference(
+ Constants.Preferences.CATEGORY_ADVANCED_SETTINGS,
+ setting,
+ String(this.state.settings[setting])
+ )
+ );
+ });
+
+ Client.savePreferences(preferences,
() => {
PreferenceStore.emitChange();
this.updateSection('');
@@ -118,6 +162,66 @@ export default class AdvancedSettingsDisplay extends React.Component {
);
}
+ let previewFeaturesSection;
+ let previewFeaturesSectionDivider;
+ if (this.state.preReleaseFeaturesKeys.length > 0) {
+ previewFeaturesSectionDivider = (
+ <div className='divider-light'/>
+ );
+
+ if (this.props.activeSection === 'advancedPreviewFeatures') {
+ const inputs = [];
+
+ this.state.preReleaseFeaturesKeys.forEach((key) => {
+ const feature = this.state.preReleaseFeatures[key];
+ inputs.push(
+ <div key={'advancedPreviewFeatures_' + feature.label}>
+ <div className='checkbox'>
+ <label>
+ <input
+ type='checkbox'
+ checked={this.state.settings[Constants.FeatureTogglePrefix + feature.label] === 'true'}
+ onChange={(e) => {
+ this.toggleFeature(feature.label, e.target.checked);
+ }}
+ />
+ {feature.description}
+ </label>
+ </div>
+ </div>
+ );
+ });
+
+ inputs.push(
+ <div key='advancedPreviewFeatures_helptext'>
+ <br/>
+ {'Check any pre-released features you\'d like to preview.'}
+ </div>
+ );
+
+ previewFeaturesSection = (
+ <SettingItemMax
+ title='Preview pre-release features'
+ inputs={inputs}
+ submit={this.saveEnabledFeatures}
+ server_error={serverError}
+ updateSection={(e) => {
+ this.updateSection('');
+ e.preventDefault();
+ }}
+ />
+ );
+ } else {
+ previewFeaturesSection = (
+ <SettingItemMin
+ title='Preview pre-release features'
+ describe={this.state.enabledFeatures + (this.state.enabledFeatures === 1 ? ' Feature ' : ' Features ') + 'enabled'}
+ updateSection={() => this.props.updateSection('advancedPreviewFeatures')}
+ />
+ );
+ }
+ }
+
return (
<div>
<div className='modal-header'>
@@ -145,6 +249,8 @@ export default class AdvancedSettingsDisplay extends React.Component {
<h3 className='tab-header'>{'Advanced Settings'}</h3>
<div className='divider-dark first'/>
{ctrlSendSection}
+ {previewFeaturesSectionDivider}
+ {previewFeaturesSection}
<div className='divider-dark'/>
</div>
</div>
diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx
index 24b0d0dd0..a8f0f9c63 100644
--- a/web/react/stores/post_store.jsx
+++ b/web/react/stores/post_store.jsx
@@ -39,6 +39,7 @@ class PostStoreClass extends EventEmitter {
this.makePostsInfo = this.makePostsInfo.bind(this);
+ this.getPost = this.getPost.bind(this);
this.getAllPosts = this.getAllPosts.bind(this);
this.getEarliestPost = this.getEarliestPost.bind(this);
this.getLatestPost = this.getLatestPost.bind(this);
@@ -160,6 +161,17 @@ class PostStoreClass extends EventEmitter {
}
}
+ getPost(channelId, postId) {
+ const posts = this.postsInfo[channelId].postList;
+ let post = null;
+
+ if (posts.posts.hasOwnProperty(postId)) {
+ post = Object.assign({}, posts.posts[postId]);
+ }
+
+ return post;
+ }
+
getAllPosts(id) {
if (this.postsInfo.hasOwnProperty(id)) {
return Object.assign({}, this.postsInfo[id].postList);
@@ -554,7 +566,7 @@ class PostStoreClass extends EventEmitter {
return 0;
}
getCommentCount(post) {
- const posts = this.getPosts(post.channel_id).posts;
+ const posts = this.getAllPosts(post.channel_id).posts;
let commentCount = 0;
for (const id in posts) {
diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx
index 372e15556..2009e07dd 100644
--- a/web/react/utils/constants.jsx
+++ b/web/react/utils/constants.jsx
@@ -398,5 +398,12 @@ export default {
},
NotificationPrefs: {
MENTION: 'mention'
+ },
+ FeatureTogglePrefix: 'feature_enabled_',
+ PRE_RELEASE_FEATURES: {
+ MARKDOWN_PREVIEW: {
+ label: 'markdown_preview', // github issue: https://github.com/mattermost/platform/pull/1389
+ description: 'Show markdown preview option in message input box'
+ }
}
};
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index 9b2f7e057..80c377d7f 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -1221,3 +1221,7 @@ export function getPostTerm(post) {
return postTerm;
}
+
+export function isFeatureEnabled(feature) {
+ return PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, Constants.FeatureTogglePrefix + feature.label, {value: 'false'}).value === 'true';
+}
diff --git a/web/sass-files/sass/partials/_base.scss b/web/sass-files/sass/partials/_base.scss
index 2fc63443e..7efe70cb4 100644
--- a/web/sass-files/sass/partials/_base.scss
+++ b/web/sass-files/sass/partials/_base.scss
@@ -116,7 +116,7 @@ a:focus, a:hover {
.btn {
&.btn-danger {
color: #fff;
- &:hover, &:active {
+ &:hover, &:active, &:focus {
color: #fff;
}
}
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index b7609bb7d..da161e54f 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -53,6 +53,7 @@ body.ios {
top: 0;
left: 0;
box-shadow: none;
+ white-space: normal;
}
.textbox-preview-link, .textbox-help-link {
position: absolute;
@@ -283,14 +284,14 @@ body.ios {
.custom-textarea {
padding-top: 8px;
padding-right: 28px;
- max-height: 160px;
+ max-height: 162px !important;
overflow: auto;
line-height: 1.5;
}
.textarea-div {
padding-top: 8px;
padding-right: 30px;
- max-height: 160px;
+ max-height: 163px !important;
overflow: auto;
line-height: 1.5;
}