mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
MM-2065 style refactoring
This commit is contained in:
@@ -3,57 +3,86 @@
|
||||
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
componentDidMount: function() {
|
||||
export default class CommandList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
channel_id: ChannelStore.getCurrentId()
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
if(this.refs.modal) {
|
||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
|
||||
var button = e.relatedTarget;
|
||||
self.setState({ channel_id: $(button).attr('data-channelid') });
|
||||
});
|
||||
if (this.refs.modal) {
|
||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function show(e) {
|
||||
var button = e.relatedTarget;
|
||||
self.setState({channel_id: $(button).attr('data-channelid')});
|
||||
});
|
||||
}
|
||||
},
|
||||
getInitialState: function() {
|
||||
return { channel_id: ChannelStore.getCurrentId() };
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
var channel = ChannelStore.get(this.state.channel_id);
|
||||
|
||||
if (!channel) {
|
||||
channel = {};
|
||||
channel.display_name = "No Channel Found";
|
||||
channel.name = "No Channel Found";
|
||||
channel.id = "No Channel Found";
|
||||
channel.display_name = 'No Channel Found';
|
||||
channel.name = 'No Channel Found';
|
||||
channel.id = 'No Channel Found';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="modal fade" ref="modal" id="channel_info" tabIndex="-1" role="dialog" aria-hidden="true">
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 className="modal-title" id="myModalLabel"><span className="name">{channel.display_name}</span></h4>
|
||||
<div
|
||||
className='modal fade'
|
||||
ref='modal'
|
||||
id='channel_info'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
>
|
||||
<div className='modal-dialog'>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
<h4
|
||||
className='modal-title'
|
||||
id='myModalLabel'
|
||||
>
|
||||
<span className='name'>{channel.display_name}</span>
|
||||
</h4>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="row form-group">
|
||||
<div className="col-sm-3 info__label">Channel Name: </div>
|
||||
<div className="col-sm-9">{channel.display_name}</div>
|
||||
<div className='modal-body'>
|
||||
<div className='row form-group'>
|
||||
<div className='col-sm-3 info__label'>Channel Name: </div>
|
||||
<div className='col-sm-9'>{channel.display_name}</div>
|
||||
</div>
|
||||
<div className="row form-group">
|
||||
<div className="col-sm-3 info__label">Channel Handle:</div>
|
||||
<div className="col-sm-9">{channel.name}</div>
|
||||
<div className='row form-group'>
|
||||
<div className='col-sm-3 info__label'>Channel Handle:</div>
|
||||
<div className='col-sm-9'>{channel.name}</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-sm-3 info__label">Channel ID:</div>
|
||||
<div className="col-sm-9">{channel.id}</div>
|
||||
<div className='row'>
|
||||
<div className='col-sm-3 info__label'>Channel ID:</div>
|
||||
<div className='col-sm-9'>{channel.id}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<div className='modal-footer'>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
data-dismiss='modal'
|
||||
>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ var utils = require('../utils/utils.jsx');
|
||||
var client = require('../utils/client.jsx');
|
||||
var AsyncClient = require('../utils/async_client.jsx');
|
||||
|
||||
|
||||
export default class ChannelInviteModal extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
@@ -129,15 +128,37 @@ export default class ChannelInviteModal extends React.Component {
|
||||
if (this.state.loading) {
|
||||
content = (<LoadingScreen />);
|
||||
} else {
|
||||
content = (<MemberList memberList={this.state.nonmembers} isAdmin={isAdmin} handleInvite={this.handleInvite} />);
|
||||
content = (
|
||||
<MemberList
|
||||
memberList={this.state.nonmembers}
|
||||
isAdmin={isAdmin}
|
||||
handleInvite={this.handleInvite}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='modal fade' id='channel_invite' tabIndex='-1' role='dialog' aria-hidden='true'>
|
||||
<div className='modal-dialog' role='document'>
|
||||
<div
|
||||
className='modal fade'
|
||||
id='channel_invite'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
>
|
||||
<div
|
||||
className='modal-dialog'
|
||||
role='document'
|
||||
>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button type='button' className='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>×</span></button>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
<h4 className='modal-title'>Add New Members to <span className='name'>{this.state.channelName}</span></h4>
|
||||
</div>
|
||||
<div className='modal-body'>
|
||||
@@ -145,7 +166,11 @@ export default class ChannelInviteModal extends React.Component {
|
||||
{content}
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button type='button' className='btn btn-default' data-dismiss='modal'>Close</button>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
data-dismiss='modal'
|
||||
>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -153,4 +178,3 @@ export default class ChannelInviteModal extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
ChannelInviteModal.displayName = 'ChannelInviteModal';
|
||||
|
||||
@@ -3,25 +3,40 @@
|
||||
|
||||
var client = require('../utils/client.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
getInitialState: function() {
|
||||
return { suggestions: [ ], cmd: "" };
|
||||
},
|
||||
handleClick: function(i) {
|
||||
this.props.addCommand(this.state.suggestions[i].suggestion)
|
||||
this.setState({ suggestions: [ ], cmd: "" });
|
||||
},
|
||||
addFirstCommand: function() {
|
||||
if (this.state.suggestions.length == 0) return;
|
||||
this.handleClick(0);
|
||||
},
|
||||
isEmpty: function() {
|
||||
return this.state.suggestions.length == 0;
|
||||
},
|
||||
getSuggestedCommands: function(cmd) {
|
||||
export default class CommandList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
if (!cmd || cmd.charAt(0) != '/') {
|
||||
this.setState({ suggestions: [ ], cmd: "" });
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.addFirstCommand = this.addFirstCommand.bind(this);
|
||||
this.isEmpty = this.isEmpty.bind(this);
|
||||
this.getSuggestedCommands = this.getSuggestedCommands.bind(this);
|
||||
|
||||
this.state = {
|
||||
suggestions: [ ],
|
||||
cmd: ''
|
||||
};
|
||||
}
|
||||
|
||||
handleClick(i) {
|
||||
this.props.addCommand(this.state.suggestions[i].suggestion);
|
||||
this.setState({suggestions: [ ], cmd: ''});
|
||||
}
|
||||
|
||||
addFirstCommand() {
|
||||
if (this.state.suggestions.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.handleClick(0);
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return this.state.suggestions.length === 0;
|
||||
}
|
||||
|
||||
getSuggestedCommands(cmd) {
|
||||
if (!cmd || cmd.charAt(0) !== '/') {
|
||||
this.setState({suggestions: [ ], cmd: ''});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,36 +44,56 @@ module.exports = React.createClass({
|
||||
this.props.channelId,
|
||||
cmd,
|
||||
true,
|
||||
function(data) {
|
||||
function success(data) {
|
||||
if (data.suggestions.length === 1 && data.suggestions[0].suggestion === cmd) {
|
||||
data.suggestions = [];
|
||||
}
|
||||
this.setState({ suggestions: data.suggestions, cmd: cmd });
|
||||
this.setState({suggestions: data.suggestions, cmd: cmd});
|
||||
}.bind(this),
|
||||
function(err){
|
||||
}
|
||||
function fail() {
|
||||
}
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
if (this.state.suggestions.length == 0) return (<div/>);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.suggestions.length === 0) {
|
||||
return (<div/>);
|
||||
}
|
||||
|
||||
var suggestions = [];
|
||||
|
||||
for (var i = 0; i < this.state.suggestions.length; i++) {
|
||||
if (this.state.suggestions[i].suggestion != this.state.cmd) {
|
||||
if (this.state.suggestions[i].suggestion !== this.state.cmd) {
|
||||
suggestions.push(
|
||||
<div key={i} className="command-name" onClick={this.handleClick.bind(this, i)}>
|
||||
<div className="command__title"><strong>{ this.state.suggestions[i].suggestion }</strong></div>
|
||||
<div className="command__desc">{ this.state.suggestions[i].description }</div>
|
||||
<div
|
||||
key={i}
|
||||
className='command-name'
|
||||
onClick={this.handleClick.bind(this, i)}
|
||||
>
|
||||
<div className='command__title'><strong>{this.state.suggestions[i].suggestion}</strong></div>
|
||||
<div className='command__desc'>{this.state.suggestions[i].description}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref="mentionlist" className="command-box" style={{height:(this.state.suggestions.length*56)+2}}>
|
||||
{ suggestions }
|
||||
<div
|
||||
ref='mentionlist'
|
||||
className='command-box'
|
||||
style={{height: (this.state.suggestions.length * 56) + 2}}
|
||||
>
|
||||
{suggestions}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
CommandList.defaultProps = {
|
||||
channelId: null
|
||||
};
|
||||
|
||||
CommandList.propTypes = {
|
||||
addCommand: React.PropTypes.func,
|
||||
channelId: React.PropTypes.string
|
||||
};
|
||||
@@ -6,20 +6,19 @@ var Constants = require('../utils/constants.jsx');
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
var utils = require('../utils/utils.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'FileUpload',
|
||||
propTypes: {
|
||||
onUploadError: React.PropTypes.func,
|
||||
getFileCount: React.PropTypes.func,
|
||||
onFileUpload: React.PropTypes.func,
|
||||
onUploadStart: React.PropTypes.func,
|
||||
channelId: React.PropTypes.string,
|
||||
postType: React.PropTypes.string
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {requests: {}};
|
||||
},
|
||||
handleChange: function() {
|
||||
export default class FileUpload extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleDrop = this.handleDrop.bind(this);
|
||||
|
||||
this.state = {
|
||||
requests: {}
|
||||
};
|
||||
}
|
||||
|
||||
handleChange() {
|
||||
var element = $(this.refs.fileInput.getDOMNode());
|
||||
var files = element.prop('files');
|
||||
|
||||
@@ -30,7 +29,7 @@ module.exports = React.createClass({
|
||||
// This looks redundant, but must be done this way due to
|
||||
// setState being an asynchronous call
|
||||
var numFiles = 0;
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
if (files[i].size <= Constants.MAX_FILE_SIZE) {
|
||||
numFiles++;
|
||||
}
|
||||
@@ -42,7 +41,7 @@ module.exports = React.createClass({
|
||||
this.props.onUploadError('Uploads limited to ' + Constants.MAX_UPLOAD_FILES + ' files maximum. Please use additional posts for more files.');
|
||||
}
|
||||
|
||||
for (var i = 0; i < files.length && i < numToUpload; i++) {
|
||||
for (let i = 0; i < files.length && i < numToUpload; i++) {
|
||||
if (files[i].size > Constants.MAX_FILE_SIZE) {
|
||||
this.props.onUploadError('Files must be no more than ' + Constants.MAX_FILE_SIZE / 1000000 + ' MB');
|
||||
continue;
|
||||
@@ -58,7 +57,7 @@ module.exports = React.createClass({
|
||||
formData.append('client_ids', clientId);
|
||||
|
||||
var request = client.uploadFile(formData,
|
||||
function(data) {
|
||||
function success(data) {
|
||||
var parsedData = $.parseJSON(data);
|
||||
this.props.onFileUpload(parsedData.filenames, parsedData.client_ids, channelId);
|
||||
|
||||
@@ -68,7 +67,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
this.setState({requests: requests});
|
||||
}.bind(this),
|
||||
function(err) {
|
||||
function fail(err) {
|
||||
this.props.onUploadError(err, clientId);
|
||||
}.bind(this)
|
||||
);
|
||||
@@ -87,9 +86,12 @@ module.exports = React.createClass({
|
||||
element[0].type = 'text';
|
||||
element[0].type = 'file';
|
||||
}
|
||||
} catch(e) {}
|
||||
},
|
||||
handleDrop: function(e) {
|
||||
} catch(e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
handleDrop(e) {
|
||||
this.props.onUploadError(null);
|
||||
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
@@ -120,7 +122,7 @@ module.exports = React.createClass({
|
||||
formData.append('client_ids', clientId);
|
||||
|
||||
var request = client.uploadFile(formData,
|
||||
function(data) {
|
||||
function success(data) {
|
||||
var parsedData = $.parseJSON(data);
|
||||
this.props.onFileUpload(parsedData.filenames, parsedData.client_ids, channelId);
|
||||
|
||||
@@ -130,7 +132,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
this.setState({requests: requests});
|
||||
}.bind(this),
|
||||
function(err) {
|
||||
function fail(err) {
|
||||
this.props.onUploadError(err, clientId);
|
||||
}.bind(this)
|
||||
);
|
||||
@@ -144,40 +146,41 @@ module.exports = React.createClass({
|
||||
} else {
|
||||
this.props.onUploadError('Invalid file upload', -1);
|
||||
}
|
||||
},
|
||||
componentDidMount: function() {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
var inputDiv = this.refs.input.getDOMNode();
|
||||
var self = this;
|
||||
|
||||
if (this.props.postType === 'post') {
|
||||
$('.row.main').dragster({
|
||||
enter: function() {
|
||||
enter() {
|
||||
$('.center-file-overlay').removeClass('hidden');
|
||||
},
|
||||
leave: function() {
|
||||
leave() {
|
||||
$('.center-file-overlay').addClass('hidden');
|
||||
},
|
||||
drop: function(dragsterEvent, e) {
|
||||
drop(dragsterEvent, e) {
|
||||
$('.center-file-overlay').addClass('hidden');
|
||||
self.handleDrop(e);
|
||||
}
|
||||
});
|
||||
} else if (this.props.postType === 'comment') {
|
||||
$('.post-right__container').dragster({
|
||||
enter: function() {
|
||||
enter() {
|
||||
$('.right-file-overlay').removeClass('hidden');
|
||||
},
|
||||
leave: function() {
|
||||
leave() {
|
||||
$('.right-file-overlay').addClass('hidden');
|
||||
},
|
||||
drop: function(dragsterEvent, e) {
|
||||
drop(dragsterEvent, e) {
|
||||
$('.right-file-overlay').addClass('hidden');
|
||||
self.handleDrop(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('paste', function(e) {
|
||||
document.addEventListener('paste', function handlePaste(e) {
|
||||
var textarea = $(inputDiv.parentNode.parentNode).find('.custom-textarea')[0];
|
||||
|
||||
if (textarea !== e.target && !$.contains(textarea, e.target)) {
|
||||
@@ -191,7 +194,7 @@ module.exports = React.createClass({
|
||||
var items = e.clipboardData.items;
|
||||
var numItems = 0;
|
||||
if (items) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].type.indexOf('image') !== -1) {
|
||||
var testExt = items[i].type.split('/')[1].toLowerCase();
|
||||
|
||||
@@ -269,8 +272,9 @@ module.exports = React.createClass({
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
cancelUpload: function(clientId) {
|
||||
}
|
||||
|
||||
cancelUpload(clientId) {
|
||||
var requests = this.state.requests;
|
||||
var request = requests[clientId];
|
||||
|
||||
@@ -280,15 +284,33 @@ module.exports = React.createClass({
|
||||
delete requests[clientId];
|
||||
this.setState({requests: requests});
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span ref='input' className='btn btn-file'>
|
||||
<span
|
||||
ref='input'
|
||||
className='btn btn-file'
|
||||
>
|
||||
<span>
|
||||
<i className='glyphicon glyphicon-paperclip' />
|
||||
</span>
|
||||
<input ref='fileInput' type='file' onChange={this.handleChange} multiple/>
|
||||
<input
|
||||
ref='fileInput'
|
||||
type='file'
|
||||
onChange={this.handleChange}
|
||||
multiple='true'
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
FileUpload.propTypes = {
|
||||
onUploadError: React.PropTypes.func,
|
||||
getFileCount: React.PropTypes.func,
|
||||
onFileUpload: React.PropTypes.func,
|
||||
onUploadStart: React.PropTypes.func,
|
||||
channelId: React.PropTypes.string,
|
||||
postType: React.PropTypes.string
|
||||
};
|
||||
|
||||
@@ -1,53 +1,57 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
|
||||
var utils = require('../utils/utils.jsx');
|
||||
var client = require('../utils/client.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleSubmit: function(e) {
|
||||
export default class FindTeam extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var state = { };
|
||||
|
||||
var email = this.refs.email.getDOMNode().value.trim().toLowerCase();
|
||||
if (!email || !utils.isEmail(email)) {
|
||||
state.email_error = "Please enter a valid email address";
|
||||
state.email_error = 'Please enter a valid email address';
|
||||
this.setState(state);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
state.email_error = "";
|
||||
}
|
||||
|
||||
state.email_error = '';
|
||||
|
||||
client.findTeamsSendEmail(email,
|
||||
function(data) {
|
||||
function success() {
|
||||
state.sent = true;
|
||||
this.setState(state);
|
||||
}.bind(this),
|
||||
function(err) {
|
||||
function fail(err) {
|
||||
state.email_error = err.message;
|
||||
this.setState(state);
|
||||
}.bind(this)
|
||||
);
|
||||
},
|
||||
getInitialState: function() {
|
||||
return { };
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
var email_error = this.state.email_error ? <label className='control-label'>{ this.state.email_error }</label> : null;
|
||||
render() {
|
||||
var emailError = null;
|
||||
var emailErrorClass = 'form-group';
|
||||
|
||||
var divStyle = {
|
||||
"marginTop": "50px",
|
||||
if (this.state.email_error) {
|
||||
emailError = <label className='control-label'>{this.state.email_error}</label>;
|
||||
emailErrorClass = 'form-group has-error';
|
||||
}
|
||||
|
||||
if (this.state.sent) {
|
||||
return (
|
||||
<div>
|
||||
<h4>{"Find Your " + utils.toTitleCase(strings.Team)}</h4>
|
||||
<p>{"An email was sent with links to any " + strings.TeamPlural + " to which you are a member."}</p>
|
||||
<h4>{'Find Your ' + utils.toTitleCase(strings.Team)}</h4>
|
||||
<p>{'An email was sent with links to any ' + strings.TeamPlural + ' to which you are a member.'}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -56,17 +60,25 @@ module.exports = React.createClass({
|
||||
<div>
|
||||
<h4>Find Your Team</h4>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<p>{"Get an email with links to any " + strings.TeamPlural + " to which you are a member."}</p>
|
||||
<div className="form-group">
|
||||
<p>{'Get an email with links to any ' + strings.TeamPlural + ' to which you are a member.'}</p>
|
||||
<div className='form-group'>
|
||||
<label className='control-label'>Email</label>
|
||||
<div className={ email_error ? "form-group has-error" : "form-group" }>
|
||||
<input type="text" ref="email" className="form-control" placeholder="you@domain.com" maxLength="128" />
|
||||
{ email_error }
|
||||
<div className={emailErrorClass}>
|
||||
<input
|
||||
type='text'
|
||||
ref='email'
|
||||
className='form-control'
|
||||
placeholder='you@domain.com'
|
||||
maxLength='128'
|
||||
/>
|
||||
{emailError}
|
||||
</div>
|
||||
</div>
|
||||
<button className="btn btn-md btn-primary" type="submit">Send</button>
|
||||
<button
|
||||
className='btn btn-md btn-primary'
|
||||
type='submit'>Send</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,10 +7,28 @@ var Client = require('../utils/client.jsx');
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
var ConfirmModal = require('./confirm_modal.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
componentDidMount: function() {
|
||||
export default class InviteMemberModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
this.addInviteFields = this.addInviteFields.bind(this);
|
||||
this.clearFields = this.clearFields.bind(this);
|
||||
this.removeInviteFields = this.removeInviteFields.bind(this);
|
||||
|
||||
this.state = {
|
||||
inviteIds: [0],
|
||||
idCount: 0,
|
||||
emailErrors: {},
|
||||
firstNameErrors: {},
|
||||
lastNameErrors: {},
|
||||
emailEnabled: !ConfigStore.getSettingAsBoolean('ByPassEmail', false)
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
$('#invite_member').on('hide.bs.modal', function(e) {
|
||||
$('#invite_member').on('hide.bs.modal', function hide(e) {
|
||||
if ($('#invite_member').attr('data-confirm') === 'true') {
|
||||
$('#invite_member').attr('data-confirm', 'false');
|
||||
return;
|
||||
@@ -31,11 +49,12 @@ module.exports = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
$('#invite_member').on('hidden.bs.modal', function() {
|
||||
$('#invite_member').on('hidden.bs.modal', function show() {
|
||||
self.clearFields();
|
||||
});
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
}
|
||||
|
||||
handleSubmit() {
|
||||
if (!this.state.emailEnabled) {
|
||||
return;
|
||||
}
|
||||
@@ -90,11 +109,11 @@ module.exports = React.createClass({
|
||||
data.invites = invites;
|
||||
|
||||
Client.inviteMembers(data,
|
||||
function() {
|
||||
function success() {
|
||||
$(this.refs.modal.getDOMNode()).attr('data-confirm', 'true');
|
||||
$(this.refs.modal.getDOMNode()).modal('hide');
|
||||
}.bind(this),
|
||||
function(err) {
|
||||
function fail(err) {
|
||||
if (err.message === 'This person is already on your team') {
|
||||
emailErrors[err.detailed_error] = err.message;
|
||||
this.setState({emailErrors: emailErrors});
|
||||
@@ -103,18 +122,21 @@ module.exports = React.createClass({
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
},
|
||||
componentDidUpdate: function() {
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
$(this.refs.modalBody.getDOMNode()).css('max-height', $(window).height() - 200);
|
||||
$(this.refs.modalBody.getDOMNode()).css('overflow-y', 'scroll');
|
||||
},
|
||||
addInviteFields: function() {
|
||||
}
|
||||
|
||||
addInviteFields() {
|
||||
var count = this.state.idCount + 1;
|
||||
var inviteIds = this.state.inviteIds;
|
||||
inviteIds.push(count);
|
||||
this.setState({inviteIds: inviteIds, idCount: count});
|
||||
},
|
||||
clearFields: function() {
|
||||
}
|
||||
|
||||
clearFields() {
|
||||
var inviteIds = this.state.inviteIds;
|
||||
|
||||
for (var i = 0; i < inviteIds.length; i++) {
|
||||
@@ -133,8 +155,9 @@ module.exports = React.createClass({
|
||||
firstNameErrors: {},
|
||||
lastNameErrors: {}
|
||||
});
|
||||
},
|
||||
removeInviteFields: function(index) {
|
||||
}
|
||||
|
||||
removeInviteFields(index) {
|
||||
var count = this.state.idCount;
|
||||
var inviteIds = this.state.inviteIds;
|
||||
var i = inviteIds.indexOf(index);
|
||||
@@ -145,24 +168,10 @@ module.exports = React.createClass({
|
||||
inviteIds.push(++count);
|
||||
}
|
||||
this.setState({inviteIds: inviteIds, idCount: count});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
inviteIds: [0],
|
||||
idCount: 0,
|
||||
emailErrors: {},
|
||||
firstNameErrors: {},
|
||||
lastNameErrors: {},
|
||||
emailEnabled: !ConfigStore.getSettingAsBoolean('ByPassEmail', false)
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
var currentUser = UserStore.getCurrentUser();
|
||||
}
|
||||
|
||||
var inputDisabled = '';
|
||||
if (!this.state.emailEnabled) {
|
||||
inputDisabled = 'disabled';
|
||||
}
|
||||
render() {
|
||||
var currentUser = UserStore.getCurrentUser();
|
||||
|
||||
if (currentUser != null) {
|
||||
var inviteSections = [];
|
||||
@@ -185,7 +194,13 @@ module.exports = React.createClass({
|
||||
var removeButton = null;
|
||||
if (index) {
|
||||
removeButton = (<div>
|
||||
<button type='button' className='btn btn-link remove__member' onClick={this.removeInviteFields.bind(this, index)}><span className='fa fa-trash'></span></button>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-link remove__member'
|
||||
onClick={this.removeInviteFields.bind(this, index)}
|
||||
>
|
||||
<span className='fa fa-trash'></span>
|
||||
</button>
|
||||
</div>);
|
||||
}
|
||||
var emailClass = 'form-group invite';
|
||||
@@ -206,13 +221,27 @@ module.exports = React.createClass({
|
||||
nameFields = (<div className='row--invite'>
|
||||
<div className='col-sm-6'>
|
||||
<div className={firstNameClass}>
|
||||
<input type='text' className='form-control' ref={'first_name' + index} placeholder='First name' maxLength='64' disabled={!this.state.emailEnabled}/>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
ref={'first_name' + index}
|
||||
placeholder='First name'
|
||||
maxLength='64'
|
||||
disabled={!this.state.emailEnabled}
|
||||
/>
|
||||
{firstNameError}
|
||||
</div>
|
||||
</div>
|
||||
<div className='col-sm-6'>
|
||||
<div className={lastNameClass}>
|
||||
<input type='text' className='form-control' ref={'last_name' + index} placeholder='Last name' maxLength='64' disabled={!this.state.emailEnabled}/>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
ref={'last_name' + index}
|
||||
placeholder='Last name'
|
||||
maxLength='64'
|
||||
disabled={!this.state.emailEnabled}
|
||||
/>
|
||||
{lastNameError}
|
||||
</div>
|
||||
</div>
|
||||
@@ -223,7 +252,15 @@ module.exports = React.createClass({
|
||||
<div key={'key' + index}>
|
||||
{removeButton}
|
||||
<div className={emailClass}>
|
||||
<input onKeyUp={this.displayNameKeyUp} type='text' ref={'email' + index} className='form-control' placeholder='email@domain.com' maxLength='64' disabled={!this.state.emailEnabled}/>
|
||||
<input
|
||||
onKeyUp={this.displayNameKeyUp}
|
||||
type='text'
|
||||
ref={'email' + index}
|
||||
className='form-control'
|
||||
placeholder='email@domain.com'
|
||||
maxLength='64'
|
||||
disabled={!this.state.emailEnabled}
|
||||
/>
|
||||
{emailError}
|
||||
</div>
|
||||
{nameFields}
|
||||
@@ -242,23 +279,44 @@ module.exports = React.createClass({
|
||||
content = (
|
||||
<div>
|
||||
{serverError}
|
||||
<button type='button' className='btn btn-default' onClick={this.addInviteFields}>Add another</button>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
onClick={this.addInviteFields}
|
||||
>Add another</button>
|
||||
<br/>
|
||||
<br/>
|
||||
<span>People invited automatically join Town Square channel.</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
sendButton = <button onClick={this.handleSubmit} type='button' className='btn btn-primary'>Send Invitations</button>
|
||||
sendButton =
|
||||
(
|
||||
<button
|
||||
onClick={this.handleSubmit}
|
||||
type='button'
|
||||
className='btn btn-primary'
|
||||
>Send Invitations</button>
|
||||
);
|
||||
} else {
|
||||
var teamInviteLink = null;
|
||||
if (currentUser && this.props.teamType === 'O') {
|
||||
var linkUrl = utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + currentUser.team_id;
|
||||
var link = <a href='#' data-toggle='modal' data-target='#get_link' data-title='Team Invite' data-value={linkUrl} onClick={
|
||||
function() {
|
||||
$('#invite_member').modal('hide');
|
||||
}
|
||||
}>Team Invite Link</a>;
|
||||
var link =
|
||||
(
|
||||
<a
|
||||
href='#'
|
||||
data-toggle='modal'
|
||||
data-target='#get_link'
|
||||
data-title='Team Invite'
|
||||
data-value={linkUrl}
|
||||
onClick={
|
||||
function click() {
|
||||
$('#invite_member').modal('hide');
|
||||
}
|
||||
}
|
||||
>Team Invite Link</a>
|
||||
);
|
||||
|
||||
teamInviteLink = (
|
||||
<p>
|
||||
@@ -277,22 +335,46 @@ module.exports = React.createClass({
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='modal fade' ref='modal' id='invite_member' tabIndex='-1' role='dialog' aria-hidden='true'>
|
||||
<div
|
||||
className='modal fade'
|
||||
ref='modal'
|
||||
id='invite_member'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
>
|
||||
<div className='modal-dialog'>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button type='button' className='close' data-dismiss='modal' aria-label='Close' data-reactid='.5.0.0.0.0'><span aria-hidden='true' data-reactid='.5.0.0.0.0.0'>×</span></button>
|
||||
<h4 className='modal-title' id='myModalLabel'>Invite New Member</h4>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
<h4
|
||||
className='modal-title'
|
||||
id='myModalLabel'
|
||||
>Invite New Member</h4>
|
||||
</div>
|
||||
<div ref='modalBody' className='modal-body'>
|
||||
<div
|
||||
ref='modalBody'
|
||||
className='modal-body'
|
||||
>
|
||||
<form role='form'>
|
||||
{inviteSections}
|
||||
</form>
|
||||
{content}
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button type='button' className='btn btn-default' data-dismiss='modal'>Cancel</button>
|
||||
{sendButton}
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
data-dismiss='modal'
|
||||
>Cancel</button>
|
||||
{sendButton}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -309,4 +391,8 @@ module.exports = React.createClass({
|
||||
}
|
||||
return <div/>;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
InviteMemberModal.propTypes = {
|
||||
teamType: React.PropTypes.string
|
||||
};
|
||||
|
||||
@@ -3,32 +3,45 @@
|
||||
|
||||
var MemberListItem = require('./member_list_item.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
render: function() {
|
||||
export default class MemberList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
var members = [];
|
||||
|
||||
if (this.props.memberList != null) {
|
||||
if (this.props.memberList !== null) {
|
||||
members = this.props.memberList;
|
||||
}
|
||||
|
||||
var message = "";
|
||||
if (members.length === 0)
|
||||
var message = '';
|
||||
if (members.length === 0) {
|
||||
message = <span>No users to add.</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="member-list-holder">
|
||||
{members.map(function(member) {
|
||||
return <MemberListItem
|
||||
<div className='member-list-holder'>
|
||||
{members.map(function mymembers(member) {
|
||||
return (<MemberListItem
|
||||
key={member.id}
|
||||
member={member}
|
||||
isAdmin={this.props.isAdmin}
|
||||
handleInvite={this.props.handleInvite}
|
||||
handleRemove={this.props.handleRemove}
|
||||
handleMakeAdmin={this.props.handleMakeAdmin}
|
||||
/>;
|
||||
/>);
|
||||
}, this)}
|
||||
{message}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MemberList.propTypes = {
|
||||
memberList: React.PropTypes.array,
|
||||
isAdmin: React.PropTypes.bool,
|
||||
handleInvite: React.PropTypes.func,
|
||||
handleRemove: React.PropTypes.func,
|
||||
handleMakeAdmin: React.PropTypes.func
|
||||
};
|
||||
|
||||
@@ -7,19 +7,22 @@ var Client = require('../utils/client.jsx');
|
||||
var AsyncClient = require('../utils/async_client.jsx');
|
||||
var utils = require('../utils/utils.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MoreDirectChannels',
|
||||
componentDidMount: function() {
|
||||
export default class MoreDirectChannels extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {channels: [], loadingDMChannel: -1};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function showModal(e) {
|
||||
var button = e.relatedTarget;
|
||||
self.setState({channels: $(button).data('channels')});
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {channels: [], loadingDMChannel: -1};
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
var self = this;
|
||||
|
||||
var directMessageItems = this.state.channels.map(function mapActivityToChannel(channel, index) {
|
||||
@@ -48,7 +51,12 @@ module.exports = React.createClass({
|
||||
var otherUserId = utils.getUserIdFromChannelName(channel);
|
||||
|
||||
if (self.state.loadingDMChannel === index) {
|
||||
badge = <img className='channel-loading-gif pull-right' src='/static/images/load.gif'/>;
|
||||
badge = (
|
||||
<img
|
||||
className='channel-loading-gif pull-right'
|
||||
src='/static/images/load.gif'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (self.state.loadingDMChannel === -1) {
|
||||
@@ -73,16 +81,36 @@ module.exports = React.createClass({
|
||||
}
|
||||
|
||||
return (
|
||||
<li key={channel.name} className={active}><a className={'sidebar-channel ' + titleClass} href='#' onClick={handleClick}>{badge}{channel.display_name}</a></li>
|
||||
<li
|
||||
key={channel.name}
|
||||
className={active}
|
||||
>
|
||||
<a
|
||||
className={'sidebar-channel ' + titleClass}
|
||||
href='#'
|
||||
onClick={handleClick}
|
||||
>{badge}{channel.display_name}</a>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className='modal fade' id='more_direct_channels' ref='modal' tabIndex='-1' role='dialog' aria-hidden='true'>
|
||||
<div
|
||||
className='modal fade'
|
||||
id='more_direct_channels'
|
||||
ref='modal'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
>
|
||||
<div className='modal-dialog'>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button type='button' className='close' data-dismiss='modal'>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
<span className='sr-only'>Close</span>
|
||||
</button>
|
||||
@@ -94,11 +122,15 @@ module.exports = React.createClass({
|
||||
</ul>
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button type='button' className='btn btn-default' data-dismiss='modal'>Close</button>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
data-dismiss='modal'
|
||||
>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,57 +1,70 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
|
||||
var SocketStore = require('../stores/socket_store.jsx');
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
timer: null,
|
||||
lastTime: 0,
|
||||
componentDidMount: function() {
|
||||
SocketStore.addChangeListener(this._onChange);
|
||||
},
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
if(this.props.channelId !== newProps.channelId) {
|
||||
this.setState({text:""});
|
||||
}
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
SocketStore.removeChangeListener(this._onChange);
|
||||
},
|
||||
_onChange: function(msg) {
|
||||
if (msg.action == "typing" &&
|
||||
this.props.channelId == msg.channel_id &&
|
||||
this.props.parentId == msg.props.parent_id) {
|
||||
export default class MsgTyping extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.timer = null;
|
||||
this.lastTime = 0;
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
|
||||
this.state = {
|
||||
text: ''
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
SocketStore.addChangeListener(this.onChange);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
if (this.props.channelId !== newProps.channelId) {
|
||||
this.setState({text: ''});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
SocketStore.removeChangeListener(this.onChange);
|
||||
}
|
||||
|
||||
onChange(msg) {
|
||||
if (msg.action === 'typing' &&
|
||||
this.props.channelId === msg.channel_id &&
|
||||
this.props.parentId === msg.props.parent_id) {
|
||||
this.lastTime = new Date().getTime();
|
||||
|
||||
var username = "Someone";
|
||||
var username = 'Someone';
|
||||
if (UserStore.hasProfile(msg.user_id)) {
|
||||
username = UserStore.getProfile(msg.user_id).username;
|
||||
}
|
||||
|
||||
this.setState({ text: username + " is typing..." });
|
||||
this.setState({text: username + ' is typing...'});
|
||||
|
||||
if (!this.timer) {
|
||||
var outer = this;
|
||||
outer.timer = setInterval(function() {
|
||||
if ((new Date().getTime() - outer.lastTime) > 8000) {
|
||||
outer.setState({ text: "" });
|
||||
}
|
||||
}, 3000);
|
||||
this.timer = setInterval(function myTimer() {
|
||||
if ((new Date().getTime() - this.lastTime) > 8000) {
|
||||
this.setState({text: ''});
|
||||
}
|
||||
}.bind(this), 3000);
|
||||
}
|
||||
} else if (msg.action === 'posted' && msg.channel_id === this.props.channelId) {
|
||||
this.setState({text: ''});
|
||||
}
|
||||
else if (msg.action == "posted" && msg.channel_id === this.props.channelId) {
|
||||
this.setState({text:""})
|
||||
}
|
||||
},
|
||||
getInitialState: function() {
|
||||
return { text: "" };
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span className="msg-typing">{ this.state.text }</span>
|
||||
<span className='msg-typing'>{this.state.text}</span>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MsgTyping.propTypes = {
|
||||
channelId: React.PropTypes.string,
|
||||
parentId: React.PropTypes.string
|
||||
};
|
||||
|
||||
@@ -51,8 +51,10 @@ export default class PostList extends React.Component {
|
||||
|
||||
if (deletedPosts && Object.keys(deletedPosts).length > 0) {
|
||||
for (var pid in deletedPosts) {
|
||||
postList.posts[pid] = deletedPosts[pid];
|
||||
postList.order.unshift(pid);
|
||||
if (deletedPosts.hasOwnProperty(pid)) {
|
||||
postList.posts[pid] = deletedPosts[pid];
|
||||
postList.order.unshift(pid);
|
||||
}
|
||||
}
|
||||
|
||||
postList.order.sort(function postSort(a, b) {
|
||||
@@ -71,7 +73,9 @@ export default class PostList extends React.Component {
|
||||
if (pendingPostList) {
|
||||
postList.order = pendingPostList.order.concat(postList.order);
|
||||
for (var ppid in pendingPostList.posts) {
|
||||
postList.posts[ppid] = pendingPostList.posts[ppid];
|
||||
if (pendingPostList.posts.hasOwnProperty(ppid)) {
|
||||
postList.posts[ppid] = pendingPostList.posts[ppid];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,7 +271,6 @@ export default class PostList extends React.Component {
|
||||
}
|
||||
}
|
||||
onSocketChange(msg) {
|
||||
var postList;
|
||||
var post;
|
||||
if (msg.action === 'posted' || msg.action === 'post_edited') {
|
||||
post = JSON.parse(msg.props.post);
|
||||
@@ -280,7 +283,6 @@ export default class PostList extends React.Component {
|
||||
}
|
||||
|
||||
post = JSON.parse(msg.props.post);
|
||||
postList = this.state.postList;
|
||||
|
||||
PostStore.storeUnseenDeletedPost(post);
|
||||
PostStore.removePost(post, true);
|
||||
@@ -644,11 +646,18 @@ export default class PostList extends React.Component {
|
||||
if (posts && this.state.isFirstLoadComplete) {
|
||||
postCtls = this.createPosts(posts, order);
|
||||
} else {
|
||||
postCtls.push(<LoadingScreen position='absolute' />);
|
||||
postCtls.push(
|
||||
<LoadingScreen
|
||||
position='absolute'
|
||||
key='loading'
|
||||
/>);
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref='postlist' className='post-list-holder-by-time'>
|
||||
<div
|
||||
ref='postlist'
|
||||
className='post-list-holder-by-time'
|
||||
>
|
||||
<div className='post-list__table'>
|
||||
<div className='post-list__content'>
|
||||
{moreMessages}
|
||||
@@ -658,4 +667,4 @@ export default class PostList extends React.Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,62 +3,99 @@
|
||||
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
var BrowserStore = require('../stores/browser_store.jsx')
|
||||
var BrowserStore = require('../stores/browser_store.jsx');
|
||||
var utils = require('../utils/utils.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleShow: function() {
|
||||
var newState = {};
|
||||
if(BrowserStore.getItem("channel-removed-state")) {
|
||||
newState = BrowserStore.getItem("channel-removed-state");
|
||||
BrowserStore.removeItem("channel-removed-state");
|
||||
}
|
||||
export default class RemovedFromChannelModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.setState(newState);
|
||||
},
|
||||
handleClose: function() {
|
||||
var townSquare = ChannelStore.getByName("town-square");
|
||||
utils.switchChannel(townSquare);
|
||||
this.handleShow = this.handleShow.bind(this);
|
||||
this.handleClose = this.handleClose.bind(this);
|
||||
|
||||
this.setState({channelName: "", remover: ""});
|
||||
},
|
||||
componentDidMount: function() {
|
||||
$(this.getDOMNode()).on('show.bs.modal',this.handleShow);
|
||||
$(this.getDOMNode()).on('hidden.bs.modal',this.handleClose);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
$(this.getDOMNode()).off('show.bs.modal',this.handleShow);
|
||||
$(this.getDOMNode()).off('hidden.bs.modal',this.handleClose);
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {channelName: "", remover: ""}
|
||||
},
|
||||
render: function() {
|
||||
this.state = {
|
||||
channelName: '',
|
||||
remover: ''
|
||||
};
|
||||
}
|
||||
|
||||
handleShow() {
|
||||
var newState = {};
|
||||
if (BrowserStore.getItem('channel-removed-state')) {
|
||||
newState = BrowserStore.getItem('channel-removed-state');
|
||||
BrowserStore.removeItem('channel-removed-state');
|
||||
}
|
||||
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
handleClose() {
|
||||
var townSquare = ChannelStore.getByName('town-square');
|
||||
utils.switchChannel(townSquare);
|
||||
|
||||
this.setState({channelName: '', remover: ''});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
$(React.findDOMNode(this)).on('show.bs.modal', this.handleShow);
|
||||
$(React.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);
|
||||
}
|
||||
|
||||
render() {
|
||||
var currentUser = UserStore.getCurrentUser();
|
||||
var channelName = this.state.channelName ? this.state.channelName : "the channel"
|
||||
var remover = this.state.remover ? this.state.remover : "Someone"
|
||||
|
||||
var channelName = 'the channel';
|
||||
if (this.state.channelName) {
|
||||
channelName = this.state.channelName;
|
||||
}
|
||||
|
||||
var remover = 'Someone';
|
||||
if (this.state.remover) {
|
||||
remover = this.state.remover;
|
||||
}
|
||||
|
||||
if (currentUser != null) {
|
||||
return (
|
||||
<div className='modal fade' ref='modal' id='removed_from_channel' tabIndex='-1' role='dialog' aria-hidden='true'>
|
||||
<div className='modal-dialog'>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button type='button' className='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>×</span></button>
|
||||
<h4 className='modal-title'>Removed from <span className='name'>{channelName}</span></h4>
|
||||
<div
|
||||
className='modal fade'
|
||||
ref='modal'
|
||||
id='removed_from_channel'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
>
|
||||
<div className='modal-dialog'>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
><span aria-hidden='true'>×</span></button>
|
||||
<h4 className='modal-title'>Removed from <span className='name'>{channelName}</span></h4>
|
||||
</div>
|
||||
<div className='modal-body'>
|
||||
<p>{remover} removed you from {channelName}</p>
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-primary'
|
||||
data-dismiss='modal'
|
||||
>Okay</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className='modal-body'>
|
||||
<p>{remover} removed you from {channelName}</p>
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button type='button' className='btn btn-primary' data-dismiss='modal'>Okay</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return <div/>;
|
||||
}
|
||||
|
||||
return <div/>;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -33,7 +33,9 @@ export default class RhsThread extends React.Component {
|
||||
|
||||
if (pendingPostList) {
|
||||
for (var pid in pendingPostList.posts) {
|
||||
postList.posts[pid] = pendingPostList.posts[pid];
|
||||
if (pendingPostList.posts.hasOwnProperty(pid)) {
|
||||
postList.posts[pid] = pendingPostList.posts[pid];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +83,9 @@ export default class RhsThread extends React.Component {
|
||||
if (currentPosts.posts[currentPosts.order[0]].channel_id === currentSelected.posts[currentSelected.order[0]].channel_id) {
|
||||
currentSelected.posts = {};
|
||||
for (var postId in currentPosts.posts) {
|
||||
currentSelected.posts[postId] = currentPosts.posts[postId];
|
||||
if (currentPosts.posts.hasOwnProperty(postId)) {
|
||||
currentSelected.posts[postId] = currentPosts.posts[postId];
|
||||
}
|
||||
}
|
||||
|
||||
PostStore.storeSelectedPost(currentSelected);
|
||||
@@ -128,9 +132,11 @@ export default class RhsThread extends React.Component {
|
||||
var postsArray = [];
|
||||
|
||||
for (var postId in postList.posts) {
|
||||
var cpost = postList.posts[postId];
|
||||
if (cpost.root_id === rootPost.id) {
|
||||
postsArray.push(cpost);
|
||||
if (postList.posts.hasOwnProperty(postId)) {
|
||||
var cpost = postList.posts[postId];
|
||||
if (cpost.root_id === rootPost.id) {
|
||||
postsArray.push(cpost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +215,7 @@ RhsThread.defaultProps = {
|
||||
fromSearch: '',
|
||||
isMentionSearch: false
|
||||
};
|
||||
|
||||
RhsThread.propTypes = {
|
||||
fromSearch: React.PropTypes.string,
|
||||
isMentionSearch: React.PropTypes.bool
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
module.exports = React.createClass({
|
||||
setPicture: function(file) {
|
||||
export default class SettingPicture extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.setPicture = this.setPicture.bind(this);
|
||||
}
|
||||
|
||||
setPicture(file) {
|
||||
if (file) {
|
||||
var reader = new FileReader();
|
||||
|
||||
var img = this.refs.image.getDOMNode();
|
||||
reader.onload = function(e) {
|
||||
reader.onload = function load(e) {
|
||||
$(img).attr('src', e.target.result);
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
},
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.picture) {
|
||||
this.setPicture(nextProps.picture);
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
var clientError = null;
|
||||
if (this.props.client_error) {
|
||||
clientError = <div className='form-group has-error'><label className='control-label'>{this.props.client_error}</label></div>;
|
||||
@@ -31,14 +39,31 @@ module.exports = React.createClass({
|
||||
|
||||
var img = null;
|
||||
if (this.props.picture) {
|
||||
img = (<img ref='image' className='profile-img' src=''/>);
|
||||
img = (
|
||||
<img
|
||||
ref='image'
|
||||
className='profile-img'
|
||||
src=''
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
img = (<img ref='image' className='profile-img' src={this.props.src}/>);
|
||||
img = (
|
||||
<img
|
||||
ref='image'
|
||||
className='profile-img'
|
||||
src={this.props.src}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
var confirmButton;
|
||||
if (this.props.loadingPicture) {
|
||||
confirmButton = <img className='spinner' src='/static/images/load.gif'/>;
|
||||
confirmButton = (
|
||||
<img
|
||||
className='spinner'
|
||||
src='/static/images/load.gif'
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
var confirmButtonClass = 'btn btn-sm';
|
||||
if (this.props.submitActive) {
|
||||
@@ -46,9 +71,15 @@ module.exports = React.createClass({
|
||||
} else {
|
||||
confirmButtonClass += ' btn-inactive disabled';
|
||||
}
|
||||
confirmButton = <a className={confirmButtonClass} onClick={this.props.submit}>Save</a>;
|
||||
|
||||
confirmButton = (
|
||||
<a
|
||||
className={confirmButtonClass}
|
||||
onClick={this.props.submit}
|
||||
>Save</a>
|
||||
);
|
||||
}
|
||||
var helpText = 'Upload a profile picture in either JPG or PNG format, at least ' + config.ProfileWidth + 'px in width and ' + config.ProfileHeight + 'px height.'
|
||||
var helpText = 'Upload a profile picture in either JPG or PNG format, at least ' + config.ProfileWidth + 'px in width and ' + config.ProfileHeight + 'px height.';
|
||||
|
||||
var self = this;
|
||||
return (
|
||||
@@ -65,13 +96,36 @@ module.exports = React.createClass({
|
||||
<li className='setting-list-item'>
|
||||
{serverError}
|
||||
{clientError}
|
||||
<span className='btn btn-sm btn-primary btn-file sel-btn'>Select<input ref='input' accept='.jpg,.png,.bmp' type='file' onChange={this.props.pictureChange}/></span>
|
||||
<span className='btn btn-sm btn-primary btn-file sel-btn'
|
||||
>Select<input
|
||||
ref='input'
|
||||
accept='.jpg,.png,.bmp'
|
||||
type='file'
|
||||
onChange={this.props.pictureChange}
|
||||
/>
|
||||
</span>
|
||||
{confirmButton}
|
||||
<a className='btn btn-sm theme' href='#' onClick={self.props.updateSection}>Cancel</a>
|
||||
<a
|
||||
className='btn btn-sm theme'
|
||||
href='#'
|
||||
onClick={self.props.updateSection}
|
||||
>Cancel</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SettingPicture.propTypes = {
|
||||
client_error: React.PropTypes.string,
|
||||
server_error: React.PropTypes.string,
|
||||
src: React.PropTypes.string,
|
||||
picture: React.PropTypes.object,
|
||||
loadingPicture: React.PropTypes.bool,
|
||||
submitActive: React.PropTypes.bool,
|
||||
submit: React.PropTypes.func,
|
||||
title: React.PropTypes.string,
|
||||
pictureChange: React.PropTypes.func
|
||||
};
|
||||
@@ -1,36 +1,37 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Setting Upload',
|
||||
propTypes: {
|
||||
title: React.PropTypes.string.isRequired,
|
||||
submit: React.PropTypes.func.isRequired,
|
||||
fileTypesAccepted: React.PropTypes.string.isRequired,
|
||||
clientError: React.PropTypes.string,
|
||||
serverError: React.PropTypes.string,
|
||||
helpText: React.PropTypes.string
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
export default class SettingsUpload extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.doFileSelect = this.doFileSelect.bind(this);
|
||||
this.doSubmit = this.doSubmit.bind(this);
|
||||
this.onFileSelect = this.onFileSelect.bind(this);
|
||||
|
||||
this.state = {
|
||||
clientError: this.props.clientError,
|
||||
serverError: this.props.serverError
|
||||
};
|
||||
},
|
||||
componentWillReceiveProps: function() {
|
||||
}
|
||||
|
||||
componentWillReceiveProps() {
|
||||
this.setState({
|
||||
clientError: this.props.clientError,
|
||||
serverError: this.props.serverError
|
||||
});
|
||||
},
|
||||
doFileSelect: function(e) {
|
||||
}
|
||||
|
||||
doFileSelect(e) {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
clientError: '',
|
||||
serverError: ''
|
||||
});
|
||||
},
|
||||
doSubmit: function(e) {
|
||||
}
|
||||
|
||||
doSubmit(e) {
|
||||
e.preventDefault();
|
||||
var inputnode = this.refs.uploadinput.getDOMNode();
|
||||
if (inputnode.files && inputnode.files[0]) {
|
||||
@@ -38,16 +39,18 @@ module.exports = React.createClass({
|
||||
} else {
|
||||
this.setState({clientError: 'No file selected.'});
|
||||
}
|
||||
},
|
||||
onFileSelect: function(e) {
|
||||
}
|
||||
|
||||
onFileSelect(e) {
|
||||
var filename = $(e.target).val();
|
||||
if (filename.substring(3, 11) === 'fakepath') {
|
||||
filename = filename.substring(12);
|
||||
}
|
||||
$(e.target).closest('li').find('.file-status').addClass('hide');
|
||||
$(e.target).closest('li').find('.file-name').removeClass('hide').html(filename);
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
var clientError = null;
|
||||
if (this.state.clientError) {
|
||||
clientError = (
|
||||
@@ -67,7 +70,11 @@ module.exports = React.createClass({
|
||||
<li className='col-xs-offset-3 col-xs-8'>
|
||||
<ul className='setting-list'>
|
||||
<li className='setting-list-item'>
|
||||
<span className='btn btn-sm btn-primary btn-file sel-btn'>Select file<input ref='uploadinput' accept={this.props.fileTypesAccepted} type='file' onChange={this.onFileSelect}/></span>
|
||||
<span className='btn btn-sm btn-primary btn-file sel-btn'>Select file<input
|
||||
ref='uploadinput'
|
||||
accept={this.props.fileTypesAccepted}
|
||||
type='file'
|
||||
onChange={this.onFileSelect}/></span>
|
||||
<a
|
||||
className={'btn btn-sm btn-primary'}
|
||||
onClick={this.doSubmit}>
|
||||
@@ -82,4 +89,13 @@ module.exports = React.createClass({
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SettingsUpload.propTypes = {
|
||||
title: React.PropTypes.string.isRequired,
|
||||
submit: React.PropTypes.func.isRequired,
|
||||
fileTypesAccepted: React.PropTypes.string.isRequired,
|
||||
clientError: React.PropTypes.string,
|
||||
serverError: React.PropTypes.string,
|
||||
helpText: React.PropTypes.object
|
||||
};
|
||||
@@ -5,12 +5,19 @@ var UserStore = require('../stores/user_store.jsx');
|
||||
var client = require('../utils/client.jsx');
|
||||
var utils = require('../utils/utils.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleLogoutClick: function(e) {
|
||||
export default class SidebarRightMenu extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleLogoutClick = this.handleLogoutClick.bind(this);
|
||||
}
|
||||
|
||||
handleLogoutClick(e) {
|
||||
e.preventDefault();
|
||||
client.logout();
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
var teamLink = '';
|
||||
var inviteLink = '';
|
||||
var teamSettingsLink = '';
|
||||
@@ -23,14 +30,22 @@ module.exports = React.createClass({
|
||||
|
||||
inviteLink = (
|
||||
<li>
|
||||
<a href='#' data-toggle='modal' data-target='#invite_member'><i className='glyphicon glyphicon-user'></i>Invite New Member</a>
|
||||
<a href='#'
|
||||
data-toggle='modal'
|
||||
data-target='#invite_member'
|
||||
><i className='glyphicon glyphicon-user'></i>Invite New Member</a>
|
||||
</li>
|
||||
);
|
||||
|
||||
if (this.props.teamType === 'O') {
|
||||
teamLink = (
|
||||
<li>
|
||||
<a href='#' data-toggle='modal' data-target='#get_link' data-title='Team Invite' data-value={utils.getWindowLocationOrigin()+'/signup_user_complete/?id='+currentUser.team_id}><i className='glyphicon glyphicon-link'></i>Get Team Invite Link</a>
|
||||
<a href='#'
|
||||
data-toggle='modal'
|
||||
data-target='#get_link'
|
||||
data-title='Team Invite'
|
||||
data-value={utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + currentUser.team_id}
|
||||
><i className='glyphicon glyphicon-link'></i>Get Team Invite Link</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
@@ -39,12 +54,20 @@ module.exports = React.createClass({
|
||||
if (isAdmin) {
|
||||
teamSettingsLink = (
|
||||
<li>
|
||||
<a href='#' data-toggle='modal' data-target='#team_settings'><i className='glyphicon glyphicon-globe'></i>Team Settings</a>
|
||||
<a
|
||||
href='#'
|
||||
data-toggle='modal'
|
||||
data-target='#team_settings'
|
||||
><i className='glyphicon glyphicon-globe'></i>Team Settings</a>
|
||||
</li>
|
||||
);
|
||||
manageLink = (
|
||||
<li>
|
||||
<a href='#' data-toggle='modal' data-target='#team_members'><i className='glyphicon glyphicon-wrench'></i>Manage Team</a>
|
||||
<a
|
||||
href='#'
|
||||
data-toggle='modal'
|
||||
data-target='#team_members'
|
||||
><i className='glyphicon glyphicon-wrench'></i>Manage Team</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
@@ -61,23 +84,48 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<div className='team__header theme'>
|
||||
<a className='team__name' href='/channels/town-square'>{teamDisplayName}</a>
|
||||
<a
|
||||
className='team__name'
|
||||
href='/channels/town-square'
|
||||
>{teamDisplayName}</a>
|
||||
</div>
|
||||
|
||||
<div className='nav-pills__container'>
|
||||
<ul className='nav nav-pills nav-stacked'>
|
||||
<li><a href='#' data-toggle='modal' data-target='#user_settings'><i className='glyphicon glyphicon-cog'></i>Account Settings</a></li>
|
||||
<li>
|
||||
<a
|
||||
href='#'
|
||||
data-toggle='modal'
|
||||
data-target='#user_settings'
|
||||
><i className='glyphicon glyphicon-cog'></i>Account Settings</a></li>
|
||||
{teamSettingsLink}
|
||||
{inviteLink}
|
||||
{teamLink}
|
||||
{manageLink}
|
||||
<li><a href='#' onClick={this.handleLogoutClick}><i className='glyphicon glyphicon-log-out'></i>Logout</a></li>
|
||||
<li>
|
||||
<a
|
||||
href='#'
|
||||
onClick={this.handleLogoutClick}
|
||||
><i className='glyphicon glyphicon-log-out'></i>Logout</a></li>
|
||||
<li className='divider'></li>
|
||||
<li><a target='_blank' href='/static/help/configure_links.html'><i className='glyphicon glyphicon-question-sign'></i>Help</a></li>
|
||||
<li><a target='_blank' href='/static/help/configure_links.html'><i className='glyphicon glyphicon-earphone'></i>Report a Problem</a></li>
|
||||
<li>
|
||||
<a
|
||||
target='_blank'
|
||||
href='/static/help/configure_links.html'
|
||||
><i className='glyphicon glyphicon-question-sign'></i>Help</a></li>
|
||||
<li>
|
||||
<a
|
||||
target='_blank'
|
||||
href='/static/help/configure_links.html'
|
||||
><i className='glyphicon glyphicon-earphone'></i>Report a Problem</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SidebarRightMenu.propTypes = {
|
||||
teamType: React.PropTypes.string,
|
||||
teamDisplayName: React.PropTypes.string
|
||||
};
|
||||
@@ -4,26 +4,38 @@
|
||||
var utils = require('../utils/utils.jsx');
|
||||
var SettingUpload = require('./setting_upload.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Import Tab',
|
||||
getInitialState: function() {
|
||||
return {status: 'ready', link: ''};
|
||||
},
|
||||
onImportFailure: function() {
|
||||
export default class TeamImportTab extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onImportFailure = this.onImportFailure.bind(this);
|
||||
this.onImportSuccess = this.onImportSuccess.bind(this);
|
||||
this.doImportSlack = this.doImportSlack.bind(this);
|
||||
|
||||
this.state = {
|
||||
status: 'ready',
|
||||
link: ''
|
||||
};
|
||||
}
|
||||
|
||||
onImportFailure() {
|
||||
this.setState({status: 'fail', link: ''});
|
||||
},
|
||||
onImportSuccess: function(data) {
|
||||
}
|
||||
|
||||
onImportSuccess(data) {
|
||||
this.setState({status: 'done', link: 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(data)});
|
||||
},
|
||||
doImportSlack: function(file) {
|
||||
}
|
||||
|
||||
doImportSlack(file) {
|
||||
this.setState({status: 'in-progress', link: ''});
|
||||
utils.importSlack(file, this.onImportSuccess, this.onImportFailure);
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
var uploadHelpText = (
|
||||
<div>
|
||||
<br/>
|
||||
Slack does not allow you to export files, images, private groups or direct messages stored in Slack. Therefore, Slack import to Mattermost only supports importing of text messages in your Slack team's public channels.
|
||||
Slack does not allow you to export files, images, private groups or direct messages stored in Slack. Therefore, Slack import to Mattermost only supports importing of text messages in your Slack team's public channels.
|
||||
<br/><br/>
|
||||
The Slack import to Mattermost is in "Preview". Slack bot posts and channels with underscores do not yet import.
|
||||
<br/><br/>
|
||||
@@ -39,22 +51,25 @@ module.exports = React.createClass({
|
||||
|
||||
var messageSection;
|
||||
switch (this.state.status) {
|
||||
case 'ready':
|
||||
messageSection = '';
|
||||
|
||||
case 'ready':
|
||||
messageSection = '';
|
||||
break;
|
||||
case 'in-progress':
|
||||
messageSection = (
|
||||
<p className="confirm-import alert alert-warning"><i className="fa fa-spinner fa-pulse"></i> Importing...</p>
|
||||
case 'in-progress':
|
||||
messageSection = (
|
||||
<p className='confirm-import alert alert-warning'><i className='fa fa-spinner fa-pulse'></i> Importing...</p>
|
||||
);
|
||||
break;
|
||||
case 'done':
|
||||
messageSection = (
|
||||
<p className="confirm-import alert alert-success"><i className="fa fa-check"></i> Import successful: <a href={this.state.link} download='MattermostImportSummary.txt'>View Summary</a></p>
|
||||
case 'done':
|
||||
messageSection = (
|
||||
<p className='confirm-import alert alert-success'><i className='fa fa-check'></i> Import successful: <a href={this.state.link}
|
||||
download='MattermostImportSummary.txt'>View Summary</a></p>
|
||||
);
|
||||
break;
|
||||
case 'fail':
|
||||
messageSection = (
|
||||
<p className="confirm-import alert alert-warning"><i className="fa fa-warning"></i> Import failure: <a href={this.state.link} download='MattermostImportSummary.txt'>View Summary</a></p>
|
||||
case 'fail':
|
||||
messageSection = (
|
||||
<p className='confirm-import alert alert-warning'><i className='fa fa-warning'></i> Import failure: <a href={this.state.link}
|
||||
download='MattermostImportSummary.txt'>View Summary</a></p>
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -62,10 +77,22 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<div className='modal-header'>
|
||||
<button type='button' className='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>×</span></button>
|
||||
<h4 className='modal-title' ref='title'><i className='modal-back'></i>Import</h4>
|
||||
<button type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
<h4
|
||||
className='modal-title'
|
||||
ref='title'
|
||||
><i className='modal-back'></i>Import</h4>
|
||||
</div>
|
||||
<div ref='wrapper' className='user-settings'>
|
||||
<div
|
||||
ref='wrapper'
|
||||
className='user-settings'
|
||||
>
|
||||
<h3 className='tab-header'>Import</h3>
|
||||
<div className='divider-dark first'/>
|
||||
{uploadSection}
|
||||
@@ -75,4 +102,4 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,77 +2,131 @@
|
||||
// See License.txt for license information.
|
||||
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
var MemberListTeam = require('./member_list_team.jsx');
|
||||
var Client = require('../utils/client.jsx');
|
||||
var utils = require('../utils/utils.jsx');
|
||||
|
||||
function getStateFromStores() {
|
||||
var users = UserStore.getProfiles();
|
||||
var member_list = [];
|
||||
for (var id in users) member_list.push(users[id]);
|
||||
var memberList = [];
|
||||
for (var id in users) {
|
||||
if (users.hasOwnProperty(id)) {
|
||||
memberList.push(users[id]);
|
||||
}
|
||||
}
|
||||
|
||||
memberList.sort(function sort(a, b) {
|
||||
if (a.username < b.username) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a.username > b.username) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
member_list.sort(function(a,b) {
|
||||
if (a.username < b.username) return -1;
|
||||
if (a.username > b.username) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
return {
|
||||
member_list: member_list
|
||||
member_list: memberList
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = React.createClass({
|
||||
componentDidMount: function() {
|
||||
UserStore.addChangeListener(this._onChange);
|
||||
export default class TeamMembers extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
|
||||
this.state = getStateFromStores();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
UserStore.addChangeListener(this.onChange);
|
||||
|
||||
var self = this;
|
||||
$(this.refs.modal.getDOMNode()).on('hidden.bs.modal', function(e) {
|
||||
self.setState({ render_members: false });
|
||||
$(this.refs.modal.getDOMNode()).on('hidden.bs.modal', function show() {
|
||||
self.setState({render_members: false});
|
||||
});
|
||||
|
||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
|
||||
self.setState({ render_members: true });
|
||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function hide() {
|
||||
self.setState({render_members: true});
|
||||
});
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
UserStore.removeChangeListener(this._onChange);
|
||||
},
|
||||
_onChange: function() {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
UserStore.removeChangeListener(this.onChange);
|
||||
}
|
||||
|
||||
onChange() {
|
||||
var newState = getStateFromStores();
|
||||
if (!utils.areStatesEqual(newState, this.state)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
},
|
||||
getInitialState: function() {
|
||||
return getStateFromStores();
|
||||
},
|
||||
render: function() {
|
||||
var server_error = this.state.server_error ? <label className='has-error control-label'>{this.state.server_error}</label> : null;
|
||||
}
|
||||
|
||||
render() {
|
||||
var serverError = null;
|
||||
|
||||
if (this.state.server_error) {
|
||||
serverError = <label className='has-error control-label'>{this.state.server_error}</label>;
|
||||
}
|
||||
|
||||
var renderMembers = '';
|
||||
|
||||
if (this.state.render_members) {
|
||||
renderMembers = <MemberListTeam users={this.state.member_list} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="modal fade" ref="modal" id="team_members" tabIndex="-1" role="dialog" aria-hidden="true">
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<button type="button" className="close" data-dismiss="modal" aria-label="Close" data-reactid=".5.0.0.0.0"><span aria-hidden="true" data-reactid=".5.0.0.0.0.0">×</span></button>
|
||||
<h4 className="modal-title" id="myModalLabel">{this.props.teamDisplayName + " Members"}</h4>
|
||||
</div>
|
||||
<div ref="modalBody" className="modal-body">
|
||||
<div className="channel-settings">
|
||||
<div className="team-member-list">
|
||||
{ this.state.render_members ? <MemberListTeam users={this.state.member_list} /> : "" }
|
||||
<div
|
||||
className='modal fade'
|
||||
ref='modal'
|
||||
id='team_members'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
>
|
||||
<div className='modal-dialog'>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
<h4
|
||||
className='modal-title'
|
||||
id='myModalLabel'
|
||||
>{this.props.teamDisplayName + ' Members'}</h4>
|
||||
</div>
|
||||
<div
|
||||
ref='modalBody'
|
||||
className='modal-body'
|
||||
>
|
||||
<div className='channel-settings'>
|
||||
<div className='team-member-list'>
|
||||
{renderMembers}
|
||||
</div>
|
||||
{serverError}
|
||||
</div>
|
||||
{ server_error }
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
data-dismiss='modal'
|
||||
>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TeamMembers.propTypes = {
|
||||
teamDisplayName: React.PropTypes.string
|
||||
};
|
||||
|
||||
@@ -8,56 +8,82 @@ var SecurityTab = require('./user_settings_security.jsx');
|
||||
var GeneralTab = require('./user_settings_general.jsx');
|
||||
var AppearanceTab = require('./user_settings_appearance.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'UserSettings',
|
||||
propTypes: {
|
||||
activeTab: React.PropTypes.string,
|
||||
activeSection: React.PropTypes.string,
|
||||
updateSection: React.PropTypes.func,
|
||||
updateTab: React.PropTypes.func
|
||||
},
|
||||
componentDidMount: function() {
|
||||
export default class UserSettings extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onListenerChange = this.onListenerChange.bind(this);
|
||||
|
||||
this.state = {user: UserStore.getCurrentUser()};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
UserStore.addChangeListener(this.onListenerChange);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
UserStore.removeChangeListener(this.onListenerChange);
|
||||
},
|
||||
onListenerChange: function () {
|
||||
}
|
||||
|
||||
onListenerChange() {
|
||||
var user = UserStore.getCurrentUser();
|
||||
if (!utils.areStatesEqual(this.state.user, user)) {
|
||||
this.setState({user: user});
|
||||
}
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {user: UserStore.getCurrentUser()};
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.activeTab === 'general') {
|
||||
return (
|
||||
<div>
|
||||
<GeneralTab user={this.state.user} activeSection={this.props.activeSection} updateSection={this.props.updateSection} />
|
||||
<GeneralTab
|
||||
user={this.state.user}
|
||||
activeSection={this.props.activeSection}
|
||||
updateSection={this.props.updateSection}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.activeTab === 'security') {
|
||||
return (
|
||||
<div>
|
||||
<SecurityTab user={this.state.user} activeSection={this.props.activeSection} updateSection={this.props.updateSection} updateTab={this.props.updateTab} />
|
||||
<SecurityTab
|
||||
user={this.state.user}
|
||||
activeSection={this.props.activeSection}
|
||||
updateSection={this.props.updateSection}
|
||||
updateTab={this.props.updateTab}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.activeTab === 'notifications') {
|
||||
return (
|
||||
<div>
|
||||
<NotificationsTab user={this.state.user} activeSection={this.props.activeSection} updateSection={this.props.updateSection} updateTab={this.props.updateTab} />
|
||||
<NotificationsTab
|
||||
user={this.state.user}
|
||||
activeSection={this.props.activeSection}
|
||||
updateSection={this.props.updateSection}
|
||||
updateTab={this.props.updateTab}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.activeTab === 'appearance') {
|
||||
return (
|
||||
<div>
|
||||
<AppearanceTab activeSection={this.props.activeSection} updateSection={this.props.updateSection} updateTab={this.props.updateTab} />
|
||||
<AppearanceTab
|
||||
activeSection={this.props.activeSection}
|
||||
updateSection={this.props.updateSection}
|
||||
updateTab={this.props.updateTab}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return <div/>;
|
||||
}
|
||||
|
||||
return <div/>;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
UserSettings.propTypes = {
|
||||
activeTab: React.PropTypes.string,
|
||||
activeSection: React.PropTypes.string,
|
||||
updateSection: React.PropTypes.func,
|
||||
updateTab: React.PropTypes.func
|
||||
};
|
||||
Reference in New Issue
Block a user