Merge remote-tracking branch 'upstream/master' into PLT-637
Conflicts: web/react/utils/constants.jsx
Этот коммит содержится в:
@@ -19,6 +19,7 @@
|
||||
},
|
||||
"globals": {
|
||||
"React": false,
|
||||
"ReactDOM": false,
|
||||
"ReactBootstrap": false
|
||||
},
|
||||
"rules": {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// See License.txt for license information.
|
||||
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
var AsyncClient = require('../utils/async_client.jsx');
|
||||
var LoadingScreen = require('./loading_screen.jsx');
|
||||
var Utils = require('../utils/utils.jsx');
|
||||
@@ -14,8 +15,10 @@ export default class AccessHistoryModal extends React.Component {
|
||||
this.handleMoreInfo = this.handleMoreInfo.bind(this);
|
||||
this.onHide = this.onHide.bind(this);
|
||||
this.onShow = this.onShow.bind(this);
|
||||
this.formatAuditInfo = this.formatAuditInfo.bind(this);
|
||||
this.handleRevokedSession = this.handleRevokedSession.bind(this);
|
||||
|
||||
let state = this.getStateFromStoresForAudits();
|
||||
const state = this.getStateFromStoresForAudits();
|
||||
state.moreInfo = [];
|
||||
|
||||
this.state = state;
|
||||
@@ -34,9 +37,9 @@ export default class AccessHistoryModal extends React.Component {
|
||||
}
|
||||
componentDidMount() {
|
||||
UserStore.addAuditsChangeListener(this.onAuditChange);
|
||||
$(React.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.onShow);
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
UserStore.removeAuditsChangeListener(this.onAuditChange);
|
||||
@@ -52,23 +55,269 @@ export default class AccessHistoryModal extends React.Component {
|
||||
newMoreInfo[index] = true;
|
||||
this.setState({moreInfo: newMoreInfo});
|
||||
}
|
||||
handleRevokedSession(sessionId) {
|
||||
return 'The session with id ' + sessionId + ' was revoked';
|
||||
}
|
||||
formatAuditInfo(currentAudit) {
|
||||
const currentActionURL = currentAudit.action.replace(/\/api\/v[1-9]/, '');
|
||||
|
||||
let currentAuditDesc = '';
|
||||
|
||||
if (currentActionURL.indexOf('/channels') === 0) {
|
||||
const channelInfo = currentAudit.extra_info.split(' ');
|
||||
const channelNameField = channelInfo[0].split('=');
|
||||
|
||||
let channelURL = '';
|
||||
let channelObj;
|
||||
let channelName = '';
|
||||
if (channelNameField.indexOf('name') >= 0) {
|
||||
channelURL = channelNameField[channelNameField.indexOf('name') + 1];
|
||||
channelObj = ChannelStore.getByName(channelURL);
|
||||
if (channelObj) {
|
||||
channelName = channelObj.display_name;
|
||||
} else {
|
||||
channelName = channelURL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (currentActionURL) {
|
||||
case '/channels/create':
|
||||
currentAuditDesc = 'Created the ' + channelName + ' channel/group';
|
||||
break;
|
||||
case '/channels/create_direct':
|
||||
currentAuditDesc = 'Established a direct message channel with ' + Utils.getDirectTeammate(channelObj.id).username;
|
||||
break;
|
||||
case '/channels/update':
|
||||
currentAuditDesc = 'Updated the ' + channelName + ' channel/group name';
|
||||
break;
|
||||
case '/channels/update_desc':
|
||||
currentAuditDesc = 'Updated the ' + channelName + ' channel/group description';
|
||||
break;
|
||||
default:
|
||||
let userIdField = [];
|
||||
let userId = '';
|
||||
let username = '';
|
||||
|
||||
if (channelInfo[1]) {
|
||||
userIdField = channelInfo[1].split('=');
|
||||
|
||||
if (userIdField.indexOf('user_id') >= 0) {
|
||||
userId = userIdField[userIdField.indexOf('user_id') + 1];
|
||||
username = UserStore.getProfile(userId).username;
|
||||
}
|
||||
}
|
||||
|
||||
if (/\/channels\/[A-Za-z0-9]+\/delete/.test(currentActionURL)) {
|
||||
currentAuditDesc = 'Deleted the channel/group with the URL ' + channelURL;
|
||||
} else if (/\/channels\/[A-Za-z0-9]+\/add/.test(currentActionURL)) {
|
||||
currentAuditDesc = 'Added ' + username + ' to the ' + channelName + ' channel/group';
|
||||
} else if (/\/channels\/[A-Za-z0-9]+\/remove/.test(currentActionURL)) {
|
||||
currentAuditDesc = 'Removed ' + username + ' from the ' + channelName + ' channel/group';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} else if (currentActionURL.indexOf('/oauth') === 0) {
|
||||
const oauthInfo = currentAudit.extra_info.split(' ');
|
||||
|
||||
switch (currentActionURL) {
|
||||
case '/oauth/register':
|
||||
const clientIdField = oauthInfo[0].split('=');
|
||||
|
||||
if (clientIdField[0] === 'client_id') {
|
||||
currentAuditDesc = 'Attempted to register a new OAuth Application with ID ' + clientIdField[1];
|
||||
}
|
||||
|
||||
break;
|
||||
case '/oauth/allow':
|
||||
if (oauthInfo[0] === 'attempt') {
|
||||
currentAuditDesc = 'Attempted to allow a new OAuth service access';
|
||||
} else if (oauthInfo[0] === 'success') {
|
||||
currentAuditDesc = 'Successfully gave a new OAuth service access';
|
||||
} else if (oauthInfo[0] === 'fail - redirect_uri did not match registered callback') {
|
||||
currentAuditDesc = 'Failed to allow a new OAuth service access - the redirect URI did not match the previously registered callback';
|
||||
}
|
||||
|
||||
break;
|
||||
case '/oauth/access_token':
|
||||
if (oauthInfo[0] === 'attempt') {
|
||||
currentAuditDesc = 'Attempted to get an OAuth access token';
|
||||
} else if (oauthInfo[0] === 'success') {
|
||||
currentAuditDesc = 'Successfully added a new OAuth service';
|
||||
} else {
|
||||
const oauthTokenFailure = oauthInfo[0].split('-');
|
||||
|
||||
if (oauthTokenFailure[0].trim() === 'fail' && oauthTokenFailure[1]) {
|
||||
currentAuditDesc = 'Failed to get an OAuth access token - ' + oauthTokenFailure[1].trim();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (currentActionURL.indexOf('/users') === 0) {
|
||||
const userInfo = currentAudit.extra_info.split(' ');
|
||||
|
||||
switch (currentActionURL) {
|
||||
case '/users/login':
|
||||
if (userInfo[0] === 'attempt') {
|
||||
currentAuditDesc = 'Attempted to login';
|
||||
} else if (userInfo[0] === 'success') {
|
||||
currentAuditDesc = 'Successfully logged in';
|
||||
} else if (userInfo[0]) {
|
||||
currentAuditDesc = 'FAILED login attempt';
|
||||
}
|
||||
|
||||
break;
|
||||
case '/users/revoke_session':
|
||||
currentAuditDesc = this.handleRevokedSession(userInfo[0].split('=')[1]);
|
||||
break;
|
||||
case '/users/newimage':
|
||||
currentAuditDesc = 'Updated your profile picture';
|
||||
break;
|
||||
case '/users/update':
|
||||
currentAuditDesc = 'Updated the general settings of your account';
|
||||
break;
|
||||
case '/users/newpassword':
|
||||
if (userInfo[0] === 'attempted') {
|
||||
currentAuditDesc = 'Attempted to change password';
|
||||
} else if (userInfo[0] === 'completed') {
|
||||
currentAuditDesc = 'Successfully changed password';
|
||||
} else if (userInfo[0] === 'failed - tried to update user password who was logged in through oauth') {
|
||||
currentAuditDesc = 'Failed to change password - tried to update user password who was logged in through oauth';
|
||||
}
|
||||
|
||||
break;
|
||||
case '/users/update_roles':
|
||||
const userRoles = userInfo[0].split('=')[1];
|
||||
|
||||
currentAuditDesc = 'Updated user role(s) to ';
|
||||
if (userRoles.trim()) {
|
||||
currentAuditDesc += userRoles;
|
||||
} else {
|
||||
currentAuditDesc += 'member';
|
||||
}
|
||||
|
||||
break;
|
||||
case '/users/update_active':
|
||||
const updateType = userInfo[0].split('=')[0];
|
||||
const updateField = userInfo[0].split('=')[1];
|
||||
|
||||
/* Either describes account activation/deactivation or a revoked session as part of an account deactivation */
|
||||
if (updateType === 'active') {
|
||||
if (updateField === 'true') {
|
||||
currentAuditDesc = 'Account made active';
|
||||
} else if (updateField === 'false') {
|
||||
currentAuditDesc = 'Account made inactive';
|
||||
}
|
||||
|
||||
const actingUserInfo = userInfo[1].split('=');
|
||||
if (actingUserInfo[0] === 'session_user') {
|
||||
const actingUser = UserStore.getProfile(actingUserInfo[1]);
|
||||
const currentUser = UserStore.getCurrentUser();
|
||||
if (currentUser && actingUser && (Utils.isAdmin(currentUser.roles) || Utils.isSystemAdmin(currentUser.roles))) {
|
||||
currentAuditDesc += ' by ' + actingUser.username;
|
||||
} else if (currentUser && actingUser) {
|
||||
currentAuditDesc += ' by an admin';
|
||||
}
|
||||
}
|
||||
} else if (updateType === 'session_id') {
|
||||
currentAuditDesc = this.handleRevokedSession(updateField);
|
||||
}
|
||||
|
||||
break;
|
||||
case '/users/send_password_reset':
|
||||
currentAuditDesc = 'Sent an email to ' + userInfo[0].split('=')[1] + ' to reset your password';
|
||||
break;
|
||||
case '/users/reset_password':
|
||||
if (userInfo[0] === 'attempt') {
|
||||
currentAuditDesc = 'Attempted to reset password';
|
||||
} else if (userInfo[0] === 'success') {
|
||||
currentAuditDesc = 'Successfully reset password';
|
||||
}
|
||||
|
||||
break;
|
||||
case '/users/update_notify':
|
||||
currentAuditDesc = 'Updated your global notification settings';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (currentActionURL.indexOf('/hooks') === 0) {
|
||||
const webhookInfo = currentAudit.extra_info.split(' ');
|
||||
|
||||
switch (currentActionURL) {
|
||||
case '/hooks/incoming/create':
|
||||
if (webhookInfo[0] === 'attempt') {
|
||||
currentAuditDesc = 'Attempted to create a webhook';
|
||||
} else if (webhookInfo[0] === 'success') {
|
||||
currentAuditDesc = 'Successfully created a webhook';
|
||||
} else if (webhookInfo[0] === 'fail - bad channel permissions') {
|
||||
currentAuditDesc = 'Failed to create a webhook - bad channel permissions';
|
||||
}
|
||||
|
||||
break;
|
||||
case '/hooks/incoming/delete':
|
||||
if (webhookInfo[0] === 'attempt') {
|
||||
currentAuditDesc = 'Attempted to delete a webhook';
|
||||
} else if (webhookInfo[0] === 'success') {
|
||||
currentAuditDesc = 'Successfully deleted a webhook';
|
||||
} else if (webhookInfo[0] === 'fail - inappropriate conditions') {
|
||||
currentAuditDesc = 'Failed to delete a webhook - inappropriate conditions';
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (currentActionURL) {
|
||||
case '/logout':
|
||||
currentAuditDesc = 'Logged out of your account';
|
||||
break;
|
||||
case '/verify_email':
|
||||
currentAuditDesc = 'Sucessfully verified your email address';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If all else fails... */
|
||||
if (!currentAuditDesc) {
|
||||
/* Currently not called anywhere */
|
||||
if (currentAudit.extra_info.indexOf('revoked_all=') >= 0) {
|
||||
currentAuditDesc = 'Revoked all current sessions for the team';
|
||||
} else {
|
||||
let currentActionDesc = '';
|
||||
if (currentActionURL && currentActionURL.lastIndexOf('/') !== -1) {
|
||||
currentActionDesc = currentActionURL.substring(currentActionURL.lastIndexOf('/') + 1).replace('_', ' ');
|
||||
currentActionDesc = Utils.toTitleCase(currentActionDesc);
|
||||
}
|
||||
|
||||
let currentExtraInfoDesc = '';
|
||||
if (currentAudit.extra_info) {
|
||||
currentExtraInfoDesc = currentAudit.extra_info;
|
||||
|
||||
if (currentExtraInfoDesc.indexOf('=') !== -1) {
|
||||
currentExtraInfoDesc = currentExtraInfoDesc.substring(currentExtraInfoDesc.indexOf('=') + 1);
|
||||
}
|
||||
}
|
||||
currentAuditDesc = currentActionDesc + ' ' + currentExtraInfoDesc;
|
||||
}
|
||||
}
|
||||
|
||||
const currentDate = new Date(currentAudit.create_at);
|
||||
const currentAuditInfo = currentDate.toDateString() + ' - ' + currentDate.toLocaleTimeString(navigator.language, {hour: '2-digit', minute: '2-digit'}) + ' | ' + currentAuditDesc;
|
||||
return currentAuditInfo;
|
||||
}
|
||||
render() {
|
||||
var accessList = [];
|
||||
var currentHistoryDate = null;
|
||||
|
||||
for (var i = 0; i < this.state.audits.length; i++) {
|
||||
var currentAudit = this.state.audits[i];
|
||||
var newHistoryDate = new Date(currentAudit.create_at);
|
||||
var newDate = null;
|
||||
|
||||
if (!currentHistoryDate || currentHistoryDate.toLocaleDateString() !== newHistoryDate.toLocaleDateString()) {
|
||||
currentHistoryDate = newHistoryDate;
|
||||
newDate = (<div> {currentHistoryDate.toDateString()} </div>);
|
||||
}
|
||||
|
||||
if (!currentAudit.session_id && currentAudit.action.search('/users/login') !== -1) {
|
||||
currentAudit.session_id = 'N/A (Login attempt)';
|
||||
}
|
||||
const currentAudit = this.state.audits[i];
|
||||
const currentAuditInfo = this.formatAuditInfo(currentAudit);
|
||||
|
||||
var moreInfo = (
|
||||
<a
|
||||
@@ -76,15 +325,27 @@ export default class AccessHistoryModal extends React.Component {
|
||||
className='theme'
|
||||
onClick={this.handleMoreInfo.bind(this, i)}
|
||||
>
|
||||
More info
|
||||
{'More info'}
|
||||
</a>
|
||||
);
|
||||
|
||||
if (this.state.moreInfo[i]) {
|
||||
if (!currentAudit.session_id) {
|
||||
currentAudit.session_id = 'N/A';
|
||||
|
||||
if (currentAudit.action.search('/users/login') >= 0) {
|
||||
if (currentAudit.extra_info === 'attempt') {
|
||||
currentAudit.session_id += ' (Login attempt)';
|
||||
} else {
|
||||
currentAudit.session_id += ' (Login failure)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moreInfo = (
|
||||
<div>
|
||||
<div>{'IP: ' + currentAudit.ip_address}</div>
|
||||
<div>{'Session ID: ' + currentAudit.session_id}</div>
|
||||
<div>{'URL: ' + currentAudit.action.replace(/\/api\/v[1-9]/, '')}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -99,11 +360,9 @@ export default class AccessHistoryModal extends React.Component {
|
||||
key={'accessHistoryEntryKey' + i}
|
||||
className='access-history__table'
|
||||
>
|
||||
<div className='access__date'>{newDate}</div>
|
||||
<div className='access__report'>
|
||||
<div className='report__time'>{newHistoryDate.toLocaleTimeString(navigator.language, {hour: '2-digit', minute: '2-digit'})}</div>
|
||||
<div className='report__time'>{currentAuditInfo}</div>
|
||||
<div className='report__info'>
|
||||
<div>{'IP: ' + currentAudit.ip_address}</div>
|
||||
{moreInfo}
|
||||
</div>
|
||||
{divider}
|
||||
@@ -138,13 +397,13 @@ export default class AccessHistoryModal extends React.Component {
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
<span aria-hidden='true'>{'×'}</span>
|
||||
</button>
|
||||
<h4
|
||||
className='modal-title'
|
||||
id='myModalLabel'
|
||||
>
|
||||
Access History
|
||||
{'Access History'}
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -56,9 +56,9 @@ export default class ActivityLogModal extends React.Component {
|
||||
}
|
||||
componentDidMount() {
|
||||
UserStore.addSessionsChangeListener(this.onListenerChange);
|
||||
$(React.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.onShow);
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
UserStore.removeSessionsChangeListener(this.onListenerChange);
|
||||
|
||||
@@ -27,7 +27,7 @@ export default class AdminNavbarDropdown extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', () => {
|
||||
$(ReactDOM.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', () => {
|
||||
this.blockToggle = true;
|
||||
setTimeout(() => {
|
||||
this.blockToggle = false;
|
||||
@@ -36,7 +36,7 @@ export default class AdminNavbarDropdown extends React.Component {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
$(React.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown');
|
||||
$(ReactDOM.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown');
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -100,6 +100,7 @@ export default class AdminSidebar extends React.Component {
|
||||
className='menu-icon--right menu__close'
|
||||
onClick={this.removeTeam.bind(this, team.id)}
|
||||
style={{cursor: 'pointer'}}
|
||||
title='Remove team from sidebar menu'
|
||||
>
|
||||
{'x'}
|
||||
</span>
|
||||
@@ -233,7 +234,10 @@ export default class AdminSidebar extends React.Component {
|
||||
href='#'
|
||||
onClick={this.showTeamSelect}
|
||||
>
|
||||
<i className='fa fa-plus'></i>
|
||||
<i
|
||||
className='fa fa-plus'
|
||||
title='Add team to sidebar menu'
|
||||
></i>
|
||||
</a>
|
||||
</span>
|
||||
</h4>
|
||||
|
||||
@@ -41,28 +41,28 @@ export default class EmailSettings extends React.Component {
|
||||
|
||||
buildConfig() {
|
||||
var config = this.props.config;
|
||||
config.EmailSettings.EnableSignUpWithEmail = React.findDOMNode(this.refs.allowSignUpWithEmail).checked;
|
||||
config.EmailSettings.SendEmailNotifications = React.findDOMNode(this.refs.sendEmailNotifications).checked;
|
||||
config.EmailSettings.RequireEmailVerification = React.findDOMNode(this.refs.requireEmailVerification).checked;
|
||||
config.EmailSettings.SendEmailNotifications = React.findDOMNode(this.refs.sendEmailNotifications).checked;
|
||||
config.EmailSettings.FeedbackName = React.findDOMNode(this.refs.feedbackName).value.trim();
|
||||
config.EmailSettings.FeedbackEmail = React.findDOMNode(this.refs.feedbackEmail).value.trim();
|
||||
config.EmailSettings.SMTPServer = React.findDOMNode(this.refs.SMTPServer).value.trim();
|
||||
config.EmailSettings.SMTPPort = React.findDOMNode(this.refs.SMTPPort).value.trim();
|
||||
config.EmailSettings.SMTPUsername = React.findDOMNode(this.refs.SMTPUsername).value.trim();
|
||||
config.EmailSettings.SMTPPassword = React.findDOMNode(this.refs.SMTPPassword).value.trim();
|
||||
config.EmailSettings.ConnectionSecurity = React.findDOMNode(this.refs.ConnectionSecurity).value.trim();
|
||||
config.EmailSettings.EnableSignUpWithEmail = ReactDOM.findDOMNode(this.refs.allowSignUpWithEmail).checked;
|
||||
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
|
||||
config.EmailSettings.RequireEmailVerification = ReactDOM.findDOMNode(this.refs.requireEmailVerification).checked;
|
||||
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
|
||||
config.EmailSettings.FeedbackName = ReactDOM.findDOMNode(this.refs.feedbackName).value.trim();
|
||||
config.EmailSettings.FeedbackEmail = ReactDOM.findDOMNode(this.refs.feedbackEmail).value.trim();
|
||||
config.EmailSettings.SMTPServer = ReactDOM.findDOMNode(this.refs.SMTPServer).value.trim();
|
||||
config.EmailSettings.SMTPPort = ReactDOM.findDOMNode(this.refs.SMTPPort).value.trim();
|
||||
config.EmailSettings.SMTPUsername = ReactDOM.findDOMNode(this.refs.SMTPUsername).value.trim();
|
||||
config.EmailSettings.SMTPPassword = ReactDOM.findDOMNode(this.refs.SMTPPassword).value.trim();
|
||||
config.EmailSettings.ConnectionSecurity = ReactDOM.findDOMNode(this.refs.ConnectionSecurity).value.trim();
|
||||
|
||||
config.EmailSettings.InviteSalt = React.findDOMNode(this.refs.InviteSalt).value.trim();
|
||||
config.EmailSettings.InviteSalt = ReactDOM.findDOMNode(this.refs.InviteSalt).value.trim();
|
||||
if (config.EmailSettings.InviteSalt === '') {
|
||||
config.EmailSettings.InviteSalt = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
React.findDOMNode(this.refs.InviteSalt).value = config.EmailSettings.InviteSalt;
|
||||
ReactDOM.findDOMNode(this.refs.InviteSalt).value = config.EmailSettings.InviteSalt;
|
||||
}
|
||||
|
||||
config.EmailSettings.PasswordResetSalt = React.findDOMNode(this.refs.PasswordResetSalt).value.trim();
|
||||
config.EmailSettings.PasswordResetSalt = ReactDOM.findDOMNode(this.refs.PasswordResetSalt).value.trim();
|
||||
if (config.EmailSettings.PasswordResetSalt === '') {
|
||||
config.EmailSettings.PasswordResetSalt = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
React.findDOMNode(this.refs.PasswordResetSalt).value = config.EmailSettings.PasswordResetSalt;
|
||||
ReactDOM.findDOMNode(this.refs.PasswordResetSalt).value = config.EmailSettings.PasswordResetSalt;
|
||||
}
|
||||
|
||||
return config;
|
||||
@@ -70,14 +70,14 @@ export default class EmailSettings extends React.Component {
|
||||
|
||||
handleGenerateInvite(e) {
|
||||
e.preventDefault();
|
||||
React.findDOMNode(this.refs.InviteSalt).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
ReactDOM.findDOMNode(this.refs.InviteSalt).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
var s = {saveNeeded: true, serverError: this.state.serverError};
|
||||
this.setState(s);
|
||||
}
|
||||
|
||||
handleGenerateReset(e) {
|
||||
e.preventDefault();
|
||||
React.findDOMNode(this.refs.PasswordResetSalt).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
ReactDOM.findDOMNode(this.refs.PasswordResetSalt).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
var s = {saveNeeded: true, serverError: this.state.serverError};
|
||||
this.setState(s);
|
||||
}
|
||||
@@ -447,7 +447,7 @@ export default class EmailSettings extends React.Component {
|
||||
</div>
|
||||
<div className='help-text'>
|
||||
<button
|
||||
className='btn'
|
||||
className='btn btn-default'
|
||||
onClick={this.handleTestConnection}
|
||||
disabled={!this.state.sendEmailNotifications}
|
||||
id='connection-button'
|
||||
@@ -482,7 +482,7 @@ export default class EmailSettings extends React.Component {
|
||||
<p className='help-text'>{'32-character salt added to signing of email invites. Randomly generated on install. Click "Re-Generate" to create new salt.'}</p>
|
||||
<div className='help-text'>
|
||||
<button
|
||||
className='btn'
|
||||
className='btn btn-default'
|
||||
onClick={this.handleGenerateInvite}
|
||||
disabled={!this.state.sendEmailNotifications}
|
||||
>
|
||||
@@ -513,7 +513,7 @@ export default class EmailSettings extends React.Component {
|
||||
<p className='help-text'>{'32-character salt added to signing of password reset emails. Randomly generated on install. Click "Re-Generate" to create new salt.'}</p>
|
||||
<div className='help-text'>
|
||||
<button
|
||||
className='btn'
|
||||
className='btn btn-default'
|
||||
onClick={this.handleGenerateReset}
|
||||
disabled={!this.state.sendEmailNotifications}
|
||||
>
|
||||
|
||||
@@ -37,12 +37,12 @@ export default class GitLabSettings extends React.Component {
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.GitLabSettings.Enable = React.findDOMNode(this.refs.Enable).checked;
|
||||
config.GitLabSettings.Secret = React.findDOMNode(this.refs.Secret).value.trim();
|
||||
config.GitLabSettings.Id = React.findDOMNode(this.refs.Id).value.trim();
|
||||
config.GitLabSettings.AuthEndpoint = React.findDOMNode(this.refs.AuthEndpoint).value.trim();
|
||||
config.GitLabSettings.TokenEndpoint = React.findDOMNode(this.refs.TokenEndpoint).value.trim();
|
||||
config.GitLabSettings.UserApiEndpoint = React.findDOMNode(this.refs.UserApiEndpoint).value.trim();
|
||||
config.GitLabSettings.Enable = ReactDOM.findDOMNode(this.refs.Enable).checked;
|
||||
config.GitLabSettings.Secret = ReactDOM.findDOMNode(this.refs.Secret).value.trim();
|
||||
config.GitLabSettings.Id = ReactDOM.findDOMNode(this.refs.Id).value.trim();
|
||||
config.GitLabSettings.AuthEndpoint = ReactDOM.findDOMNode(this.refs.AuthEndpoint).value.trim();
|
||||
config.GitLabSettings.TokenEndpoint = ReactDOM.findDOMNode(this.refs.TokenEndpoint).value.trim();
|
||||
config.GitLabSettings.UserApiEndpoint = ReactDOM.findDOMNode(this.refs.UserApiEndpoint).value.trim();
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
@@ -116,12 +116,14 @@ export default class GitLabSettings extends React.Component {
|
||||
<p className='help-text'>
|
||||
{'When true, Mattermost allows team creation and account signup using GitLab OAuth.'} <br/>
|
||||
</p>
|
||||
<ol className='help-text'>
|
||||
<li>{'Log in to your GitLab account and go to Applications -> Profile Settings.'}</li>
|
||||
<li>{'Enter Redirect URIs "<your-mattermost-url>/login/gitlab/complete" (example: http://localhost:8065/login/gitlab/complete) and "<your-mattermost-url>/signup/gitlab/complete". '}</li>
|
||||
<li>{'Then use "Secret" and "Id" fields from GitLab to complete the options below.'}</li>
|
||||
<li>{'Complete the Endpoint URLs below. '}</li>
|
||||
</ol>
|
||||
<div className='help-text'>
|
||||
<ol>
|
||||
<li>{'Log in to your GitLab account and go to Applications -> Profile Settings.'}</li>
|
||||
<li>{'Enter Redirect URIs "<your-mattermost-url>/login/gitlab/complete" (example: http://localhost:8065/login/gitlab/complete) and "<your-mattermost-url>/signup/gitlab/complete". '}</li>
|
||||
<li>{'Then use "Secret" and "Id" fields from GitLab to complete the options below.'}</li>
|
||||
<li>{'Complete the Endpoint URLs below. '}</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -258,7 +260,7 @@ export default class GitLabSettings extends React.Component {
|
||||
}
|
||||
|
||||
|
||||
//config.GitLabSettings.Scope = React.findDOMNode(this.refs.Scope).value.trim();
|
||||
//config.GitLabSettings.Scope = ReactDOM.findDOMNode(this.refs.Scope).value.trim();
|
||||
// <div className='form-group'>
|
||||
// <label
|
||||
// className='control-label col-sm-4'
|
||||
|
||||
@@ -24,7 +24,7 @@ export default class FileSettings extends React.Component {
|
||||
var s = {saveNeeded: true, serverError: this.state.serverError};
|
||||
|
||||
if (action === 'DriverName') {
|
||||
s.DriverName = React.findDOMNode(this.refs.DriverName).value;
|
||||
s.DriverName = ReactDOM.findDOMNode(this.refs.DriverName).value;
|
||||
}
|
||||
|
||||
this.setState(s);
|
||||
@@ -32,7 +32,7 @@ export default class FileSettings extends React.Component {
|
||||
|
||||
handleGenerate(e) {
|
||||
e.preventDefault();
|
||||
React.findDOMNode(this.refs.PublicLinkSalt).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
ReactDOM.findDOMNode(this.refs.PublicLinkSalt).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
var s = {saveNeeded: true, serverError: this.state.serverError};
|
||||
this.setState(s);
|
||||
}
|
||||
@@ -42,62 +42,62 @@ export default class FileSettings extends React.Component {
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.FileSettings.DriverName = React.findDOMNode(this.refs.DriverName).value;
|
||||
config.FileSettings.Directory = React.findDOMNode(this.refs.Directory).value;
|
||||
config.FileSettings.AmazonS3AccessKeyId = React.findDOMNode(this.refs.AmazonS3AccessKeyId).value;
|
||||
config.FileSettings.AmazonS3SecretAccessKey = React.findDOMNode(this.refs.AmazonS3SecretAccessKey).value;
|
||||
config.FileSettings.AmazonS3Bucket = React.findDOMNode(this.refs.AmazonS3Bucket).value;
|
||||
config.FileSettings.AmazonS3Region = React.findDOMNode(this.refs.AmazonS3Region).value;
|
||||
config.FileSettings.EnablePublicLink = React.findDOMNode(this.refs.EnablePublicLink).checked;
|
||||
config.FileSettings.DriverName = ReactDOM.findDOMNode(this.refs.DriverName).value;
|
||||
config.FileSettings.Directory = ReactDOM.findDOMNode(this.refs.Directory).value;
|
||||
config.FileSettings.AmazonS3AccessKeyId = ReactDOM.findDOMNode(this.refs.AmazonS3AccessKeyId).value;
|
||||
config.FileSettings.AmazonS3SecretAccessKey = ReactDOM.findDOMNode(this.refs.AmazonS3SecretAccessKey).value;
|
||||
config.FileSettings.AmazonS3Bucket = ReactDOM.findDOMNode(this.refs.AmazonS3Bucket).value;
|
||||
config.FileSettings.AmazonS3Region = ReactDOM.findDOMNode(this.refs.AmazonS3Region).value;
|
||||
config.FileSettings.EnablePublicLink = ReactDOM.findDOMNode(this.refs.EnablePublicLink).checked;
|
||||
|
||||
config.FileSettings.PublicLinkSalt = React.findDOMNode(this.refs.PublicLinkSalt).value.trim();
|
||||
config.FileSettings.PublicLinkSalt = ReactDOM.findDOMNode(this.refs.PublicLinkSalt).value.trim();
|
||||
|
||||
if (config.FileSettings.PublicLinkSalt === '') {
|
||||
config.FileSettings.PublicLinkSalt = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
React.findDOMNode(this.refs.PublicLinkSalt).value = config.FileSettings.PublicLinkSalt;
|
||||
ReactDOM.findDOMNode(this.refs.PublicLinkSalt).value = config.FileSettings.PublicLinkSalt;
|
||||
}
|
||||
|
||||
var thumbnailWidth = 120;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.ThumbnailWidth).value, 10))) {
|
||||
thumbnailWidth = parseInt(React.findDOMNode(this.refs.ThumbnailWidth).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.ThumbnailWidth).value, 10))) {
|
||||
thumbnailWidth = parseInt(ReactDOM.findDOMNode(this.refs.ThumbnailWidth).value, 10);
|
||||
}
|
||||
config.FileSettings.ThumbnailWidth = thumbnailWidth;
|
||||
React.findDOMNode(this.refs.ThumbnailWidth).value = thumbnailWidth;
|
||||
ReactDOM.findDOMNode(this.refs.ThumbnailWidth).value = thumbnailWidth;
|
||||
|
||||
var thumbnailHeight = 100;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.ThumbnailHeight).value, 10))) {
|
||||
thumbnailHeight = parseInt(React.findDOMNode(this.refs.ThumbnailHeight).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.ThumbnailHeight).value, 10))) {
|
||||
thumbnailHeight = parseInt(ReactDOM.findDOMNode(this.refs.ThumbnailHeight).value, 10);
|
||||
}
|
||||
config.FileSettings.ThumbnailHeight = thumbnailHeight;
|
||||
React.findDOMNode(this.refs.ThumbnailHeight).value = thumbnailHeight;
|
||||
ReactDOM.findDOMNode(this.refs.ThumbnailHeight).value = thumbnailHeight;
|
||||
|
||||
var previewWidth = 1024;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.PreviewWidth).value, 10))) {
|
||||
previewWidth = parseInt(React.findDOMNode(this.refs.PreviewWidth).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.PreviewWidth).value, 10))) {
|
||||
previewWidth = parseInt(ReactDOM.findDOMNode(this.refs.PreviewWidth).value, 10);
|
||||
}
|
||||
config.FileSettings.PreviewWidth = previewWidth;
|
||||
React.findDOMNode(this.refs.PreviewWidth).value = previewWidth;
|
||||
ReactDOM.findDOMNode(this.refs.PreviewWidth).value = previewWidth;
|
||||
|
||||
var previewHeight = 0;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.PreviewHeight).value, 10))) {
|
||||
previewHeight = parseInt(React.findDOMNode(this.refs.PreviewHeight).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.PreviewHeight).value, 10))) {
|
||||
previewHeight = parseInt(ReactDOM.findDOMNode(this.refs.PreviewHeight).value, 10);
|
||||
}
|
||||
config.FileSettings.PreviewHeight = previewHeight;
|
||||
React.findDOMNode(this.refs.PreviewHeight).value = previewHeight;
|
||||
ReactDOM.findDOMNode(this.refs.PreviewHeight).value = previewHeight;
|
||||
|
||||
var profileWidth = 128;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.ProfileWidth).value, 10))) {
|
||||
profileWidth = parseInt(React.findDOMNode(this.refs.ProfileWidth).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.ProfileWidth).value, 10))) {
|
||||
profileWidth = parseInt(ReactDOM.findDOMNode(this.refs.ProfileWidth).value, 10);
|
||||
}
|
||||
config.FileSettings.ProfileWidth = profileWidth;
|
||||
React.findDOMNode(this.refs.ProfileWidth).value = profileWidth;
|
||||
ReactDOM.findDOMNode(this.refs.ProfileWidth).value = profileWidth;
|
||||
|
||||
var profileHeight = 128;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.ProfileHeight).value, 10))) {
|
||||
profileHeight = parseInt(React.findDOMNode(this.refs.ProfileHeight).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.ProfileHeight).value, 10))) {
|
||||
profileHeight = parseInt(ReactDOM.findDOMNode(this.refs.ProfileHeight).value, 10);
|
||||
}
|
||||
config.FileSettings.ProfileHeight = profileHeight;
|
||||
React.findDOMNode(this.refs.ProfileHeight).value = profileHeight;
|
||||
ReactDOM.findDOMNode(this.refs.ProfileHeight).value = profileHeight;
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
|
||||
@@ -46,12 +46,12 @@ export default class LogSettings extends React.Component {
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.LogSettings.EnableConsole = React.findDOMNode(this.refs.consoleEnable).checked;
|
||||
config.LogSettings.ConsoleLevel = React.findDOMNode(this.refs.consoleLevel).value;
|
||||
config.LogSettings.EnableFile = React.findDOMNode(this.refs.fileEnable).checked;
|
||||
config.LogSettings.FileLevel = React.findDOMNode(this.refs.fileLevel).value;
|
||||
config.LogSettings.FileLocation = React.findDOMNode(this.refs.fileLocation).value.trim();
|
||||
config.LogSettings.FileFormat = React.findDOMNode(this.refs.fileFormat).value.trim();
|
||||
config.LogSettings.EnableConsole = ReactDOM.findDOMNode(this.refs.consoleEnable).checked;
|
||||
config.LogSettings.ConsoleLevel = ReactDOM.findDOMNode(this.refs.consoleLevel).value;
|
||||
config.LogSettings.EnableFile = ReactDOM.findDOMNode(this.refs.fileEnable).checked;
|
||||
config.LogSettings.FileLevel = ReactDOM.findDOMNode(this.refs.fileLevel).value;
|
||||
config.LogSettings.FileLocation = ReactDOM.findDOMNode(this.refs.fileLocation).value.trim();
|
||||
config.LogSettings.FileFormat = ReactDOM.findDOMNode(this.refs.fileFormat).value.trim();
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
|
||||
@@ -28,8 +28,8 @@ export default class PrivacySettings extends React.Component {
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.PrivacySettings.ShowEmailAddress = React.findDOMNode(this.refs.ShowEmailAddress).checked;
|
||||
config.PrivacySettings.ShowFullName = React.findDOMNode(this.refs.ShowFullName).checked;
|
||||
config.PrivacySettings.ShowEmailAddress = ReactDOM.findDOMNode(this.refs.ShowEmailAddress).checked;
|
||||
config.PrivacySettings.ShowFullName = ReactDOM.findDOMNode(this.refs.ShowFullName).checked;
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
|
||||
@@ -46,23 +46,23 @@ export default class RateSettings extends React.Component {
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.RateLimitSettings.EnableRateLimiter = React.findDOMNode(this.refs.EnableRateLimiter).checked;
|
||||
config.RateLimitSettings.VaryByRemoteAddr = React.findDOMNode(this.refs.VaryByRemoteAddr).checked;
|
||||
config.RateLimitSettings.VaryByHeader = React.findDOMNode(this.refs.VaryByHeader).value.trim();
|
||||
config.RateLimitSettings.EnableRateLimiter = ReactDOM.findDOMNode(this.refs.EnableRateLimiter).checked;
|
||||
config.RateLimitSettings.VaryByRemoteAddr = ReactDOM.findDOMNode(this.refs.VaryByRemoteAddr).checked;
|
||||
config.RateLimitSettings.VaryByHeader = ReactDOM.findDOMNode(this.refs.VaryByHeader).value.trim();
|
||||
|
||||
var PerSec = 10;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.PerSec).value, 10))) {
|
||||
PerSec = parseInt(React.findDOMNode(this.refs.PerSec).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.PerSec).value, 10))) {
|
||||
PerSec = parseInt(ReactDOM.findDOMNode(this.refs.PerSec).value, 10);
|
||||
}
|
||||
config.RateLimitSettings.PerSec = PerSec;
|
||||
React.findDOMNode(this.refs.PerSec).value = PerSec;
|
||||
ReactDOM.findDOMNode(this.refs.PerSec).value = PerSec;
|
||||
|
||||
var MemoryStoreSize = 10000;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.MemoryStoreSize).value, 10))) {
|
||||
MemoryStoreSize = parseInt(React.findDOMNode(this.refs.MemoryStoreSize).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.MemoryStoreSize).value, 10))) {
|
||||
MemoryStoreSize = parseInt(ReactDOM.findDOMNode(this.refs.MemoryStoreSize).value, 10);
|
||||
}
|
||||
config.RateLimitSettings.MemoryStoreSize = MemoryStoreSize;
|
||||
React.findDOMNode(this.refs.MemoryStoreSize).value = MemoryStoreSize;
|
||||
ReactDOM.findDOMNode(this.refs.MemoryStoreSize).value = MemoryStoreSize;
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
|
||||
@@ -18,7 +18,7 @@ export default class ResetPasswordModal extends React.Component {
|
||||
|
||||
doSubmit(e) {
|
||||
e.preventDefault();
|
||||
var password = React.findDOMNode(this.refs.password).value;
|
||||
var password = ReactDOM.findDOMNode(this.refs.password).value;
|
||||
|
||||
if (!password || password.length < 5) {
|
||||
this.setState({serverError: 'Please enter at least 5 characters.'});
|
||||
@@ -34,7 +34,7 @@ export default class ResetPasswordModal extends React.Component {
|
||||
|
||||
Client.resetPassword(data,
|
||||
() => {
|
||||
this.props.onModalSubmit(React.findDOMNode(this.refs.password).value);
|
||||
this.props.onModalSubmit(ReactDOM.findDOMNode(this.refs.password).value);
|
||||
},
|
||||
(err) => {
|
||||
this.setState({serverError: err.message});
|
||||
|
||||
@@ -13,7 +13,7 @@ export default class SelectTeamModal extends React.Component {
|
||||
|
||||
doSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.props.onModalSubmit(React.findDOMNode(this.refs.team).value);
|
||||
this.props.onModalSubmit(ReactDOM.findDOMNode(this.refs.team).value);
|
||||
}
|
||||
doCancel() {
|
||||
this.props.onModalDismissed();
|
||||
|
||||
@@ -27,28 +27,28 @@ export default class ServiceSettings extends React.Component {
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.ServiceSettings.ListenAddress = React.findDOMNode(this.refs.ListenAddress).value.trim();
|
||||
config.ServiceSettings.ListenAddress = ReactDOM.findDOMNode(this.refs.ListenAddress).value.trim();
|
||||
if (config.ServiceSettings.ListenAddress === '') {
|
||||
config.ServiceSettings.ListenAddress = ':8065';
|
||||
React.findDOMNode(this.refs.ListenAddress).value = config.ServiceSettings.ListenAddress;
|
||||
ReactDOM.findDOMNode(this.refs.ListenAddress).value = config.ServiceSettings.ListenAddress;
|
||||
}
|
||||
|
||||
config.ServiceSettings.SegmentDeveloperKey = React.findDOMNode(this.refs.SegmentDeveloperKey).value.trim();
|
||||
config.ServiceSettings.GoogleDeveloperKey = React.findDOMNode(this.refs.GoogleDeveloperKey).value.trim();
|
||||
config.ServiceSettings.EnableIncomingWebhooks = React.findDOMNode(this.refs.EnableIncomingWebhooks).checked;
|
||||
config.ServiceSettings.EnablePostUsernameOverride = React.findDOMNode(this.refs.EnablePostUsernameOverride).checked;
|
||||
config.ServiceSettings.EnablePostIconOverride = React.findDOMNode(this.refs.EnablePostIconOverride).checked;
|
||||
config.ServiceSettings.EnableTesting = React.findDOMNode(this.refs.EnableTesting).checked;
|
||||
config.ServiceSettings.EnableSecurityFixAlert = React.findDOMNode(this.refs.EnableSecurityFixAlert).checked;
|
||||
config.ServiceSettings.SegmentDeveloperKey = ReactDOM.findDOMNode(this.refs.SegmentDeveloperKey).value.trim();
|
||||
config.ServiceSettings.GoogleDeveloperKey = ReactDOM.findDOMNode(this.refs.GoogleDeveloperKey).value.trim();
|
||||
config.ServiceSettings.EnableIncomingWebhooks = ReactDOM.findDOMNode(this.refs.EnableIncomingWebhooks).checked;
|
||||
config.ServiceSettings.EnablePostUsernameOverride = ReactDOM.findDOMNode(this.refs.EnablePostUsernameOverride).checked;
|
||||
config.ServiceSettings.EnablePostIconOverride = ReactDOM.findDOMNode(this.refs.EnablePostIconOverride).checked;
|
||||
config.ServiceSettings.EnableTesting = ReactDOM.findDOMNode(this.refs.EnableTesting).checked;
|
||||
config.ServiceSettings.EnableSecurityFixAlert = ReactDOM.findDOMNode(this.refs.EnableSecurityFixAlert).checked;
|
||||
|
||||
//config.ServiceSettings.EnableOAuthServiceProvider = React.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
|
||||
//config.ServiceSettings.EnableOAuthServiceProvider = ReactDOM.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
|
||||
|
||||
var MaximumLoginAttempts = 10;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.MaximumLoginAttempts).value, 10))) {
|
||||
MaximumLoginAttempts = parseInt(React.findDOMNode(this.refs.MaximumLoginAttempts).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.MaximumLoginAttempts).value, 10))) {
|
||||
MaximumLoginAttempts = parseInt(ReactDOM.findDOMNode(this.refs.MaximumLoginAttempts).value, 10);
|
||||
}
|
||||
config.ServiceSettings.MaximumLoginAttempts = MaximumLoginAttempts;
|
||||
React.findDOMNode(this.refs.MaximumLoginAttempts).value = MaximumLoginAttempts;
|
||||
ReactDOM.findDOMNode(this.refs.MaximumLoginAttempts).value = MaximumLoginAttempts;
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
|
||||
@@ -29,27 +29,27 @@ export default class SqlSettings extends React.Component {
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.SqlSettings.Trace = React.findDOMNode(this.refs.Trace).checked;
|
||||
config.SqlSettings.AtRestEncryptKey = React.findDOMNode(this.refs.AtRestEncryptKey).value.trim();
|
||||
config.SqlSettings.Trace = ReactDOM.findDOMNode(this.refs.Trace).checked;
|
||||
config.SqlSettings.AtRestEncryptKey = ReactDOM.findDOMNode(this.refs.AtRestEncryptKey).value.trim();
|
||||
|
||||
if (config.SqlSettings.AtRestEncryptKey === '') {
|
||||
config.SqlSettings.AtRestEncryptKey = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
React.findDOMNode(this.refs.AtRestEncryptKey).value = config.SqlSettings.AtRestEncryptKey;
|
||||
ReactDOM.findDOMNode(this.refs.AtRestEncryptKey).value = config.SqlSettings.AtRestEncryptKey;
|
||||
}
|
||||
|
||||
var MaxOpenConns = 10;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.MaxOpenConns).value, 10))) {
|
||||
MaxOpenConns = parseInt(React.findDOMNode(this.refs.MaxOpenConns).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.MaxOpenConns).value, 10))) {
|
||||
MaxOpenConns = parseInt(ReactDOM.findDOMNode(this.refs.MaxOpenConns).value, 10);
|
||||
}
|
||||
config.SqlSettings.MaxOpenConns = MaxOpenConns;
|
||||
React.findDOMNode(this.refs.MaxOpenConns).value = MaxOpenConns;
|
||||
ReactDOM.findDOMNode(this.refs.MaxOpenConns).value = MaxOpenConns;
|
||||
|
||||
var MaxIdleConns = 10;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.MaxIdleConns).value, 10))) {
|
||||
MaxIdleConns = parseInt(React.findDOMNode(this.refs.MaxIdleConns).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.MaxIdleConns).value, 10))) {
|
||||
MaxIdleConns = parseInt(ReactDOM.findDOMNode(this.refs.MaxIdleConns).value, 10);
|
||||
}
|
||||
config.SqlSettings.MaxIdleConns = MaxIdleConns;
|
||||
React.findDOMNode(this.refs.MaxIdleConns).value = MaxIdleConns;
|
||||
ReactDOM.findDOMNode(this.refs.MaxIdleConns).value = MaxIdleConns;
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
@@ -79,7 +79,7 @@ export default class SqlSettings extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
React.findDOMNode(this.refs.AtRestEncryptKey).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
ReactDOM.findDOMNode(this.refs.AtRestEncryptKey).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
|
||||
var s = {saveNeeded: true, serverError: this.state.serverError};
|
||||
this.setState(s);
|
||||
}
|
||||
@@ -220,7 +220,7 @@ export default class SqlSettings extends React.Component {
|
||||
<p className='help-text'>{'32-character salt available to encrypt and decrypt sensitive fields in database.'}</p>
|
||||
<div className='help-text'>
|
||||
<button
|
||||
className='help-link'
|
||||
className='btn btn-default'
|
||||
onClick={this.handleGenerate}
|
||||
>
|
||||
{'Re-Generate'}
|
||||
|
||||
@@ -27,17 +27,17 @@ export default class TeamSettings extends React.Component {
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.TeamSettings.SiteName = React.findDOMNode(this.refs.SiteName).value.trim();
|
||||
config.TeamSettings.RestrictCreationToDomains = React.findDOMNode(this.refs.RestrictCreationToDomains).value.trim();
|
||||
config.TeamSettings.EnableTeamCreation = React.findDOMNode(this.refs.EnableTeamCreation).checked;
|
||||
config.TeamSettings.EnableUserCreation = React.findDOMNode(this.refs.EnableUserCreation).checked;
|
||||
config.TeamSettings.SiteName = ReactDOM.findDOMNode(this.refs.SiteName).value.trim();
|
||||
config.TeamSettings.RestrictCreationToDomains = ReactDOM.findDOMNode(this.refs.RestrictCreationToDomains).value.trim();
|
||||
config.TeamSettings.EnableTeamCreation = ReactDOM.findDOMNode(this.refs.EnableTeamCreation).checked;
|
||||
config.TeamSettings.EnableUserCreation = ReactDOM.findDOMNode(this.refs.EnableUserCreation).checked;
|
||||
|
||||
var MaxUsersPerTeam = 50;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.MaxUsersPerTeam).value, 10))) {
|
||||
MaxUsersPerTeam = parseInt(React.findDOMNode(this.refs.MaxUsersPerTeam).value, 10);
|
||||
if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.MaxUsersPerTeam).value, 10))) {
|
||||
MaxUsersPerTeam = parseInt(ReactDOM.findDOMNode(this.refs.MaxUsersPerTeam).value, 10);
|
||||
}
|
||||
config.TeamSettings.MaxUsersPerTeam = MaxUsersPerTeam;
|
||||
React.findDOMNode(this.refs.MaxUsersPerTeam).value = MaxUsersPerTeam;
|
||||
ReactDOM.findDOMNode(this.refs.MaxUsersPerTeam).value = MaxUsersPerTeam;
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
|
||||
@@ -29,7 +29,7 @@ export default class ChangeUrlModal extends React.Component {
|
||||
}
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.show === true && prevProps.show === false) {
|
||||
React.findDOMNode(this.refs.urlinput).select();
|
||||
ReactDOM.findDOMNode(this.refs.urlinput).select();
|
||||
}
|
||||
}
|
||||
onURLChanged(e) {
|
||||
@@ -60,7 +60,7 @@ export default class ChangeUrlModal extends React.Component {
|
||||
doSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const url = React.findDOMNode(this.refs.urlinput).value;
|
||||
const url = ReactDOM.findDOMNode(this.refs.urlinput).value;
|
||||
const cleanedURL = Utils.cleanUpUrlable(url);
|
||||
if (cleanedURL !== url || url.length < 2 || url.indexOf('__') > -1) {
|
||||
this.setState({urlError: this.getURLError(url)});
|
||||
|
||||
@@ -17,6 +17,9 @@ const AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||
const Constants = require('../utils/constants.jsx');
|
||||
const ActionTypes = Constants.ActionTypes;
|
||||
|
||||
const Popover = ReactBootstrap.Popover;
|
||||
const OverlayTrigger = ReactBootstrap.OverlayTrigger;
|
||||
|
||||
export default class ChannelHeader extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -110,7 +113,21 @@ export default class ChannelHeader extends React.Component {
|
||||
}
|
||||
|
||||
const channel = this.state.channel;
|
||||
const popoverContent = React.renderToString(<MessageWrapper message={channel.description}/>);
|
||||
const popoverContent = (
|
||||
<Popover
|
||||
id='hader-popover'
|
||||
bStyle='info'
|
||||
bSize='large'
|
||||
placement='bottom'
|
||||
className='description'
|
||||
onMouseOver={() => this.refs.descriptionOverlay.show()}
|
||||
onMouseOut={() => this.refs.descriptionOverlay.hide()}
|
||||
>
|
||||
<MessageWrapper
|
||||
message={channel.description}
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
let channelTitle = channel.display_name;
|
||||
const currentId = UserStore.getCurrentId();
|
||||
const isAdmin = Utils.isAdmin(this.state.memberChannel.roles) || Utils.isAdmin(this.state.memberTeam.roles);
|
||||
@@ -301,75 +318,82 @@ export default class ChannelHeader extends React.Component {
|
||||
|
||||
return (
|
||||
<table className='channel-header alt'>
|
||||
<tr>
|
||||
<th>
|
||||
<div className='channel-header__info'>
|
||||
<div className='dropdown'>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
<div className='channel-header__info'>
|
||||
<div className='dropdown'>
|
||||
<a
|
||||
href='#'
|
||||
className='dropdown-toggle theme'
|
||||
type='button'
|
||||
id='channel_header_dropdown'
|
||||
data-toggle='dropdown'
|
||||
aria-expanded='true'
|
||||
>
|
||||
<strong className='heading'>{channelTitle} </strong>
|
||||
<span className='glyphicon glyphicon-chevron-down header-dropdown__icon' />
|
||||
</a>
|
||||
<ul
|
||||
className='dropdown-menu'
|
||||
role='menu'
|
||||
aria-labelledby='channel_header_dropdown'
|
||||
>
|
||||
{dropdownContents}
|
||||
</ul>
|
||||
</div>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
placement='bottom'
|
||||
overlay={popoverContent}
|
||||
ref='descriptionOverlay'
|
||||
>
|
||||
<div
|
||||
onClick={TextFormatting.handleClick}
|
||||
className='description'
|
||||
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(channel.description, {singleline: true, mentionHighlight: false})}}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
</th>
|
||||
<th>
|
||||
<PopoverListMembers
|
||||
members={this.state.users}
|
||||
channelId={channel.id}
|
||||
/>
|
||||
</th>
|
||||
<th className='search-bar__container'><NavbarSearchBox /></th>
|
||||
<th>
|
||||
<div className='dropdown channel-header__links'>
|
||||
<a
|
||||
href='#'
|
||||
className='dropdown-toggle theme'
|
||||
type='button'
|
||||
id='channel_header_dropdown'
|
||||
id='channel_header_right_dropdown'
|
||||
data-toggle='dropdown'
|
||||
aria-expanded='true'
|
||||
>
|
||||
<strong className='heading'>{channelTitle} </strong>
|
||||
<span className='glyphicon glyphicon-chevron-down header-dropdown__icon' />
|
||||
<span dangerouslySetInnerHTML={{__html: Constants.MENU_ICON}} />
|
||||
</a>
|
||||
<ul
|
||||
className='dropdown-menu'
|
||||
className='dropdown-menu dropdown-menu-right'
|
||||
role='menu'
|
||||
aria-labelledby='channel_header_dropdown'
|
||||
aria-labelledby='channel_header_right_dropdown'
|
||||
>
|
||||
{dropdownContents}
|
||||
<li role='presentation'>
|
||||
<a
|
||||
role='menuitem'
|
||||
href='#'
|
||||
onClick={this.searchMentions}
|
||||
>
|
||||
Recent Mentions
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
data-toggle='popover'
|
||||
data-content={popoverContent}
|
||||
className='description'
|
||||
onClick={TextFormatting.handleClick}
|
||||
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(channel.description, {singleline: true, mentionHighlight: false})}}
|
||||
/>
|
||||
</div>
|
||||
</th>
|
||||
<th>
|
||||
<PopoverListMembers
|
||||
members={this.state.users}
|
||||
channelId={channel.id}
|
||||
/>
|
||||
</th>
|
||||
<th className='search-bar__container'><NavbarSearchBox /></th>
|
||||
<th>
|
||||
<div className='dropdown channel-header__links'>
|
||||
<a
|
||||
href='#'
|
||||
className='dropdown-toggle theme'
|
||||
type='button'
|
||||
id='channel_header_right_dropdown'
|
||||
data-toggle='dropdown'
|
||||
aria-expanded='true'
|
||||
>
|
||||
<span dangerouslySetInnerHTML={{__html: Constants.MENU_ICON}} />
|
||||
</a>
|
||||
<ul
|
||||
className='dropdown-menu dropdown-menu-right'
|
||||
role='menu'
|
||||
aria-labelledby='channel_header_right_dropdown'
|
||||
>
|
||||
<li role='presentation'>
|
||||
<a
|
||||
role='menuitem'
|
||||
href='#'
|
||||
onClick={this.searchMentions}
|
||||
>
|
||||
Recent Mentions
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export default class CommandList extends React.Component {
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
if (this.refs.modal) {
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function show(e) {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', function show(e) {
|
||||
var button = e.relatedTarget;
|
||||
self.setState({channel_id: $(button).attr('data-channelid')});
|
||||
});
|
||||
|
||||
@@ -56,8 +56,8 @@ export default class ChannelInviteModal extends React.Component {
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this)).on('hidden.bs.modal', this.onHide);
|
||||
$(React.findDOMNode(this)).on('show.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this)).on('hidden.bs.modal', this.onHide);
|
||||
$(ReactDOM.findDOMNode(this)).on('show.bs.modal', this.onShow);
|
||||
|
||||
ChannelStore.addExtraInfoChangeListener(this.onListenerChange);
|
||||
ChannelStore.addChangeListener(this.onListenerChange);
|
||||
|
||||
@@ -75,15 +75,6 @@ export default class ChannelLoader extends React.Component {
|
||||
Utils.applyTheme(Constants.THEMES.default);
|
||||
}
|
||||
|
||||
/* Setup global mouse events */
|
||||
$('body').on('click', function hidePopover(e) {
|
||||
$('[data-toggle="popover"]').each(function eachPopover() {
|
||||
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
|
||||
$(this).popover('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('mouseenter mouseleave', '.post', function mouseOver(ev) {
|
||||
if (ev.type === 'mouseenter') {
|
||||
$(this).parent('div').prev('.date-separator, .new-separator').addClass('hovered--after');
|
||||
|
||||
@@ -74,9 +74,9 @@ export default class ChannelMembers extends React.Component {
|
||||
componentDidMount() {
|
||||
ChannelStore.addExtraInfoChangeListener(this.onChange);
|
||||
ChannelStore.addChangeListener(this.onChange);
|
||||
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
ChannelStore.removeExtraInfoChangeListener(this.onChange);
|
||||
|
||||
@@ -51,7 +51,7 @@ export default class ChannelNotifications extends React.Component {
|
||||
componentDidMount() {
|
||||
ChannelStore.addChangeListener(this.onListenerChange);
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
ChannelStore.removeChangeListener(this.onListenerChange);
|
||||
@@ -104,7 +104,7 @@ export default class ChannelNotifications extends React.Component {
|
||||
}
|
||||
handleUpdateNotifyLevel(notifyLevel) {
|
||||
this.setState({notifyLevel});
|
||||
React.findDOMNode(this.refs.modal).focus();
|
||||
ReactDOM.findDOMNode(this.refs.modal).focus();
|
||||
}
|
||||
createNotifyLevelSection(serverError) {
|
||||
var handleUpdateSection;
|
||||
@@ -266,7 +266,7 @@ export default class ChannelNotifications extends React.Component {
|
||||
|
||||
handleUpdateMarkUnreadLevel(markUnreadLevel) {
|
||||
this.setState({markUnreadLevel});
|
||||
React.findDOMNode(this.refs.modal).focus();
|
||||
ReactDOM.findDOMNode(this.refs.modal).focus();
|
||||
}
|
||||
|
||||
createMarkUnreadLevelSection(serverError) {
|
||||
|
||||
@@ -46,7 +46,9 @@ export default class CreateComment extends React.Component {
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevState.uploadsInProgress < this.state.uploadsInProgress) {
|
||||
$('.post-right__scroll').scrollTop($('.post-right__scroll')[0].scrollHeight);
|
||||
$('.post-right__scroll').perfectScrollbar('update');
|
||||
if ($(window).width() > 768) {
|
||||
$('.post-right__scroll').perfectScrollbar('update');
|
||||
}
|
||||
}
|
||||
}
|
||||
handleSubmit(e) {
|
||||
@@ -126,7 +128,7 @@ export default class CreateComment extends React.Component {
|
||||
commentMsgKeyPress(e) {
|
||||
if (e.which === 13 && !e.shiftKey && !e.altKey) {
|
||||
e.preventDefault();
|
||||
React.findDOMNode(this.refs.textbox).blur();
|
||||
ReactDOM.findDOMNode(this.refs.textbox).blur();
|
||||
this.handleSubmit(e);
|
||||
}
|
||||
|
||||
@@ -189,7 +191,7 @@ export default class CreateComment extends React.Component {
|
||||
handleTextDrop(text) {
|
||||
const newText = this.state.messageText + text;
|
||||
this.handleUserInput(newText);
|
||||
Utils.setCaretPosition(React.findDOMNode(this.refs.textbox.refs.message), newText.length);
|
||||
Utils.setCaretPosition(ReactDOM.findDOMNode(this.refs.textbox.refs.message), newText.length);
|
||||
}
|
||||
removePreview(id) {
|
||||
let previews = this.state.previews;
|
||||
@@ -255,6 +257,17 @@ export default class CreateComment extends React.Component {
|
||||
postFooterClassName += ' has-error';
|
||||
}
|
||||
|
||||
let uploadsInProgressText = null;
|
||||
if (this.state.uploadsInProgress.length > 0) {
|
||||
uploadsInProgressText = (
|
||||
<span
|
||||
className='pull-right post-right-comments-upload-in-progress'
|
||||
>
|
||||
{this.state.uploadsInProgress.length === 1 ? 'File uploading' : 'Files uploading'}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<div className='post-create'>
|
||||
@@ -295,6 +308,7 @@ export default class CreateComment extends React.Component {
|
||||
value='Add Comment'
|
||||
onClick={this.handleSubmit}
|
||||
/>
|
||||
{uploadsInProgressText}
|
||||
{postError}
|
||||
{serverError}
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,7 @@ const Utils = require('../utils/utils.jsx');
|
||||
|
||||
const Constants = require('../utils/constants.jsx');
|
||||
const ActionTypes = Constants.ActionTypes;
|
||||
const KeyCodes = Constants.KeyCodes;
|
||||
|
||||
export default class CreatePost extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -35,6 +36,7 @@ export default class CreatePost extends React.Component {
|
||||
this.removePreview = this.removePreview.bind(this);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.getFileCount = this.getFileCount.bind(this);
|
||||
this.handleArrowUp = this.handleArrowUp.bind(this);
|
||||
|
||||
PostStore.clearDraftUploads();
|
||||
|
||||
@@ -172,9 +174,9 @@ export default class CreatePost extends React.Component {
|
||||
}
|
||||
}
|
||||
postMsgKeyPress(e) {
|
||||
if (e.which === 13 && !e.shiftKey && !e.altKey) {
|
||||
if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
|
||||
e.preventDefault();
|
||||
React.findDOMNode(this.refs.textbox).blur();
|
||||
ReactDOM.findDOMNode(this.refs.textbox).blur();
|
||||
this.handleSubmit(e);
|
||||
}
|
||||
|
||||
@@ -192,7 +194,7 @@ export default class CreatePost extends React.Component {
|
||||
PostStore.storeCurrentDraft(draft);
|
||||
}
|
||||
resizePostHolder() {
|
||||
const height = $(window).height() - $(React.findDOMNode(this.refs.topDiv)).height() - 50;
|
||||
const height = $(window).height() - $(ReactDOM.findDOMNode(this.refs.topDiv)).height() - 50;
|
||||
$('.post-list-holder-by-time').css('height', `${height}px`);
|
||||
$(window).trigger('resize');
|
||||
if ($(window).width() > 960) {
|
||||
@@ -243,7 +245,7 @@ export default class CreatePost extends React.Component {
|
||||
handleTextDrop(text) {
|
||||
const newText = this.state.messageText + text;
|
||||
this.handleUserInput(newText);
|
||||
Utils.setCaretPosition(React.findDOMNode(this.refs.textbox.refs.message), newText.length);
|
||||
Utils.setCaretPosition(ReactDOM.findDOMNode(this.refs.textbox.refs.message), newText.length);
|
||||
}
|
||||
removePreview(id) {
|
||||
const previews = Object.assign([], this.state.previews);
|
||||
@@ -292,6 +294,27 @@ export default class CreatePost extends React.Component {
|
||||
const draft = PostStore.getDraft(channelId);
|
||||
return draft.previews.length + draft.uploadsInProgress.length;
|
||||
}
|
||||
handleArrowUp(e) {
|
||||
if (e.keyCode === KeyCodes.UP && this.state.messageText === '') {
|
||||
e.preventDefault();
|
||||
|
||||
const channelId = ChannelStore.getCurrentId();
|
||||
const lastPost = PostStore.getCurrentUsersLatestPost(channelId);
|
||||
if (!lastPost) {
|
||||
return;
|
||||
}
|
||||
var type = (lastPost.root_id && lastPost.root_id.length > 0) ? 'Comment' : 'Post';
|
||||
|
||||
AppDispatcher.handleViewAction({
|
||||
type: ActionTypes.RECIEVED_EDIT_POST,
|
||||
refocusId: '#post_textbox',
|
||||
title: type,
|
||||
message: lastPost.message,
|
||||
postId: lastPost.id,
|
||||
channelId: lastPost.channel_id
|
||||
});
|
||||
}
|
||||
}
|
||||
render() {
|
||||
let serverError = null;
|
||||
if (this.state.serverError) {
|
||||
@@ -336,6 +359,7 @@ export default class CreatePost extends React.Component {
|
||||
<Textbox
|
||||
onUserInput={this.handleUserInput}
|
||||
onKeyPress={this.postMsgKeyPress}
|
||||
onKeyDown={this.handleArrowUp}
|
||||
onHeightChange={this.resizePostHolder}
|
||||
messageText={this.state.messageText}
|
||||
createMessage='Write a message...'
|
||||
|
||||
@@ -41,7 +41,7 @@ export default class DeleteChannelModal extends React.Component {
|
||||
});
|
||||
}
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
}
|
||||
render() {
|
||||
const channel = ChannelStore.getCurrent();
|
||||
|
||||
@@ -73,7 +73,7 @@ export default class DeletePostModal extends React.Component {
|
||||
this.setState(newState);
|
||||
}
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
PostStore.addSelectedPostChangeListener(this.onListenerChange);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
|
||||
@@ -34,7 +34,7 @@ export default class EditChannelModal extends React.Component {
|
||||
function handleUpdateSuccess() {
|
||||
this.setState({serverError: ''});
|
||||
AsyncClient.getChannel(this.state.channelId);
|
||||
$(React.findDOMNode(this.refs.modal)).modal('hide');
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide');
|
||||
}.bind(this),
|
||||
function handleUpdateError(err) {
|
||||
if (err.message === 'Invalid channel_description parameter') {
|
||||
@@ -56,11 +56,11 @@ export default class EditChannelModal extends React.Component {
|
||||
this.setState({description: $(button).attr('data-desc'), title: $(button).attr('data-title'), channelId: $(button).attr('data-channelid'), serverError: ''});
|
||||
}
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.handleClose);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.handleClose);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
$(React.findDOMNode(this.refs.modal)).off('hidden.bs.modal', this.handleClose);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).off('hidden.bs.modal', this.handleClose);
|
||||
}
|
||||
render() {
|
||||
var serverError = null;
|
||||
|
||||
@@ -5,6 +5,7 @@ var Client = require('../utils/client.jsx');
|
||||
var AsyncClient = require('../utils/async_client.jsx');
|
||||
var Textbox = require('./textbox.jsx');
|
||||
var BrowserStore = require('../stores/browser_store.jsx');
|
||||
var PostStore = require('../stores/post_store.jsx');
|
||||
|
||||
export default class EditPostModal extends React.Component {
|
||||
constructor() {
|
||||
@@ -14,6 +15,7 @@ export default class EditPostModal extends React.Component {
|
||||
this.handleEditInput = this.handleEditInput.bind(this);
|
||||
this.handleEditKeyPress = this.handleEditKeyPress.bind(this);
|
||||
this.handleUserInput = this.handleUserInput.bind(this);
|
||||
this.handleEditPostEvent = this.handleEditPostEvent.bind(this);
|
||||
|
||||
this.state = {editText: '', title: '', post_id: '', channel_id: '', comments: 0, refocusId: ''};
|
||||
}
|
||||
@@ -35,16 +37,15 @@ export default class EditPostModal extends React.Component {
|
||||
|
||||
Client.updatePost(updatedPost,
|
||||
function success() {
|
||||
AsyncClient.getPosts(this.state.channel_id);
|
||||
AsyncClient.getPosts(updatedPost.channel_id);
|
||||
window.scrollTo(0, 0);
|
||||
}.bind(this),
|
||||
},
|
||||
function error(err) {
|
||||
AsyncClient.dispatchError(err, 'updatePost');
|
||||
}
|
||||
);
|
||||
|
||||
$('#edit_post').modal('hide');
|
||||
$(this.state.refocusId).focus();
|
||||
}
|
||||
handleEditInput(editMessage) {
|
||||
this.setState({editText: editMessage});
|
||||
@@ -52,28 +53,57 @@ export default class EditPostModal extends React.Component {
|
||||
handleEditKeyPress(e) {
|
||||
if (e.which === 13 && !e.shiftKey && !e.altKey) {
|
||||
e.preventDefault();
|
||||
React.findDOMNode(this.refs.editbox).blur();
|
||||
ReactDOM.findDOMNode(this.refs.editbox).blur();
|
||||
this.handleEdit(e);
|
||||
}
|
||||
}
|
||||
handleUserInput(e) {
|
||||
this.setState({editText: e.target.value});
|
||||
}
|
||||
handleEditPostEvent(options) {
|
||||
this.setState({
|
||||
editText: options.message || '',
|
||||
title: options.title || '',
|
||||
post_id: options.postId || '',
|
||||
channel_id: options.channelId || '',
|
||||
comments: options.comments || 0,
|
||||
refocusId: options.refocusId || ''
|
||||
});
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).modal('show');
|
||||
}
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function onHidden() {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function onHidden() {
|
||||
self.setState({editText: '', title: '', channel_id: '', post_id: '', comments: 0, refocusId: '', error: ''});
|
||||
});
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function onShow(e) {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', function onShow(e) {
|
||||
var button = e.relatedTarget;
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
self.setState({editText: $(button).attr('data-message'), title: $(button).attr('data-title'), channel_id: $(button).attr('data-channelid'), post_id: $(button).attr('data-postid'), comments: $(button).attr('data-comments'), refocusId: $(button).attr('data-refoucsid')});
|
||||
});
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('shown.bs.modal', function onShown() {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', function onShown() {
|
||||
self.refs.editbox.resize();
|
||||
$('#edit_textbox').get(0).focus();
|
||||
});
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('hide.bs.modal', function onShown() {
|
||||
if (self.state.refocusId !== '') {
|
||||
setTimeout(() => {
|
||||
$(self.state.refocusId).get(0).focus();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
PostStore.addEditPostListener(this.handleEditPostEvent);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
PostStore.removeEditPostListener(this.handleEditPostEvent);
|
||||
}
|
||||
render() {
|
||||
var error = (<div className='form-group'><br /></div>);
|
||||
|
||||
@@ -39,11 +39,9 @@ export default class EmailVerify extends React.Component {
|
||||
|
||||
return (
|
||||
<div className='col-sm-12'>
|
||||
<div className='panel panel-default verify_panel'>
|
||||
<div className='panel-heading'>
|
||||
<h3 className='panel-title'>{title}</h3>
|
||||
</div>
|
||||
<div className='panel-body'>
|
||||
<div className='signup-team__container'>
|
||||
<h3>{title}</h3>
|
||||
<div>
|
||||
{body}
|
||||
{resend}
|
||||
{resendConfirm}
|
||||
|
||||
@@ -43,7 +43,7 @@ export default class FileAttachment extends React.Component {
|
||||
return function loader() {
|
||||
$(this).remove();
|
||||
if (name in self.refs) {
|
||||
var imgDiv = React.findDOMNode(self.refs[name]);
|
||||
var imgDiv = ReactDOM.findDOMNode(self.refs[name]);
|
||||
|
||||
$(imgDiv).removeClass('post__load');
|
||||
$(imgDiv).addClass('post__image');
|
||||
@@ -82,7 +82,7 @@ export default class FileAttachment extends React.Component {
|
||||
if (nextState.fileSize !== this.state.fileSize) {
|
||||
if (this.refs.fileSize) {
|
||||
// update the UI element to display the file size without re-rendering the whole component
|
||||
React.findDOMNode(this.refs.fileSize).innerHTML = utils.fileSizeToString(nextState.fileSize);
|
||||
ReactDOM.findDOMNode(this.refs.fileSize).innerHTML = utils.fileSizeToString(nextState.fileSize);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ export default class FileUpload extends React.Component {
|
||||
}
|
||||
|
||||
handleChange() {
|
||||
var element = $(React.findDOMNode(this.refs.fileInput));
|
||||
var element = $(ReactDOM.findDOMNode(this.refs.fileInput));
|
||||
|
||||
this.uploadFiles(element.prop('files'));
|
||||
|
||||
@@ -115,7 +115,7 @@ export default class FileUpload extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
var inputDiv = React.findDOMNode(this.refs.input);
|
||||
var inputDiv = ReactDOM.findDOMNode(this.refs.input);
|
||||
var self = this;
|
||||
|
||||
if (this.props.postType === 'post') {
|
||||
|
||||
@@ -17,7 +17,7 @@ export default class FindTeam extends React.Component {
|
||||
|
||||
var state = { };
|
||||
|
||||
var email = React.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
var email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
if (!email || !utils.isEmail(email)) {
|
||||
state.email_error = 'Please enter a valid email address';
|
||||
this.setState(state);
|
||||
|
||||
@@ -22,12 +22,12 @@ export default class GetLinkModal extends React.Component {
|
||||
}
|
||||
componentDidMount() {
|
||||
if (this.refs.modal) {
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
$(React.findDOMNode(this.refs.modal)).on('hide.bs.modal', this.onHide);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hide.bs.modal', this.onHide);
|
||||
}
|
||||
}
|
||||
handleClick() {
|
||||
var copyTextarea = $(React.findDOMNode(this.refs.textarea));
|
||||
var copyTextarea = $(ReactDOM.findDOMNode(this.refs.textarea));
|
||||
copyTextarea.select();
|
||||
|
||||
try {
|
||||
|
||||
@@ -36,7 +36,7 @@ export default class InviteMemberModal extends React.Component {
|
||||
var notEmpty = false;
|
||||
for (var i = 0; i < self.state.inviteIds.length; i++) {
|
||||
var index = self.state.inviteIds[i];
|
||||
if (React.findDOMNode(self.refs['email' + index]).value.trim() !== '') {
|
||||
if (ReactDOM.findDOMNode(self.refs['email' + index]).value.trim() !== '') {
|
||||
notEmpty = true;
|
||||
break;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ export default class InviteMemberModal extends React.Component {
|
||||
for (var i = 0; i < count; i++) {
|
||||
var index = inviteIds[i];
|
||||
var invite = {};
|
||||
invite.email = React.findDOMNode(this.refs['email' + index]).value.trim();
|
||||
invite.email = ReactDOM.findDOMNode(this.refs['email' + index]).value.trim();
|
||||
if (!invite.email || !utils.isEmail(invite.email)) {
|
||||
emailErrors[index] = 'Please enter a valid email address';
|
||||
valid = false;
|
||||
@@ -77,9 +77,9 @@ export default class InviteMemberModal extends React.Component {
|
||||
emailErrors[index] = '';
|
||||
}
|
||||
|
||||
invite.firstName = React.findDOMNode(this.refs['first_name' + index]).value.trim();
|
||||
invite.firstName = ReactDOM.findDOMNode(this.refs['first_name' + index]).value.trim();
|
||||
|
||||
invite.lastName = React.findDOMNode(this.refs['last_name' + index]).value.trim();
|
||||
invite.lastName = ReactDOM.findDOMNode(this.refs['last_name' + index]).value.trim();
|
||||
|
||||
invites.push(invite);
|
||||
}
|
||||
@@ -95,8 +95,8 @@ export default class InviteMemberModal extends React.Component {
|
||||
|
||||
Client.inviteMembers(data,
|
||||
function success() {
|
||||
$(React.findDOMNode(this.refs.modal)).attr('data-confirm', 'true');
|
||||
$(React.findDOMNode(this.refs.modal)).modal('hide');
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).attr('data-confirm', 'true');
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide');
|
||||
}.bind(this),
|
||||
function fail(err) {
|
||||
if (err.message === 'This person is already on your team') {
|
||||
@@ -110,8 +110,8 @@ export default class InviteMemberModal extends React.Component {
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
$(React.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 200);
|
||||
$(React.findDOMNode(this.refs.modalBody)).css('overflow-y', 'scroll');
|
||||
$(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 200);
|
||||
$(ReactDOM.findDOMNode(this.refs.modalBody)).css('overflow-y', 'scroll');
|
||||
}
|
||||
|
||||
addInviteFields() {
|
||||
@@ -126,9 +126,9 @@ export default class InviteMemberModal extends React.Component {
|
||||
|
||||
for (var i = 0; i < inviteIds.length; i++) {
|
||||
var index = inviteIds[i];
|
||||
React.findDOMNode(this.refs['email' + index]).value = '';
|
||||
React.findDOMNode(this.refs['first_name' + index]).value = '';
|
||||
React.findDOMNode(this.refs['last_name' + index]).value = '';
|
||||
ReactDOM.findDOMNode(this.refs['email' + index]).value = '';
|
||||
ReactDOM.findDOMNode(this.refs['first_name' + index]).value = '';
|
||||
ReactDOM.findDOMNode(this.refs['last_name' + index]).value = '';
|
||||
}
|
||||
|
||||
this.setState({
|
||||
|
||||
@@ -25,14 +25,14 @@ export default class Login extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
const email = React.findDOMNode(this.refs.email).value.trim();
|
||||
const email = ReactDOM.findDOMNode(this.refs.email).value.trim();
|
||||
if (!email) {
|
||||
state.serverError = 'An email is required';
|
||||
this.setState(state);
|
||||
return;
|
||||
}
|
||||
|
||||
const password = React.findDOMNode(this.refs.password).value.trim();
|
||||
const password = ReactDOM.findDOMNode(this.refs.password).value.trim();
|
||||
if (!password) {
|
||||
state.serverError = 'A password is required';
|
||||
this.setState(state);
|
||||
|
||||
@@ -61,7 +61,7 @@ export default class MentionList extends React.Component {
|
||||
}
|
||||
onClick(e) {
|
||||
if (!($('#' + this.props.id).is(e.target) || $('#' + this.props.id).has(e.target).length ||
|
||||
('mentionlist' in this.refs && $(React.findDOMNode(this.refs.mentionlist)).has(e.target).length))) {
|
||||
('mentionlist' in this.refs && $(ReactDOM.findDOMNode(this.refs.mentionlist)).has(e.target).length))) {
|
||||
this.setState({mentionText: '-1'});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ export default class MoreChannels extends React.Component {
|
||||
}
|
||||
componentDidMount() {
|
||||
ChannelStore.addMoreChangeListener(this.onListenerChange);
|
||||
$(React.findDOMNode(this.refs.modal)).on('shown.bs.modal', function shown() {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', function shown() {
|
||||
asyncClient.getMoreChannels(true);
|
||||
});
|
||||
|
||||
var self = this;
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function show(e) {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', function show(e) {
|
||||
var button = e.relatedTarget;
|
||||
self.setState({channelType: $(button).attr('data-channeltype')});
|
||||
});
|
||||
@@ -54,7 +54,7 @@ export default class MoreChannels extends React.Component {
|
||||
this.setState({joiningChannel: channelIndex});
|
||||
client.joinChannel(channel.id,
|
||||
function joinSuccess() {
|
||||
$(React.findDOMNode(this.refs.modal)).modal('hide');
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide');
|
||||
asyncClient.getChannel(channel.id);
|
||||
utils.switchChannel(channel);
|
||||
this.setState({joiningChannel: -1});
|
||||
@@ -65,7 +65,7 @@ export default class MoreChannels extends React.Component {
|
||||
);
|
||||
}
|
||||
handleNewChannel() {
|
||||
$(React.findDOMNode(this.refs.modal)).modal('hide');
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide');
|
||||
this.setState({showNewChannelModal: true});
|
||||
}
|
||||
render() {
|
||||
|
||||
@@ -1,133 +1,273 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
var TeamStore = require('../stores/team_store.jsx');
|
||||
var Client = require('../utils/client.jsx');
|
||||
var Constants = require('../utils/constants.jsx');
|
||||
var AsyncClient = require('../utils/async_client.jsx');
|
||||
var PreferenceStore = require('../stores/preference_store.jsx');
|
||||
var utils = require('../utils/utils.jsx');
|
||||
const AsyncClient = require('../utils/async_client.jsx');
|
||||
const ChannelStore = require('../stores/channel_store.jsx');
|
||||
const Constants = require('../utils/constants.jsx');
|
||||
const Client = require('../utils/client.jsx');
|
||||
const Modal = ReactBootstrap.Modal;
|
||||
const PreferenceStore = require('../stores/preference_store.jsx');
|
||||
const TeamStore = require('../stores/team_store.jsx');
|
||||
const UserStore = require('../stores/user_store.jsx');
|
||||
const Utils = require('../utils/utils.jsx');
|
||||
|
||||
export default class MoreDirectChannels extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {channels: [], loadingDMChannel: -1};
|
||||
this.handleFilterChange = this.handleFilterChange.bind(this);
|
||||
this.handleHide = this.handleHide.bind(this);
|
||||
this.handleShowDirectChannel = this.handleShowDirectChannel.bind(this);
|
||||
this.handleUserChange = this.handleUserChange.bind(this);
|
||||
|
||||
this.createRowForUser = this.createRowForUser.bind(this);
|
||||
|
||||
this.state = {
|
||||
users: this.getUsersFromStore(),
|
||||
filter: '',
|
||||
loadingDMChannel: -1
|
||||
};
|
||||
}
|
||||
|
||||
getUsersFromStore() {
|
||||
const currentId = UserStore.getCurrentId();
|
||||
const profiles = UserStore.getProfiles();
|
||||
const users = [];
|
||||
|
||||
for (const id in profiles) {
|
||||
if (id !== currentId) {
|
||||
users.push(profiles[id]);
|
||||
}
|
||||
}
|
||||
|
||||
users.sort((a, b) => a.username.localeCompare(b.username));
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', (e) => {
|
||||
var button = e.relatedTarget;
|
||||
this.setState({channels: $(button).data('channels')}); // eslint-disable-line react/no-did-mount-set-state
|
||||
});
|
||||
UserStore.addChangeListener(this.handleUserChange);
|
||||
}
|
||||
|
||||
handleJoinDirectChannel(channel) {
|
||||
const preference = PreferenceStore.setPreference(Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, channel.teammate_id, 'true');
|
||||
componentWillUnmount() {
|
||||
UserStore.addChangeListener(this.handleUserChange);
|
||||
}
|
||||
|
||||
handleFilterChange() {
|
||||
const filter = ReactDOM.findDOMNode(this.refs.filter).value;
|
||||
|
||||
if (filter !== this.state.filter) {
|
||||
this.setState({filter});
|
||||
}
|
||||
}
|
||||
|
||||
handleHide() {
|
||||
if (this.props.onModalDismissed) {
|
||||
this.props.onModalDismissed();
|
||||
}
|
||||
|
||||
this.setState({filter: ''});
|
||||
}
|
||||
|
||||
handleShowDirectChannel(teammate, e) {
|
||||
if (this.state.loadingDMChannel !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
const channelName = Utils.getDirectChannelName(UserStore.getCurrentId(), teammate.id);
|
||||
let channel = ChannelStore.getByName(channelName);
|
||||
|
||||
const preference = PreferenceStore.setPreference(Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, teammate.id, 'true');
|
||||
AsyncClient.savePreferences([preference]);
|
||||
|
||||
if (channel) {
|
||||
Utils.switchChannel(channel);
|
||||
|
||||
this.handleHide();
|
||||
} else {
|
||||
this.setState({loadingDMChannel: teammate.id});
|
||||
|
||||
channel = {
|
||||
name: channelName,
|
||||
last_post_at: 0,
|
||||
total_msg_count: 0,
|
||||
type: 'D',
|
||||
display_name: teammate.username,
|
||||
teammate_id: teammate.id,
|
||||
status: UserStore.getStatus(teammate.id)
|
||||
};
|
||||
|
||||
Client.createDirectChannel(
|
||||
channel,
|
||||
teammate.id,
|
||||
(data) => {
|
||||
this.setState({loadingDMChannel: -1});
|
||||
|
||||
AsyncClient.getChannel(data.id);
|
||||
Utils.switchChannel(data);
|
||||
|
||||
this.handleHide();
|
||||
},
|
||||
() => {
|
||||
this.setState({loadingDMChannel: -1});
|
||||
window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/' + channelName;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
handleUserChange() {
|
||||
this.setState({users: this.getUsersFromStore()});
|
||||
}
|
||||
|
||||
createRowForUser(user) {
|
||||
const details = [];
|
||||
|
||||
const fullName = Utils.getFullName(user);
|
||||
if (fullName) {
|
||||
details.push(
|
||||
<span
|
||||
key={`${user.id}__full-name`}
|
||||
className='full-name'
|
||||
>
|
||||
{fullName}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (user.nickname) {
|
||||
const separator = fullName ? ' - ' : '';
|
||||
details.push(
|
||||
<span
|
||||
key={`${user.nickname}__nickname`}
|
||||
className='nickname'
|
||||
>
|
||||
{separator + user.nickname}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
let joinButton;
|
||||
if (this.state.loadingDMChannel === user.id) {
|
||||
joinButton = (
|
||||
<img
|
||||
className='channel-loading-gif'
|
||||
src='/static/images/load.gif'
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
joinButton = (
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-primary btn-message'
|
||||
onClick={this.handleShowDirectChannel.bind(this, user)}
|
||||
>
|
||||
{'Message'}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
key={user.id}
|
||||
className='direct-channel'
|
||||
>
|
||||
<div className='col-xs-1 image-div'>
|
||||
<img
|
||||
className='profile-image'
|
||||
src={`/api/v1/users/${user.id}/image?time=${user.update_at}`}
|
||||
/>
|
||||
</div>
|
||||
<div className='col-xs-9'>
|
||||
<div className='username'>
|
||||
{user.username}
|
||||
</div>
|
||||
<div>
|
||||
{details}
|
||||
</div>
|
||||
</div>
|
||||
<div className='col-xs-2 btn-div'>
|
||||
{joinButton}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
var directMessageItems = this.state.channels.map((channel, index) => {
|
||||
var badge = '';
|
||||
var titleClass = '';
|
||||
var handleClick = null;
|
||||
if (!this.props.show) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (channel.fake) {
|
||||
// It's a direct message channel that doesn't exist yet so let's create it now
|
||||
var otherUserId = utils.getUserIdFromChannelName(channel);
|
||||
let users = this.state.users;
|
||||
if (this.state.filter !== '') {
|
||||
users = users.filter((user) => {
|
||||
return user.username.indexOf(this.state.filter) !== -1 ||
|
||||
user.first_name.indexOf(this.state.filter) !== -1 ||
|
||||
user.last_name.indexOf(this.state.filter) !== -1 ||
|
||||
user.nickname.indexOf(this.state.filter) !== -1;
|
||||
});
|
||||
}
|
||||
|
||||
if (this.state.loadingDMChannel === index) {
|
||||
badge = (
|
||||
<img
|
||||
className='channel-loading-gif pull-right'
|
||||
src='/static/images/load.gif'
|
||||
/>
|
||||
);
|
||||
}
|
||||
const userEntries = users.map(this.createRowForUser);
|
||||
|
||||
if (this.state.loadingDMChannel === -1) {
|
||||
handleClick = (e) => {
|
||||
e.preventDefault();
|
||||
this.setState({loadingDMChannel: index});
|
||||
this.handleJoinDirectChannel(channel);
|
||||
if (userEntries.length === 0) {
|
||||
userEntries.push(<li key='no-users-found'>{'No users found :('}</li>);
|
||||
}
|
||||
|
||||
Client.createDirectChannel(channel, otherUserId,
|
||||
(data) => {
|
||||
$(React.findDOMNode(this.refs.modal)).modal('hide');
|
||||
this.setState({loadingDMChannel: -1});
|
||||
AsyncClient.getChannel(data.id);
|
||||
utils.switchChannel(data);
|
||||
},
|
||||
() => {
|
||||
this.setState({loadingDMChannel: -1});
|
||||
window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/' + channel.name;
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (channel.unread) {
|
||||
badge = <span className='badge pull-right small'>{channel.unread}</span>;
|
||||
titleClass = 'unread-title';
|
||||
}
|
||||
let memberString = 'Member';
|
||||
if (users.length !== 1) {
|
||||
memberString += 's';
|
||||
}
|
||||
|
||||
handleClick = (e) => {
|
||||
e.preventDefault();
|
||||
this.handleJoinDirectChannel(channel);
|
||||
utils.switchChannel(channel);
|
||||
$(React.findDOMNode(this.refs.modal)).modal('hide');
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<li key={channel.name}>
|
||||
<a
|
||||
className={'sidebar-channel ' + titleClass}
|
||||
href='#'
|
||||
onClick={handleClick}
|
||||
>{badge}{channel.display_name}</a>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
let count;
|
||||
if (users.length === this.state.users.length) {
|
||||
count = `${users.length} ${memberString}`;
|
||||
} else {
|
||||
count = `${users.length} ${memberString} of ${this.state.users.length} Total`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className='modal fade'
|
||||
id='more_direct_channels'
|
||||
ref='modal'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
<Modal
|
||||
className='modal-direct-channels'
|
||||
show={this.props.show}
|
||||
bsSize='large'
|
||||
onHide={this.handleHide}
|
||||
>
|
||||
<div className='modal-dialog'>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
>
|
||||
<span aria-hidden='true'>{'×'}</span>
|
||||
<span className='sr-only'>{'Close'}</span>
|
||||
</button>
|
||||
<h4 className='modal-title'>{'More Direct Messages'}</h4>
|
||||
</div>
|
||||
<div className='modal-body'>
|
||||
<ul className='nav nav-pills nav-stacked'>
|
||||
{directMessageItems}
|
||||
</ul>
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
data-dismiss='modal'
|
||||
>{'Close'}</button>
|
||||
</div>
|
||||
<Modal.Header closeButton={true}>
|
||||
<Modal.Title>{'More Direct Messages'}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<div>
|
||||
<input
|
||||
ref='filter'
|
||||
className='form-control filter-textbox'
|
||||
placeholder='Search members'
|
||||
onInput={this.handleFilterChange}
|
||||
style={{width: '200px', display: 'inline'}}
|
||||
/>
|
||||
<span className='member-count pull-right'>{count}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul className='user-list'>
|
||||
{userEntries}
|
||||
</ul>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
onClick={this.handleHide}
|
||||
>
|
||||
{'Close'}
|
||||
</button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MoreDirectChannels.propTypes = {
|
||||
show: React.PropTypes.bool.isRequired,
|
||||
onModalDismissed: React.PropTypes.func
|
||||
};
|
||||
|
||||
@@ -14,6 +14,9 @@ var Constants = require('../utils/constants.jsx');
|
||||
var ActionTypes = Constants.ActionTypes;
|
||||
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||
|
||||
var Popover = ReactBootstrap.Popover;
|
||||
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
|
||||
|
||||
export default class Navbar extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -36,12 +39,6 @@ export default class Navbar extends React.Component {
|
||||
ChannelStore.addChangeListener(this.onChange);
|
||||
ChannelStore.addExtraInfoChangeListener(this.onChange);
|
||||
$('.inner__wrap').click(this.hideSidebars);
|
||||
|
||||
$('body').on('click.infopopover', function handlePopoverClick(e) {
|
||||
if ($(e.target).attr('data-toggle') !== 'popover' && $(e.target).parents('.popover.in').length === 0) {
|
||||
$('.info-popover').popover('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
componentWillUnmount() {
|
||||
ChannelStore.removeChangeListener(this.onChange);
|
||||
@@ -224,11 +221,15 @@ export default class Navbar extends React.Component {
|
||||
return (
|
||||
<div className='navbar-brand'>
|
||||
<div className='dropdown'>
|
||||
<div
|
||||
data-toggle='popover'
|
||||
data-content={popoverContent}
|
||||
className='description info-popover'
|
||||
/>
|
||||
<OverlayTrigger
|
||||
trigger='click'
|
||||
placement='bottom'
|
||||
overlay={popoverContent}
|
||||
className='description'
|
||||
rootClose={true}
|
||||
>
|
||||
<div className='description info-popover'/>
|
||||
</OverlayTrigger>
|
||||
<a
|
||||
href='#'
|
||||
className='dropdown-toggle theme'
|
||||
@@ -330,11 +331,17 @@ export default class Navbar extends React.Component {
|
||||
var isDirect = false;
|
||||
|
||||
if (channel) {
|
||||
popoverContent = React.renderToString(
|
||||
<MessageWrapper
|
||||
message={channel.description}
|
||||
options={{singleline: true, mentionHighlight: false}}
|
||||
/>
|
||||
popoverContent = (
|
||||
<Popover
|
||||
bsStyle='info'
|
||||
placement='bottom'
|
||||
id='description-popover'
|
||||
>
|
||||
<MessageWrapper
|
||||
message={channel.description}
|
||||
options={{singleline: true, mentionHighlight: false}}
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
isAdmin = Utils.isAdmin(this.state.member.roles);
|
||||
|
||||
@@ -354,19 +361,28 @@ export default class Navbar extends React.Component {
|
||||
}
|
||||
|
||||
if (channel.description.length === 0) {
|
||||
popoverContent = React.renderToString(
|
||||
<div>
|
||||
No channel description yet. <br/>
|
||||
<a
|
||||
href='#'
|
||||
data-toggle='modal'
|
||||
data-desc={channel.description}
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
data-target='#edit_channel'
|
||||
>
|
||||
Click here
|
||||
</a> to add one.</div>
|
||||
popoverContent = (
|
||||
<Popover
|
||||
bsStyle='info'
|
||||
placement='bottom'
|
||||
id='description-popover'
|
||||
>
|
||||
<div>
|
||||
{'No channel description yet.'}
|
||||
<br/>
|
||||
<a
|
||||
href='#'
|
||||
data-toggle='modal'
|
||||
data-desc={channel.description}
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
data-target='#edit_channel'
|
||||
>
|
||||
{'Click here'}
|
||||
</a>
|
||||
{' to add one.'}
|
||||
</div>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export default class NavbarDropdown extends React.Component {
|
||||
UserStore.addTeamsChangeListener(this.onListenerChange);
|
||||
TeamStore.addChangeListener(this.onListenerChange);
|
||||
|
||||
$(React.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', () => {
|
||||
$(ReactDOM.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', () => {
|
||||
this.blockToggle = true;
|
||||
setTimeout(() => {
|
||||
this.blockToggle = false;
|
||||
@@ -51,7 +51,7 @@ export default class NavbarDropdown extends React.Component {
|
||||
UserStore.removeTeamsChangeListener(this.onListenerChange);
|
||||
TeamStore.removeChangeListener(this.onListenerChange);
|
||||
|
||||
$(React.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown');
|
||||
$(ReactDOM.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown');
|
||||
}
|
||||
onListenerChange() {
|
||||
var newState = getStateFromStores();
|
||||
|
||||
@@ -25,7 +25,7 @@ export default class NewChannelModal extends React.Component {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const displayName = React.findDOMNode(this.refs.display_name).value.trim();
|
||||
const displayName = ReactDOM.findDOMNode(this.refs.display_name).value.trim();
|
||||
if (displayName.length < 1) {
|
||||
this.setState({displayNameError: 'This field is required'});
|
||||
return;
|
||||
@@ -35,8 +35,8 @@ export default class NewChannelModal extends React.Component {
|
||||
}
|
||||
handleChange() {
|
||||
const newData = {
|
||||
displayName: React.findDOMNode(this.refs.display_name).value,
|
||||
description: React.findDOMNode(this.refs.channel_desc).value
|
||||
displayName: ReactDOM.findDOMNode(this.refs.display_name).value,
|
||||
description: ReactDOM.findDOMNode(this.refs.channel_desc).value
|
||||
};
|
||||
this.props.onDataChanged(newData);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export default class PasswordResetForm extends React.Component {
|
||||
e.preventDefault();
|
||||
var state = {};
|
||||
|
||||
var password = React.findDOMNode(this.refs.password).value.trim();
|
||||
var password = ReactDOM.findDOMNode(this.refs.password).value.trim();
|
||||
if (!password || password.length < 5) {
|
||||
state.error = 'Please enter at least 5 characters.';
|
||||
this.setState(state);
|
||||
|
||||
@@ -16,7 +16,7 @@ export default class PasswordResetSendLink extends React.Component {
|
||||
e.preventDefault();
|
||||
var state = {};
|
||||
|
||||
var email = React.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
var email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
if (!email || !Utils.isEmail(email)) {
|
||||
state.error = 'Please enter a valid email address.';
|
||||
this.setState(state);
|
||||
@@ -33,7 +33,7 @@ export default class PasswordResetSendLink extends React.Component {
|
||||
client.sendPasswordReset(data,
|
||||
function passwordResetSent() {
|
||||
this.setState({error: null, updateText: <p>A password reset link has been sent to <b>{email}</b> for your <b>{this.props.teamDisplayName}</b> team on {window.location.hostname}.</p>, moreUpdateText: 'Please check your inbox.'});
|
||||
$(React.findDOMNode(this.refs.reset_form)).hide();
|
||||
$(ReactDOM.findDOMNode(this.refs.reset_form)).hide();
|
||||
}.bind(this),
|
||||
function passwordResetFailedToSend(err) {
|
||||
this.setState({error: err.message, update_text: null, moreUpdateText: null});
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// See License.txt for license information.
|
||||
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
var Popover = ReactBootstrap.Popover;
|
||||
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
|
||||
|
||||
export default class PopoverListMembers extends React.Component {
|
||||
componentDidMount() {
|
||||
@@ -24,16 +26,9 @@ export default class PopoverListMembers extends React.Component {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$('#member_popover').popover({placement: 'bottom', trigger: 'click', html: true});
|
||||
$('body').on('click', function onClick(e) {
|
||||
if (e.target.parentNode && $(e.target.parentNode.parentNode)[0] !== $('#member_popover')[0] && $(e.target).parents('.popover.in').length === 0) {
|
||||
$('#member_popover').popover('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
render() {
|
||||
let popoverHtml = '';
|
||||
let popoverHtml = [];
|
||||
let count = 0;
|
||||
let countText = '-';
|
||||
const members = this.props.members;
|
||||
@@ -46,7 +41,7 @@ export default class PopoverListMembers extends React.Component {
|
||||
|
||||
members.forEach(function addMemberElement(m) {
|
||||
if (teamMembers[m.username] && teamMembers[m.username].delete_at <= 0) {
|
||||
popoverHtml += `<div class='text--nowrap'>${m.username}</div>`;
|
||||
popoverHtml.push(<div className='text--nowrap'>{m.username}</div>);
|
||||
count++;
|
||||
}
|
||||
});
|
||||
@@ -59,15 +54,14 @@ export default class PopoverListMembers extends React.Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
id='member_popover'
|
||||
data-toggle='popover'
|
||||
data-content={popoverHtml}
|
||||
data-original-title='Members'
|
||||
<OverlayTrigger
|
||||
trigger='click'
|
||||
placement='bottom'
|
||||
rootClose='true'
|
||||
overlay={<Popover title='Members'>{popoverHtml}</Popover>}
|
||||
>
|
||||
<div
|
||||
id='member_tooltip'
|
||||
>
|
||||
<div id='member_popover'>
|
||||
<div>
|
||||
{countText}
|
||||
<span
|
||||
className='fa fa-user'
|
||||
@@ -75,6 +69,7 @@ export default class PopoverListMembers extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ export default class PostBody extends React.Component {
|
||||
}
|
||||
|
||||
parseEmojis() {
|
||||
twemoji.parse(React.findDOMNode(this), {size: Constants.EMOJI_SIZE});
|
||||
twemoji.parse(ReactDOM.findDOMNode(this), {size: Constants.EMOJI_SIZE});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
@@ -15,7 +15,7 @@ export default class PostDeletedModal extends React.Component {
|
||||
this.state = {};
|
||||
}
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', () => {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', () => {
|
||||
this.handleClose();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export default class PostList extends React.Component {
|
||||
PreferenceStore.addChangeListener(this.onTimeChange);
|
||||
SocketStore.addChangeListener(this.onSocketChange);
|
||||
|
||||
const postHolder = $(React.findDOMNode(this.refs.postlist));
|
||||
const postHolder = $(ReactDOM.findDOMNode(this.refs.postlist));
|
||||
|
||||
$(window).resize(() => {
|
||||
this.resize();
|
||||
@@ -135,7 +135,7 @@ export default class PostList extends React.Component {
|
||||
|
||||
$('.top-visible-post').removeClass('top-visible-post');
|
||||
|
||||
$(React.findDOMNode(this.refs.postlistcontent)).children().each(function select() {
|
||||
$(ReactDOM.findDOMNode(this.refs.postlistcontent)).children().each(function select() {
|
||||
if ($(this).position().top + $(this).height() / 2 > 0) {
|
||||
$(this).addClass('top-visible-post');
|
||||
return false;
|
||||
@@ -161,7 +161,7 @@ export default class PostList extends React.Component {
|
||||
PreferenceStore.removeChangeListener(this.onTimeChange);
|
||||
$('body').off('click.userpopover');
|
||||
$(window).off('resize');
|
||||
var postHolder = $(React.findDOMNode(this.refs.postlist));
|
||||
var postHolder = $(ReactDOM.findDOMNode(this.refs.postlist));
|
||||
postHolder.off('scroll');
|
||||
}
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
@@ -217,7 +217,7 @@ export default class PostList extends React.Component {
|
||||
}
|
||||
}
|
||||
componentWillUpdate() {
|
||||
var postHolder = $(React.findDOMNode(this.refs.postlist));
|
||||
var postHolder = $(ReactDOM.findDOMNode(this.refs.postlist));
|
||||
this.prevScrollTop = postHolder.scrollTop();
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
@@ -228,7 +228,7 @@ export default class PostList extends React.Component {
|
||||
}
|
||||
}
|
||||
resize() {
|
||||
const postHolder = $(React.findDOMNode(this.refs.postlist));
|
||||
const postHolder = $(ReactDOM.findDOMNode(this.refs.postlist));
|
||||
if ($('#create_post').length > 0) {
|
||||
const height = $(window).height() - $('#create_post').height() - $('#error_bar').outerHeight() - 50;
|
||||
postHolder.css('height', height + 'px');
|
||||
@@ -236,12 +236,12 @@ export default class PostList extends React.Component {
|
||||
}
|
||||
scrollTo(val) {
|
||||
this.isUserScroll = false;
|
||||
var postHolder = $(React.findDOMNode(this.refs.postlist));
|
||||
var postHolder = $(ReactDOM.findDOMNode(this.refs.postlist));
|
||||
postHolder[0].scrollTop = val;
|
||||
}
|
||||
scrollToBottom(force) {
|
||||
this.isUserScroll = false;
|
||||
var postHolder = $(React.findDOMNode(this.refs.postlist));
|
||||
var postHolder = $(ReactDOM.findDOMNode(this.refs.postlist));
|
||||
if ($('#new_message_' + this.props.channelId)[0] && !this.userHasSeenNew && !force) {
|
||||
$('#new_message_' + this.props.channelId)[0].scrollIntoView();
|
||||
} else {
|
||||
@@ -599,14 +599,14 @@ export default class PostList extends React.Component {
|
||||
var order = this.state.postList.order;
|
||||
var channelId = this.props.channelId;
|
||||
|
||||
$(React.findDOMNode(this.refs.loadmore)).text('Retrieving more messages...');
|
||||
$(ReactDOM.findDOMNode(this.refs.loadmore)).text('Retrieving more messages...');
|
||||
|
||||
Client.getPostsPage(
|
||||
channelId,
|
||||
order.length,
|
||||
Constants.POST_CHUNK_SIZE,
|
||||
function success(data) {
|
||||
$(React.findDOMNode(this.refs.loadmore)).text('Load more messages');
|
||||
$(ReactDOM.findDOMNode(this.refs.loadmore)).text('Load more messages');
|
||||
this.gotMorePosts = true;
|
||||
this.setState({numToDisplay: this.state.numToDisplay + Constants.POST_CHUNK_SIZE});
|
||||
|
||||
@@ -631,7 +631,7 @@ export default class PostList extends React.Component {
|
||||
Client.getProfiles();
|
||||
}.bind(this),
|
||||
function fail(err) {
|
||||
$(React.findDOMNode(this.refs.loadmore)).text('Load more messages');
|
||||
$(ReactDOM.findDOMNode(this.refs.loadmore)).text('Load more messages');
|
||||
AsyncClient.dispatchError(err, 'getPosts');
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
@@ -14,7 +14,7 @@ export default class RegisterAppModal extends React.Component {
|
||||
this.state = {clientId: '', clientSecret: '', saved: false};
|
||||
}
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this)).on('hide.bs.modal', this.onHide);
|
||||
$(ReactDOM.findDOMNode(this)).on('hide.bs.modal', this.onHide);
|
||||
}
|
||||
register() {
|
||||
var state = this.state;
|
||||
@@ -22,7 +22,7 @@ export default class RegisterAppModal extends React.Component {
|
||||
|
||||
var app = {};
|
||||
|
||||
var name = this.refs.name.getDOMNode().value;
|
||||
var name = this.refs.name.value;
|
||||
if (!name || name.length === 0) {
|
||||
state.nameError = 'Application name must be filled in.';
|
||||
this.setState(state);
|
||||
@@ -31,7 +31,7 @@ export default class RegisterAppModal extends React.Component {
|
||||
state.nameError = null;
|
||||
app.name = name;
|
||||
|
||||
var homepage = this.refs.homepage.getDOMNode().value;
|
||||
var homepage = this.refs.homepage.value;
|
||||
if (!homepage || homepage.length === 0) {
|
||||
state.homepageError = 'Homepage must be filled in.';
|
||||
this.setState(state);
|
||||
@@ -40,10 +40,10 @@ export default class RegisterAppModal extends React.Component {
|
||||
state.homepageError = null;
|
||||
app.homepage = homepage;
|
||||
|
||||
var desc = this.refs.desc.getDOMNode().value;
|
||||
var desc = this.refs.desc.value;
|
||||
app.description = desc;
|
||||
|
||||
var rawCallbacks = this.refs.callback.getDOMNode().value.trim();
|
||||
var rawCallbacks = this.refs.callback.value.trim();
|
||||
if (!rawCallbacks || rawCallbacks.length === 0) {
|
||||
state.callbackError = 'At least one callback URL must be filled in.';
|
||||
this.setState(state);
|
||||
@@ -73,7 +73,7 @@ export default class RegisterAppModal extends React.Component {
|
||||
this.setState({clientId: '', clientSecret: '', saved: false});
|
||||
}
|
||||
save() {
|
||||
this.setState({saved: this.refs.save.getDOMNode().checked});
|
||||
this.setState({saved: this.refs.save.checked});
|
||||
}
|
||||
render() {
|
||||
var nameError;
|
||||
|
||||
@@ -37,13 +37,13 @@ export default class RemovedFromChannelModal extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this)).on('show.bs.modal', this.handleShow);
|
||||
$(React.findDOMNode(this)).on('hidden.bs.modal', this.handleClose);
|
||||
$(ReactDOM.findDOMNode(this)).on('show.bs.modal', this.handleShow);
|
||||
$(ReactDOM.findDOMNode(this)).on('hidden.bs.modal', this.handleClose);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
$(React.findDOMNode(this)).off('show.bs.modal', this.handleShow);
|
||||
$(React.findDOMNode(this)).off('hidden.bs.modal', this.handleClose);
|
||||
$(ReactDOM.findDOMNode(this)).off('show.bs.modal', this.handleShow);
|
||||
$(ReactDOM.findDOMNode(this)).off('hidden.bs.modal', this.handleClose);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -76,13 +76,13 @@ export default class RenameChannelModal extends React.Component {
|
||||
|
||||
Client.updateChannel(channel,
|
||||
function handleUpdateSuccess() {
|
||||
$(React.findDOMNode(this.refs.modal)).modal('hide');
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide');
|
||||
|
||||
AsyncClient.getChannel(channel.id);
|
||||
Utils.updateAddressBar(channel.name);
|
||||
|
||||
React.findDOMNode(this.refs.displayName).value = '';
|
||||
React.findDOMNode(this.refs.channelName).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.displayName).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.channelName).value = '';
|
||||
}.bind(this),
|
||||
function handleUpdateError(err) {
|
||||
state.serverError = err.message;
|
||||
@@ -92,15 +92,15 @@ export default class RenameChannelModal extends React.Component {
|
||||
);
|
||||
}
|
||||
onNameChange() {
|
||||
this.setState({channelName: React.findDOMNode(this.refs.channelName).value});
|
||||
this.setState({channelName: ReactDOM.findDOMNode(this.refs.channelName).value});
|
||||
}
|
||||
onDisplayNameChange() {
|
||||
this.setState({displayName: React.findDOMNode(this.refs.displayName).value});
|
||||
this.setState({displayName: ReactDOM.findDOMNode(this.refs.displayName).value});
|
||||
}
|
||||
displayNameKeyUp() {
|
||||
const displayName = React.findDOMNode(this.refs.displayName).value.trim();
|
||||
const displayName = ReactDOM.findDOMNode(this.refs.displayName).value.trim();
|
||||
const channelName = Utils.cleanUpUrlable(displayName);
|
||||
React.findDOMNode(this.refs.channelName).value = channelName;
|
||||
ReactDOM.findDOMNode(this.refs.channelName).value = channelName;
|
||||
this.setState({channelName: channelName});
|
||||
}
|
||||
handleClose() {
|
||||
@@ -119,11 +119,11 @@ export default class RenameChannelModal extends React.Component {
|
||||
this.setState({displayName: button.attr('data-display'), channelName: button.attr('data-name'), channelId: button.attr('data-channelid')});
|
||||
}
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.handleShow);
|
||||
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.handleClose);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.handleShow);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.handleClose);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
$(React.findDOMNode(this.refs.modal)).off('hidden.bs.modal', this.handleClose);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).off('hidden.bs.modal', this.handleClose);
|
||||
}
|
||||
render() {
|
||||
let displayNameError = null;
|
||||
|
||||
@@ -55,7 +55,7 @@ export default class RhsComment extends React.Component {
|
||||
this.forceUpdate();
|
||||
}
|
||||
parseEmojis() {
|
||||
twemoji.parse(React.findDOMNode(this), {size: Constants.EMOJI_SIZE});
|
||||
twemoji.parse(ReactDOM.findDOMNode(this), {size: Constants.EMOJI_SIZE});
|
||||
}
|
||||
componentDidMount() {
|
||||
this.parseEmojis();
|
||||
|
||||
@@ -19,7 +19,7 @@ export default class RhsRootPost extends React.Component {
|
||||
this.state = {};
|
||||
}
|
||||
parseEmojis() {
|
||||
twemoji.parse(React.findDOMNode(this), {size: Constants.EMOJI_SIZE});
|
||||
twemoji.parse(ReactDOM.findDOMNode(this), {size: Constants.EMOJI_SIZE});
|
||||
}
|
||||
componentDidMount() {
|
||||
this.parseEmojis();
|
||||
|
||||
@@ -55,8 +55,6 @@ export default class RhsThread extends React.Component {
|
||||
if ($('.post-right__scroll')[0]) {
|
||||
$('.post-right__scroll').scrollTop($('.post-right__scroll')[0].scrollHeight);
|
||||
}
|
||||
|
||||
$('.post-right__scroll').perfectScrollbar('update');
|
||||
this.resize();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
@@ -113,8 +111,10 @@ export default class RhsThread extends React.Component {
|
||||
var height = $(window).height() - $('#error_bar').outerHeight() - 100;
|
||||
$('.post-right__scroll').css('height', height + 'px');
|
||||
$('.post-right__scroll').scrollTop(100000);
|
||||
$('.post-right__scroll').perfectScrollbar();
|
||||
$('.post-right__scroll').perfectScrollbar('update');
|
||||
if ($(window).width() > 768) {
|
||||
$('.post-right__scroll').perfectScrollbar();
|
||||
$('.post-right__scroll').perfectScrollbar('update');
|
||||
}
|
||||
}
|
||||
render() {
|
||||
var postList = this.state.postList;
|
||||
|
||||
@@ -90,7 +90,7 @@ export default class SearchBar extends React.Component {
|
||||
function success(data) {
|
||||
this.setState({isSearching: false});
|
||||
if (utils.isMobile()) {
|
||||
React.findDOMNode(this.refs.search).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.search).value = '';
|
||||
}
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
|
||||
@@ -56,7 +56,9 @@ export default class SearchResults extends React.Component {
|
||||
var height = $(window).height() - $('#error_bar').outerHeight() - 100;
|
||||
$('#search-items-container').css('height', height + 'px');
|
||||
$('#search-items-container').scrollTop(0);
|
||||
$('#search-items-container').perfectScrollbar();
|
||||
if ($(window).width() > 768) {
|
||||
$('#search-items-container').perfectScrollbar();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -12,7 +12,7 @@ export default class SettingPicture extends React.Component {
|
||||
if (file) {
|
||||
var reader = new FileReader();
|
||||
|
||||
var img = React.findDOMNode(this.refs.image);
|
||||
var img = ReactDOM.findDOMNode(this.refs.image);
|
||||
reader.onload = function load(e) {
|
||||
$(img).attr('src', e.target.result);
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ export default class SettingsUpload extends React.Component {
|
||||
|
||||
doSubmit(e) {
|
||||
e.preventDefault();
|
||||
var inputnode = React.findDOMNode(this.refs.uploadinput);
|
||||
var inputnode = ReactDOM.findDOMNode(this.refs.uploadinput);
|
||||
if (inputnode.files && inputnode.files[0]) {
|
||||
this.props.submit(inputnode.files[0]);
|
||||
} else {
|
||||
|
||||
@@ -8,6 +8,7 @@ const Client = require('../utils/client.jsx');
|
||||
const Constants = require('../utils/constants.jsx');
|
||||
const PreferenceStore = require('../stores/preference_store.jsx');
|
||||
const NewChannelFlow = require('./new_channel_flow.jsx');
|
||||
const MoreDirectChannels = require('./more_direct_channels.jsx');
|
||||
const SearchBox = require('./search_bar.jsx');
|
||||
const SidebarHeader = require('./sidebar_header.jsx');
|
||||
const SocketStore = require('../stores/socket_store.jsx');
|
||||
@@ -33,12 +34,19 @@ export default class Sidebar extends React.Component {
|
||||
this.onResize = this.onResize.bind(this);
|
||||
this.updateUnreadIndicators = this.updateUnreadIndicators.bind(this);
|
||||
this.handleLeaveDirectChannel = this.handleLeaveDirectChannel.bind(this);
|
||||
|
||||
this.showNewChannelModal = this.showNewChannelModal.bind(this);
|
||||
this.hideNewChannelModal = this.hideNewChannelModal.bind(this);
|
||||
this.showMoreDirectChannelsModal = this.showMoreDirectChannelsModal.bind(this);
|
||||
this.hideMoreDirectChannelsModal = this.hideMoreDirectChannelsModal.bind(this);
|
||||
|
||||
this.createChannelElement = this.createChannelElement.bind(this);
|
||||
|
||||
this.isLeaving = new Map();
|
||||
|
||||
const state = this.getStateFromStores();
|
||||
state.modal = '';
|
||||
state.newChannelModalType = '';
|
||||
state.showMoreDirectChannelsModal = false;
|
||||
state.loadingDMChannel = -1;
|
||||
|
||||
this.state = state;
|
||||
@@ -47,10 +55,11 @@ export default class Sidebar extends React.Component {
|
||||
const members = ChannelStore.getAllMembers();
|
||||
var teamMemberMap = UserStore.getActiveOnlyProfiles();
|
||||
var currentId = ChannelStore.getCurrentId();
|
||||
const currentUserId = UserStore.getCurrentId();
|
||||
|
||||
var teammates = [];
|
||||
for (var id in teamMemberMap) {
|
||||
if (id === UserStore.getCurrentId()) {
|
||||
if (id === currentUserId) {
|
||||
continue;
|
||||
}
|
||||
teammates.push(teamMemberMap[id]);
|
||||
@@ -58,22 +67,16 @@ export default class Sidebar extends React.Component {
|
||||
|
||||
const preferences = PreferenceStore.getPreferences(Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW);
|
||||
|
||||
// Create lists of all read and unread direct channels
|
||||
var visibleDirectChannels = [];
|
||||
var hiddenDirectChannels = [];
|
||||
var hiddenDirectChannelCount = 0;
|
||||
for (var i = 0; i < teammates.length; i++) {
|
||||
const teammate = teammates[i];
|
||||
|
||||
if (teammate.id === UserStore.getCurrentId()) {
|
||||
if (teammate.id === currentUserId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var channelName = '';
|
||||
if (teammate.id > UserStore.getCurrentId()) {
|
||||
channelName = UserStore.getCurrentId() + '__' + teammate.id;
|
||||
} else {
|
||||
channelName = teammate.id + '__' + UserStore.getCurrentId();
|
||||
}
|
||||
const channelName = Utils.getDirectChannelName(currentUserId, teammate.id);
|
||||
|
||||
let forceShow = false;
|
||||
let channel = ChannelStore.getByName(channelName);
|
||||
@@ -106,19 +109,18 @@ export default class Sidebar extends React.Component {
|
||||
|
||||
visibleDirectChannels.push(channel);
|
||||
} else {
|
||||
hiddenDirectChannels.push(channel);
|
||||
hiddenDirectChannelCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
visibleDirectChannels.sort(this.sortChannelsByDisplayName);
|
||||
hiddenDirectChannels.sort(this.sortChannelsByDisplayName);
|
||||
|
||||
return {
|
||||
activeId: currentId,
|
||||
channels: ChannelStore.getAll(),
|
||||
members,
|
||||
visibleDirectChannels,
|
||||
hiddenDirectChannels
|
||||
hiddenDirectChannelCount
|
||||
};
|
||||
}
|
||||
|
||||
@@ -132,7 +134,9 @@ export default class Sidebar extends React.Component {
|
||||
|
||||
AsyncClient.getDirectChannelPreferences();
|
||||
|
||||
$('.nav-pills__container').perfectScrollbar();
|
||||
if ($(window).width() > 768) {
|
||||
$('.nav-pills__container').perfectScrollbar();
|
||||
}
|
||||
|
||||
this.updateTitle();
|
||||
this.updateUnreadIndicators();
|
||||
@@ -280,13 +284,13 @@ export default class Sidebar extends React.Component {
|
||||
this.updateUnreadIndicators();
|
||||
}
|
||||
updateUnreadIndicators() {
|
||||
const container = $(React.findDOMNode(this.refs.container));
|
||||
const container = $(ReactDOM.findDOMNode(this.refs.container));
|
||||
|
||||
var showTopUnread = false;
|
||||
var showBottomUnread = false;
|
||||
|
||||
if (this.firstUnreadChannel) {
|
||||
var firstUnreadElement = $(React.findDOMNode(this.refs[this.firstUnreadChannel]));
|
||||
var firstUnreadElement = $(ReactDOM.findDOMNode(this.refs[this.firstUnreadChannel]));
|
||||
|
||||
if (firstUnreadElement.position().top + firstUnreadElement.height() < 0) {
|
||||
showTopUnread = true;
|
||||
@@ -294,7 +298,7 @@ export default class Sidebar extends React.Component {
|
||||
}
|
||||
|
||||
if (this.lastUnreadChannel) {
|
||||
var lastUnreadElement = $(React.findDOMNode(this.refs[this.lastUnreadChannel]));
|
||||
var lastUnreadElement = $(ReactDOM.findDOMNode(this.refs[this.lastUnreadChannel]));
|
||||
|
||||
if (lastUnreadElement.position().top > container.height()) {
|
||||
showBottomUnread = true;
|
||||
@@ -336,6 +340,20 @@ export default class Sidebar extends React.Component {
|
||||
return a.display_name.localeCompare(b.display_name);
|
||||
}
|
||||
|
||||
showNewChannelModal(type) {
|
||||
this.setState({newChannelModalType: type});
|
||||
}
|
||||
hideNewChannelModal() {
|
||||
this.setState({newChannelModalType: ''});
|
||||
}
|
||||
|
||||
showMoreDirectChannelsModal() {
|
||||
this.setState({showDirectChannelsModal: true});
|
||||
}
|
||||
hideMoreDirectChannelsModal() {
|
||||
this.setState({showDirectChannelsModal: false});
|
||||
}
|
||||
|
||||
createChannelElement(channel, index, arr, handleClose) {
|
||||
var members = this.state.members;
|
||||
var activeId = this.state.activeId;
|
||||
@@ -532,25 +550,21 @@ export default class Sidebar extends React.Component {
|
||||
head.appendChild(link);
|
||||
|
||||
var directMessageMore = null;
|
||||
if (this.state.hiddenDirectChannels.length > 0) {
|
||||
if (this.state.hiddenDirectChannelCount > 0) {
|
||||
directMessageMore = (
|
||||
<li key='more'>
|
||||
<a
|
||||
key={`more${this.state.hiddenDirectChannels.length}`}
|
||||
href='#'
|
||||
data-toggle='modal'
|
||||
className='nav-more'
|
||||
data-target='#more_direct_channels'
|
||||
data-channels={JSON.stringify(this.state.hiddenDirectChannels)}
|
||||
onClick={this.showMoreDirectChannelsModal}
|
||||
>
|
||||
{'More (' + this.state.hiddenDirectChannels.length + ')'}
|
||||
{'More (' + this.state.hiddenDirectChannelCount + ')'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
let showChannelModal = false;
|
||||
if (this.state.modal !== '') {
|
||||
if (this.state.newChannelModalType !== '') {
|
||||
showChannelModal = true;
|
||||
}
|
||||
|
||||
@@ -561,9 +575,14 @@ export default class Sidebar extends React.Component {
|
||||
<div>
|
||||
<NewChannelFlow
|
||||
show={showChannelModal}
|
||||
channelType={this.state.modal}
|
||||
onModalDismissed={() => this.setState({modal: ''})}
|
||||
channelType={this.state.newChannelModalType}
|
||||
onModalDismissed={this.hideNewChannelModal}
|
||||
/>
|
||||
<MoreDirectChannels
|
||||
show={this.state.showDirectChannelsModal}
|
||||
onModalDismissed={this.hideMoreDirectChannelsModal}
|
||||
/>
|
||||
|
||||
<SidebarHeader
|
||||
teamDisplayName={this.props.teamDisplayName}
|
||||
teamName={this.props.teamName}
|
||||
@@ -599,7 +618,7 @@ export default class Sidebar extends React.Component {
|
||||
<a
|
||||
className='add-channel-btn'
|
||||
href='#'
|
||||
onClick={() => this.setState({modal: 'O'})}
|
||||
onClick={this.showNewChannelModal.bind(this, 'O')}
|
||||
>
|
||||
{'+'}
|
||||
</a>
|
||||
@@ -632,7 +651,7 @@ export default class Sidebar extends React.Component {
|
||||
<a
|
||||
className='add-channel-btn'
|
||||
href='#'
|
||||
onClick={() => this.setState({modal: 'P'})}
|
||||
onClick={this.showNewChannelModal.bind(this, 'P')}
|
||||
>
|
||||
{'+'}
|
||||
</a>
|
||||
|
||||
@@ -28,7 +28,7 @@ export default class SignupUserComplete extends React.Component {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const providedEmail = React.findDOMNode(this.refs.email).value.trim();
|
||||
const providedEmail = ReactDOM.findDOMNode(this.refs.email).value.trim();
|
||||
if (!providedEmail) {
|
||||
this.setState({nameError: '', emailError: 'This field is required', passwordError: ''});
|
||||
return;
|
||||
@@ -39,7 +39,7 @@ export default class SignupUserComplete extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
const providedUsername = React.findDOMNode(this.refs.name).value.trim().toLowerCase();
|
||||
const providedUsername = ReactDOM.findDOMNode(this.refs.name).value.trim().toLowerCase();
|
||||
if (!providedUsername) {
|
||||
this.setState({nameError: 'This field is required', emailError: '', passwordError: '', serverError: ''});
|
||||
return;
|
||||
@@ -59,7 +59,7 @@ export default class SignupUserComplete extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
const providedPassword = React.findDOMNode(this.refs.password).value.trim();
|
||||
const providedPassword = ReactDOM.findDOMNode(this.refs.password).value.trim();
|
||||
if (!providedPassword || providedPassword.length < 5) {
|
||||
this.setState({nameError: '', emailError: '', passwordError: 'Please enter at least 5 characters', serverError: ''});
|
||||
return;
|
||||
|
||||
@@ -44,11 +44,11 @@ export default class TeamMembers extends React.Component {
|
||||
UserStore.addChangeListener(this.onChange);
|
||||
|
||||
var self = this;
|
||||
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function show() {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function show() {
|
||||
self.setState({render_members: false});
|
||||
});
|
||||
|
||||
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function hide() {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', function hide() {
|
||||
self.setState({render_members: true});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export default class TeamSignupDisplayNamePage extends React.Component {
|
||||
submitNext(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var displayName = React.findDOMNode(this.refs.name).value.trim();
|
||||
var displayName = ReactDOM.findDOMNode(this.refs.name).value.trim();
|
||||
if (!displayName) {
|
||||
this.setState({nameError: 'This field is required'});
|
||||
return;
|
||||
|
||||
@@ -13,10 +13,10 @@ export default class TeamSignupEmailItem extends React.Component {
|
||||
this.state = {};
|
||||
}
|
||||
getValue() {
|
||||
return React.findDOMNode(this.refs.email).value.trim();
|
||||
return ReactDOM.findDOMNode(this.refs.email).value.trim();
|
||||
}
|
||||
validate(teamEmail) {
|
||||
const email = React.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
const email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
|
||||
if (!email) {
|
||||
return true;
|
||||
|
||||
@@ -22,7 +22,7 @@ export default class TeamSignupPasswordPage extends React.Component {
|
||||
submitNext(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var password = React.findDOMNode(this.refs.password).value.trim();
|
||||
var password = ReactDOM.findDOMNode(this.refs.password).value.trim();
|
||||
if (!password || password.length < 5) {
|
||||
this.setState({passwordError: 'Please enter at least 5 characters'});
|
||||
return;
|
||||
|
||||
@@ -23,7 +23,7 @@ export default class TeamSignupUrlPage extends React.Component {
|
||||
submitNext(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const name = React.findDOMNode(this.refs.name).value.trim();
|
||||
const name = ReactDOM.findDOMNode(this.refs.name).value.trim();
|
||||
if (!name) {
|
||||
this.setState({nameError: 'This field is required'});
|
||||
return;
|
||||
|
||||
@@ -21,7 +21,7 @@ export default class TeamSignupUsernamePage extends React.Component {
|
||||
submitNext(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var name = React.findDOMNode(this.refs.name).value.trim().toLowerCase();
|
||||
var name = ReactDOM.findDOMNode(this.refs.name).value.trim().toLowerCase();
|
||||
|
||||
var usernameError = Utils.isValidUsername(name);
|
||||
if (usernameError === 'Cannot use a reserved word as a username.') {
|
||||
|
||||
@@ -36,7 +36,7 @@ export default class TeamSignupWelcomePage extends React.Component {
|
||||
|
||||
var state = {useDiff: true, serverError: ''};
|
||||
|
||||
var email = React.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
var email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
if (!email || !Utils.isEmail(email)) {
|
||||
state.emailError = 'Please enter a valid email address';
|
||||
this.setState(state);
|
||||
|
||||
@@ -17,7 +17,7 @@ export default class EmailSignUpPage extends React.Component {
|
||||
var team = {};
|
||||
var state = {serverError: ''};
|
||||
|
||||
team.email = React.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
team.email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||
if (!team.email || !Utils.isEmail(team.email)) {
|
||||
state.emailError = 'Please enter a valid email address';
|
||||
state.inValid = true;
|
||||
|
||||
@@ -54,7 +54,7 @@ export default class SSOSignUpPage extends React.Component {
|
||||
);
|
||||
}
|
||||
nameChange() {
|
||||
this.setState({name: React.findDOMNode(this.refs.teamname).value.trim()});
|
||||
this.setState({name: ReactDOM.findDOMNode(this.refs.teamname).value.trim()});
|
||||
}
|
||||
render() {
|
||||
var nameError = null;
|
||||
|
||||
@@ -9,6 +9,7 @@ const ErrorStore = require('../stores/error_store.jsx');
|
||||
const Utils = require('../utils/utils.jsx');
|
||||
const Constants = require('../utils/constants.jsx');
|
||||
const ActionTypes = Constants.ActionTypes;
|
||||
const KeyCodes = Constants.KeyCodes;
|
||||
|
||||
export default class Textbox extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -83,7 +84,7 @@ export default class Textbox extends React.Component {
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.caret >= 0) {
|
||||
Utils.setCaretPosition(React.findDOMNode(this.refs.message), this.caret);
|
||||
Utils.setCaretPosition(ReactDOM.findDOMNode(this.refs.message), this.caret);
|
||||
this.caret = -1;
|
||||
}
|
||||
if (this.doProcessMentions) {
|
||||
@@ -97,7 +98,7 @@ export default class Textbox extends React.Component {
|
||||
if (!this.addedMention) {
|
||||
this.checkForNewMention(nextProps.messageText);
|
||||
}
|
||||
const text = React.findDOMNode(this.refs.message).value;
|
||||
const text = ReactDOM.findDOMNode(this.refs.message).value;
|
||||
if (nextProps.channelId !== this.props.channelId || nextProps.messageText !== text) {
|
||||
this.doProcessMentions = true;
|
||||
}
|
||||
@@ -117,11 +118,11 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
|
||||
handleChange() {
|
||||
this.props.onUserInput(React.findDOMNode(this.refs.message).value);
|
||||
this.props.onUserInput(ReactDOM.findDOMNode(this.refs.message).value);
|
||||
}
|
||||
|
||||
handleKeyPress(e) {
|
||||
const text = React.findDOMNode(this.refs.message).value;
|
||||
const text = ReactDOM.findDOMNode(this.refs.message).value;
|
||||
|
||||
if (!this.refs.commands.isEmpty() && text.indexOf('/') === 0 && e.which === 13) {
|
||||
this.refs.commands.addFirstCommand();
|
||||
@@ -130,7 +131,7 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
|
||||
if (!this.doProcessMentions) {
|
||||
const caret = Utils.getCaretPosition(React.findDOMNode(this.refs.message));
|
||||
const caret = Utils.getCaretPosition(ReactDOM.findDOMNode(this.refs.message));
|
||||
const preText = text.substring(0, caret);
|
||||
const lastSpace = preText.lastIndexOf(' ');
|
||||
const lastAt = preText.lastIndexOf('@');
|
||||
@@ -144,17 +145,19 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
|
||||
handleKeyDown(e) {
|
||||
if (Utils.getSelectedText(React.findDOMNode(this.refs.message)) !== '') {
|
||||
if (Utils.getSelectedText(ReactDOM.findDOMNode(this.refs.message)) !== '') {
|
||||
this.doProcessMentions = true;
|
||||
}
|
||||
|
||||
if (e.keyCode === 8) {
|
||||
if (e.keyCode === KeyCodes.BACKSPACE) {
|
||||
this.handleBackspace(e);
|
||||
} else if (this.props.onKeyDown) {
|
||||
this.props.onKeyDown(e);
|
||||
}
|
||||
}
|
||||
|
||||
handleBackspace() {
|
||||
const text = React.findDOMNode(this.refs.message).value;
|
||||
const text = ReactDOM.findDOMNode(this.refs.message).value;
|
||||
if (text.indexOf('/') === 0) {
|
||||
this.refs.commands.getSuggestedCommands(text.substring(0, text.length - 1));
|
||||
}
|
||||
@@ -163,7 +166,7 @@ export default class Textbox extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
const caret = Utils.getCaretPosition(React.findDOMNode(this.refs.message));
|
||||
const caret = Utils.getCaretPosition(ReactDOM.findDOMNode(this.refs.message));
|
||||
const preText = text.substring(0, caret);
|
||||
const lastSpace = preText.lastIndexOf(' ');
|
||||
const lastAt = preText.lastIndexOf('@');
|
||||
@@ -174,7 +177,7 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
|
||||
checkForNewMention(text) {
|
||||
const caret = Utils.getCaretPosition(React.findDOMNode(this.refs.message));
|
||||
const caret = Utils.getCaretPosition(ReactDOM.findDOMNode(this.refs.message));
|
||||
|
||||
const preText = text.substring(0, caret);
|
||||
|
||||
@@ -201,7 +204,7 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
|
||||
addMention(name) {
|
||||
const caret = Utils.getCaretPosition(React.findDOMNode(this.refs.message));
|
||||
const caret = Utils.getCaretPosition(ReactDOM.findDOMNode(this.refs.message));
|
||||
|
||||
const text = this.props.messageText;
|
||||
|
||||
@@ -224,14 +227,14 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
|
||||
addCommand(cmd) {
|
||||
const elm = React.findDOMNode(this.refs.message);
|
||||
const elm = ReactDOM.findDOMNode(this.refs.message);
|
||||
elm.value = cmd;
|
||||
this.handleChange();
|
||||
}
|
||||
|
||||
resize() {
|
||||
const e = React.findDOMNode(this.refs.message);
|
||||
const w = React.findDOMNode(this.refs.wrapper);
|
||||
const e = ReactDOM.findDOMNode(this.refs.message);
|
||||
const w = ReactDOM.findDOMNode(this.refs.wrapper);
|
||||
|
||||
const prevHeight = $(e).height();
|
||||
|
||||
@@ -259,14 +262,14 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
|
||||
handleFocus() {
|
||||
const elm = React.findDOMNode(this.refs.message);
|
||||
const elm = ReactDOM.findDOMNode(this.refs.message);
|
||||
if (elm.title === elm.value) {
|
||||
elm.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
handleBlur() {
|
||||
const elm = React.findDOMNode(this.refs.message);
|
||||
const elm = ReactDOM.findDOMNode(this.refs.message);
|
||||
if (elm.value === '') {
|
||||
elm.value = elm.title;
|
||||
}
|
||||
@@ -318,5 +321,6 @@ Textbox.propTypes = {
|
||||
onUserInput: React.PropTypes.func.isRequired,
|
||||
onKeyPress: React.PropTypes.func.isRequired,
|
||||
onHeightChange: React.PropTypes.func,
|
||||
createMessage: React.PropTypes.string.isRequired
|
||||
createMessage: React.PropTypes.string.isRequired,
|
||||
onKeyDown: React.PropTypes.func
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
var Utils = require('../utils/utils.jsx');
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
var Popover = ReactBootstrap.Popover;
|
||||
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
|
||||
|
||||
var id = 0;
|
||||
|
||||
@@ -32,7 +34,6 @@ export default class UserProfile extends React.Component {
|
||||
componentDidMount() {
|
||||
UserStore.addChangeListener(this.onChange);
|
||||
if (!this.props.disablePopover) {
|
||||
$('#profile_' + this.uniqueId).popover({placement: 'right', container: 'body', trigger: 'click hover', html: true, delay: {show: 200, hide: 100}});
|
||||
$('body').tooltip({selector: '[data-toggle=tooltip]', trigger: 'hover click'});
|
||||
}
|
||||
}
|
||||
@@ -62,23 +63,46 @@ export default class UserProfile extends React.Component {
|
||||
return <div>{name}</div>;
|
||||
}
|
||||
|
||||
var dataContent = '<img class="user-popover__image" src="/api/v1/users/' + this.state.profile.id + '/image?time=' + this.state.profile.update_at + '" height="128" width="128" />';
|
||||
var dataContent = [];
|
||||
dataContent.push(
|
||||
<img className='user-popover__image'
|
||||
src={'/api/v1/users/' + this.state.profile.id + '/image?time=' + this.state.profile.update_at}
|
||||
height='128'
|
||||
width='128'
|
||||
/>
|
||||
);
|
||||
if (!global.window.config.ShowEmailAddress === 'true') {
|
||||
dataContent += '<div class="text-nowrap">Email not shared</div>';
|
||||
dataContent.push(<div className='text-nowrap'>{'Email not shared'}</div>);
|
||||
} else {
|
||||
dataContent += '<div data-toggle="tooltip" title="' + this.state.profile.email + '"><a href="mailto:' + this.state.profile.email + '" class="text-nowrap text-lowercase user-popover__email">' + this.state.profile.email + '</a></div>';
|
||||
dataContent.push(
|
||||
<div
|
||||
data-toggle='tooltip'
|
||||
title="' + this.state.profile.email + '"
|
||||
>
|
||||
<a
|
||||
href="mailto:' + this.state.profile.email + '"
|
||||
className='text-nowrap text-lowercase user-popover__email'
|
||||
>
|
||||
{this.state.profile.email}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<OverlayTrigger
|
||||
trigger='click'
|
||||
placement='right'
|
||||
rootClose='true'
|
||||
overlay={<Popover title={this.state.profile.username}>{dataContent}</Popover>}
|
||||
>
|
||||
<div
|
||||
className='user-popover'
|
||||
id={'profile_' + this.uniqueId}
|
||||
data-toggle='popover'
|
||||
data-content={dataContent}
|
||||
data-original-title={this.state.profile.username}
|
||||
>
|
||||
{name}
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export default class ImportThemeModal extends React.Component {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const text = React.findDOMNode(this.refs.input).value;
|
||||
const text = ReactDOM.findDOMNode(this.refs.input).value;
|
||||
|
||||
if (!this.isInputValid(text)) {
|
||||
this.setState({inputError: 'Invalid format, please try copying and pasting in again.'});
|
||||
|
||||
@@ -29,14 +29,14 @@ export default class UserSettingsAppearance extends React.Component {
|
||||
UserStore.addChangeListener(this.onChange);
|
||||
|
||||
if (this.props.activeSection === 'theme') {
|
||||
$(React.findDOMNode(this.refs[this.state.theme])).addClass('active-border');
|
||||
$(ReactDOM.findDOMNode(this.refs[this.state.theme])).addClass('active-border');
|
||||
}
|
||||
$('#user_settings').on('hidden.bs.modal', this.handleClose);
|
||||
}
|
||||
componentDidUpdate() {
|
||||
if (this.props.activeSection === 'theme') {
|
||||
$('.color-btn').removeClass('active-border');
|
||||
$(React.findDOMNode(this.refs[this.state.theme])).addClass('active-border');
|
||||
$(ReactDOM.findDOMNode(this.refs[this.state.theme])).addClass('active-border');
|
||||
}
|
||||
}
|
||||
componentWillUnmount() {
|
||||
|
||||
@@ -211,7 +211,7 @@ export default class UserSettingsGeneralTab extends React.Component {
|
||||
this.props.updateSection(section);
|
||||
}
|
||||
handleClose() {
|
||||
$(React.findDOMNode(this)).find('.form-control').each(function clearForms() {
|
||||
$(ReactDOM.findDOMNode(this)).find('.form-control').each(function clearForms() {
|
||||
this.value = '';
|
||||
});
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ export default class NotificationsTab extends React.Component {
|
||||
);
|
||||
}
|
||||
handleClose() {
|
||||
$(React.findDOMNode(this)).find('.form-control').each(function clearField() {
|
||||
$(ReactDOM.findDOMNode(this)).find('.form-control').each(function clearField() {
|
||||
this.value = '';
|
||||
});
|
||||
|
||||
@@ -158,15 +158,15 @@ export default class NotificationsTab extends React.Component {
|
||||
}
|
||||
handleNotifyRadio(notifyLevel) {
|
||||
this.setState({notifyLevel: notifyLevel});
|
||||
React.findDOMNode(this.refs.wrapper).focus();
|
||||
ReactDOM.findDOMNode(this.refs.wrapper).focus();
|
||||
}
|
||||
handleEmailRadio(enableEmail) {
|
||||
this.setState({enableEmail: enableEmail});
|
||||
React.findDOMNode(this.refs.wrapper).focus();
|
||||
ReactDOM.findDOMNode(this.refs.wrapper).focus();
|
||||
}
|
||||
handleSoundRadio(enableSound) {
|
||||
this.setState({enableSound: enableSound});
|
||||
React.findDOMNode(this.refs.wrapper).focus();
|
||||
ReactDOM.findDOMNode(this.refs.wrapper).focus();
|
||||
}
|
||||
updateUsernameKey(val) {
|
||||
this.setState({usernameKey: val});
|
||||
@@ -184,10 +184,10 @@ export default class NotificationsTab extends React.Component {
|
||||
this.setState({channelKey: val});
|
||||
}
|
||||
updateCustomMentionKeys() {
|
||||
var checked = React.findDOMNode(this.refs.customcheck).checked;
|
||||
var checked = ReactDOM.findDOMNode(this.refs.customcheck).checked;
|
||||
|
||||
if (checked) {
|
||||
var text = React.findDOMNode(this.refs.custommentions).value;
|
||||
var text = ReactDOM.findDOMNode(this.refs.custommentions).value;
|
||||
|
||||
// remove all spaces and split string into individual keys
|
||||
this.setState({customKeys: text.replace(/ /g, ''), customKeysChecked: true});
|
||||
@@ -196,7 +196,7 @@ export default class NotificationsTab extends React.Component {
|
||||
}
|
||||
}
|
||||
onCustomChange() {
|
||||
React.findDOMNode(this.refs.customcheck).checked = true;
|
||||
ReactDOM.findDOMNode(this.refs.customcheck).checked = true;
|
||||
this.updateCustomMentionKeys();
|
||||
}
|
||||
render() {
|
||||
|
||||
@@ -82,7 +82,7 @@ export default class SecurityTab extends React.Component {
|
||||
$('#user_settings').modal('hide');
|
||||
}
|
||||
handleClose() {
|
||||
$(React.findDOMNode(this)).find('.form-control').each(function resetValue() {
|
||||
$(ReactDOM.findDOMNode(this)).find('.form-control').each(function resetValue() {
|
||||
this.value = '';
|
||||
});
|
||||
this.setState({currentPassword: '', newPassword: '', confirmPassword: '', serverError: null, passwordError: null});
|
||||
|
||||
@@ -77,7 +77,7 @@ export default class ViewImageModal extends React.Component {
|
||||
}
|
||||
onModalHidden() {
|
||||
if (this.refs.video) {
|
||||
var video = React.findDOMNode(this.refs.video);
|
||||
var video = ReactDOM.findDOMNode(this.refs.video);
|
||||
video.pause();
|
||||
video.currentTime = 0;
|
||||
}
|
||||
|
||||
@@ -6,17 +6,17 @@ var SelectTeamModal = require('../components/admin_console/select_team_modal.jsx
|
||||
var AdminController = require('../components/admin_console/admin_controller.jsx');
|
||||
|
||||
export function setupAdminConsolePage() {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<AdminController />,
|
||||
document.getElementById('admin_controller')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<SelectTeamModal />,
|
||||
document.getElementById('select_team_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ErrorBar/>,
|
||||
document.getElementById('error_bar')
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var Authorize = require('../components/authorize.jsx');
|
||||
|
||||
function setupAuthorizePage(props) {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<Authorize
|
||||
teamName={props.TeamName}
|
||||
appName={props.AppName}
|
||||
|
||||
@@ -24,7 +24,6 @@ var TeamSettingsModal = require('../components/team_settings_modal.jsx');
|
||||
var ChannelMembersModal = require('../components/channel_members.jsx');
|
||||
var ChannelInviteModal = require('../components/channel_invite_modal.jsx');
|
||||
var TeamMembersModal = require('../components/team_members.jsx');
|
||||
var DirectChannelModal = require('../components/more_direct_channels.jsx');
|
||||
var ErrorBar = require('../components/error_bar.jsx');
|
||||
var ErrorStore = require('../stores/error_store.jsx');
|
||||
var ChannelLoader = require('../components/channel_loader.jsx');
|
||||
@@ -56,22 +55,22 @@ function setupChannelPage(props) {
|
||||
});
|
||||
|
||||
// ChannelLoader must be rendered first
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ChannelLoader/>,
|
||||
document.getElementById('channel_loader')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ErrorBar/>,
|
||||
document.getElementById('error_bar')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<Navbar teamDisplayName={props.TeamDisplayName} />,
|
||||
document.getElementById('navbar')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<Sidebar
|
||||
teamDisplayName={props.TeamDisplayName}
|
||||
teamName={props.TeamName}
|
||||
@@ -80,117 +79,112 @@ function setupChannelPage(props) {
|
||||
document.getElementById('sidebar-left')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<GetLinkModal />,
|
||||
document.getElementById('get_link_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<UserSettingsModal />,
|
||||
document.getElementById('user_settings_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ImportThemeModal />,
|
||||
document.getElementById('import_theme_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<TeamSettingsModal teamDisplayName={props.TeamDisplayName} />,
|
||||
document.getElementById('team_settings_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<TeamMembersModal teamDisplayName={props.TeamDisplayName} />,
|
||||
document.getElementById('team_members_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<MemberInviteModal teamType={props.TeamType} />,
|
||||
document.getElementById('invite_member_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ChannelHeader />,
|
||||
document.getElementById('channel-header')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<EditChannelModal />,
|
||||
document.getElementById('edit_channel_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<DeleteChannelModal />,
|
||||
document.getElementById('delete_channel_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<RenameChannelModal />,
|
||||
document.getElementById('rename_channel_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ChannelNotificationsModal />,
|
||||
document.getElementById('channel_notifications_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ChannelMembersModal />,
|
||||
document.getElementById('channel_members_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ChannelInviteModal />,
|
||||
document.getElementById('channel_invite_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ChannelInfoModal />,
|
||||
document.getElementById('channel_info_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<MoreChannelsModal />,
|
||||
document.getElementById('more_channels_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
<DirectChannelModal />,
|
||||
document.getElementById('direct_channel_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<PostListContainer />,
|
||||
document.getElementById('post-list')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<EditPostModal />,
|
||||
document.getElementById('edit_post_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<DeletePostModal />,
|
||||
document.getElementById('delete_post_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<PostDeletedModal />,
|
||||
document.getElementById('post_deleted_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<CreatePost />,
|
||||
document.getElementById('post-create')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<SidebarRight />,
|
||||
document.getElementById('sidebar-right')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<SidebarRightMenu
|
||||
teamDisplayName={props.TeamDisplayName}
|
||||
teamType={props.TeamType}
|
||||
@@ -198,44 +192,44 @@ function setupChannelPage(props) {
|
||||
document.getElementById('sidebar-menu')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<MentionList id='post_textbox' />,
|
||||
document.getElementById('post_mention_tab')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<MentionList id='reply_textbox' />,
|
||||
document.getElementById('reply_mention_tab')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<MentionList id='edit_textbox' />,
|
||||
document.getElementById('edit_mention_tab')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<AccessHistoryModal />,
|
||||
document.getElementById('access_history_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<ActivityLogModal />,
|
||||
document.getElementById('activity_log_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<RemovedFromChannelModal />,
|
||||
document.getElementById('removed_from_channel_modal')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<FileUploadOverlay
|
||||
overlayType='center'
|
||||
/>,
|
||||
document.getElementById('file_upload_overlay')
|
||||
);
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<RegisterAppModal />,
|
||||
document.getElementById('register_app_modal')
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var FindTeam = require('../components/find_team.jsx');
|
||||
|
||||
function setupFindTeamPage() {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<FindTeam />,
|
||||
document.getElementById('find-team')
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var Login = require('../components/login.jsx');
|
||||
|
||||
function setupLoginPage(props) {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<Login
|
||||
teamDisplayName={props.TeamDisplayName}
|
||||
teamName={props.TeamName}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var PasswordReset = require('../components/password_reset.jsx');
|
||||
|
||||
function setupPasswordResetPage(props) {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<PasswordReset
|
||||
isReset={props.IsReset}
|
||||
teamDisplayName={props.TeamDisplayName}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var SignupTeam = require('../components/signup_team.jsx');
|
||||
|
||||
function setupSignupTeamPage() {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<SignupTeam />,
|
||||
document.getElementById('signup-team')
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var SignupTeamComplete = require('../components/signup_team_complete.jsx');
|
||||
|
||||
function setupSignupTeamCompletePage(props) {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<SignupTeamComplete
|
||||
email={props.Email}
|
||||
hash={props.Hash}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var SignupUserComplete = require('../components/signup_user_complete.jsx');
|
||||
|
||||
function setupSignupUserCompletePage(props) {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<SignupUserComplete
|
||||
teamId={props.TeamId}
|
||||
teamName={props.TeamName}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var EmailVerify = require('../components/email_verify.jsx');
|
||||
|
||||
global.window.setupVerifyPage = function setupVerifyPage(props) {
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<EmailVerify
|
||||
isVerified={props.IsVerified}
|
||||
teamURL={props.TeamURL}
|
||||
|
||||
@@ -6,6 +6,7 @@ var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
var BrowserStore = require('../stores/browser_store.jsx');
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
|
||||
var Constants = require('../utils/constants.jsx');
|
||||
var ActionTypes = Constants.ActionTypes;
|
||||
@@ -16,6 +17,7 @@ var SEARCH_TERM_CHANGE_EVENT = 'search_term_change';
|
||||
var SELECTED_POST_CHANGE_EVENT = 'selected_post_change';
|
||||
var MENTION_DATA_CHANGE_EVENT = 'mention_data_change';
|
||||
var ADD_MENTION_EVENT = 'add_mention';
|
||||
var EDIT_POST_EVENT = 'edit_post';
|
||||
|
||||
class PostStoreClass extends EventEmitter {
|
||||
constructor() {
|
||||
@@ -75,6 +77,10 @@ class PostStoreClass extends EventEmitter {
|
||||
this.clearCommentDraftUploads = this.clearCommentDraftUploads.bind(this);
|
||||
this.storeLatestUpdate = this.storeLatestUpdate.bind(this);
|
||||
this.getLatestUpdate = this.getLatestUpdate.bind(this);
|
||||
this.emitEditPost = this.emitEditPost.bind(this);
|
||||
this.addEditPostListener = this.addEditPostListener.bind(this);
|
||||
this.removeEditPostListener = this.removeEditPostListener.bind(this);
|
||||
this.getCurrentUsersLatestPost = this.getCurrentUsersLatestPost.bind(this);
|
||||
}
|
||||
emitChange() {
|
||||
this.emit(CHANGE_EVENT);
|
||||
@@ -148,6 +154,18 @@ class PostStoreClass extends EventEmitter {
|
||||
this.removeListener(ADD_MENTION_EVENT, callback);
|
||||
}
|
||||
|
||||
emitEditPost(post) {
|
||||
this.emit(EDIT_POST_EVENT, post);
|
||||
}
|
||||
|
||||
addEditPostListener(callback) {
|
||||
this.on(EDIT_POST_EVENT, callback);
|
||||
}
|
||||
|
||||
removeEditPostListener(callback) {
|
||||
this.removeListener(EDIT_POST_EVENT, callback);
|
||||
}
|
||||
|
||||
getCurrentPosts() {
|
||||
var currentId = ChannelStore.getCurrentId();
|
||||
|
||||
@@ -212,6 +230,22 @@ class PostStoreClass extends EventEmitter {
|
||||
getPosts(channelId) {
|
||||
return BrowserStore.getItem('posts_' + channelId);
|
||||
}
|
||||
getCurrentUsersLatestPost(channelId) {
|
||||
const userId = UserStore.getCurrentId();
|
||||
var postList = makePostListNonNull(this.getPosts(channelId));
|
||||
var i = 0;
|
||||
var len = postList.order.length;
|
||||
var lastPost = null;
|
||||
|
||||
for (i; i < len; i++) {
|
||||
if (postList.posts[postList.order[i]].user_id === userId) {
|
||||
lastPost = postList.posts[postList.order[i]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lastPost;
|
||||
}
|
||||
storePost(post) {
|
||||
this.pStorePost(post);
|
||||
this.emitChange();
|
||||
@@ -446,6 +480,9 @@ PostStore.dispatchToken = AppDispatcher.register(function registry(payload) {
|
||||
case ActionTypes.RECIEVED_ADD_MENTION:
|
||||
PostStore.emitAddMention(action.id, action.username);
|
||||
break;
|
||||
case ActionTypes.RECIEVED_EDIT_POST:
|
||||
PostStore.emitEditPost(action);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,6 +17,7 @@ module.exports = {
|
||||
|
||||
RECIEVED_POSTS: null,
|
||||
RECIEVED_POST: null,
|
||||
RECIEVED_EDIT_POST: null,
|
||||
RECIEVED_SEARCH: null,
|
||||
RECIEVED_POST_SELECTED: null,
|
||||
RECIEVED_MENTION_DATA: null,
|
||||
@@ -290,5 +291,14 @@ module.exports = {
|
||||
Preferences: {
|
||||
CATEGORY_DIRECT_CHANNEL_SHOW: 'direct_channel_show',
|
||||
CATEGORY_DISPLAY_SETTINGS: 'display_settings'
|
||||
},
|
||||
KeyCodes: {
|
||||
UP: 38,
|
||||
DOWN: 40,
|
||||
LEFT: 37,
|
||||
RIGHT: 39,
|
||||
BACKSPACE: 8,
|
||||
ENTER: 13,
|
||||
ESCAPE: 27
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ export class MattermostMarkdownRenderer extends marked.Renderer {
|
||||
link(href, title, text) {
|
||||
let outHref = href;
|
||||
|
||||
if (outHref.lastIndexOf('http', 0) !== 0) {
|
||||
if (!(/^(mailto|https?|ftp)/.test(outHref))) {
|
||||
outHref = `http://${outHref}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ function autolinkUrls(text, tokens) {
|
||||
|
||||
if (match.getType() === 'email') {
|
||||
url = `mailto:${url}`;
|
||||
} else if (url.lastIndexOf('http', 0) !== 0) {
|
||||
} else if (!(/^(mailto|https?|ftp)/.test(url))) {
|
||||
url = `http://${url}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -474,6 +474,10 @@ export function applyTheme(theme) {
|
||||
changeCss('.date-separator .separator__text, .new-separator .separator__text', 'background:' + theme.centerChannelBg, 1);
|
||||
changeCss('.post-image__column .post-image__details', 'background:' + theme.centerChannelBg, 1);
|
||||
changeCss('.sidebar--right, .dropdown-menu, .popover', 'background:' + theme.centerChannelBg, 1);
|
||||
changeCss('.popover.bottom>.arrow:after', 'border-bottom-color:' + theme.centerChannelBg, 1);
|
||||
changeCss('.popover.right>.arrow:after', 'border-right-color:' + theme.centerChannelBg, 1);
|
||||
changeCss('.popover.left>.arrow:after', 'border-left-color:' + theme.centerChannelBg, 1);
|
||||
changeCss('.popover.top>.arrow:after', 'border-top-color:' + theme.centerChannelBg, 1);
|
||||
changeCss('.search-bar__container .search__form .search-bar, .form-control', 'background:' + theme.centerChannelBg, 1);
|
||||
}
|
||||
|
||||
@@ -918,6 +922,18 @@ export function isBrowserEdge() {
|
||||
return window.naviagtor && navigator.userAgent && navigator.userAgent.toLowerCase().indexOf('edge') > -1;
|
||||
}
|
||||
|
||||
export function getDirectChannelName(id, otherId) {
|
||||
let handle;
|
||||
|
||||
if (otherId > id) {
|
||||
handle = id + '__' + otherId;
|
||||
} else {
|
||||
handle = otherId + '__' + id;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// Used to get the id of the other user from a DM channel
|
||||
export function getUserIdFromChannelName(channel) {
|
||||
var ids = channel.name.split('__');
|
||||
|
||||
Ссылка в новой задаче
Block a user