summaryrefslogtreecommitdiffstats
path: root/web/react
diff options
context:
space:
mode:
Diffstat (limited to 'web/react')
-rw-r--r--web/react/components/confirm_modal.jsx31
-rw-r--r--web/react/components/create_comment.jsx2
-rw-r--r--web/react/components/create_post.jsx6
-rw-r--r--web/react/components/invite_member_modal.jsx120
-rw-r--r--web/react/components/login.jsx10
-rw-r--r--web/react/components/post_body.jsx16
-rw-r--r--web/react/components/signup_team_complete.jsx3
-rw-r--r--web/react/components/signup_user_complete.jsx1
-rw-r--r--web/react/components/textbox.jsx2
-rw-r--r--web/react/components/user_settings.jsx4
-rw-r--r--web/react/utils/constants.jsx1
-rw-r--r--web/react/utils/utils.jsx30
12 files changed, 161 insertions, 65 deletions
diff --git a/web/react/components/confirm_modal.jsx b/web/react/components/confirm_modal.jsx
new file mode 100644
index 000000000..3be13cf9b
--- /dev/null
+++ b/web/react/components/confirm_modal.jsx
@@ -0,0 +1,31 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+module.exports = React.createClass({
+ handleConfirm: function() {
+ $('#'+this.props.parent_id).attr('data-confirm', 'true');
+ $('#'+this.props.parent_id).modal('hide');
+ $('#'+this.props.id).modal('hide');
+ },
+ render: function() {
+ return (
+ <div className="modal fade" id={this.props.id} tabIndex="-1" role="dialog" aria-hidden="true">
+ <div className="modal-dialog">
+ <div className="modal-content">
+ <div className="modal-header">
+ <h4 className="modal-title">{this.props.title}</h4>
+ </div>
+ <div className="modal-body">
+ {this.props.message}
+ </div>
+ <div className="modal-footer">
+ <button type="button" className="btn btn-default" data-dismiss="modal">Cancel</button>
+ <button onClick={this.handleConfirm} type="button" className="btn btn-primary">{this.props.confirm_button}</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+});
+
diff --git a/web/react/components/create_comment.jsx b/web/react/components/create_comment.jsx
index 9bcbad079..cb7aa371c 100644
--- a/web/react/components/create_comment.jsx
+++ b/web/react/components/create_comment.jsx
@@ -145,7 +145,7 @@ module.exports = React.createClass({
onUserInput={this.handleUserInput}
onKeyPress={this.commentMsgKeyPress}
messageText={this.state.messageText}
- createMessage="Create a comment..."
+ createMessage="Add a comment..."
initialText=""
id="reply_textbox"
ref="textbox" />
diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx
index 191be9bf8..5a0b6f85f 100644
--- a/web/react/components/create_post.jsx
+++ b/web/react/components/create_post.jsx
@@ -31,9 +31,7 @@ module.exports = React.createClass({
post.message = this.state.messageText;
- var repRegex = new RegExp("<br>", "g");
- if (post.message.replace(repRegex, " ").trim().length === 0
- && this.state.previews.length === 0) {
+ if (post.message.trim().length === 0 && this.state.previews.length === 0) {
return;
}
@@ -250,7 +248,7 @@ module.exports = React.createClass({
onUserInput={this.handleUserInput}
onKeyPress={this.postMsgKeyPress}
messageText={this.state.messageText}
- createMessage="Create a post..."
+ createMessage="Write a message..."
channelId={this.state.channel_id}
id="post_textbox"
ref="textbox" />
diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx
index 1d2bbed84..5980664de 100644
--- a/web/react/components/invite_member_modal.jsx
+++ b/web/react/components/invite_member_modal.jsx
@@ -4,8 +4,37 @@
var utils = require('../utils/utils.jsx');
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() {
+ var self = this;
+ $('#invite_member').on('hide.bs.modal', function(e) {
+ if ($('#invite_member').attr('data-confirm') === 'true') {
+ $('#invite_member').attr('data-confirm', 'false');
+ return;
+ }
+
+ var not_empty = false;
+ for (var i = 0; i < self.state.invite_ids.length; i++) {
+ var index = self.state.invite_ids[i];
+ if (self.refs["email"+index].getDOMNode().value.trim() !== '') {
+ not_empty = true;
+ break;
+ }
+ }
+
+ if (not_empty) {
+ $('#confirm_invite_modal').modal('show');
+ e.preventDefault();
+ }
+
+ });
+
+ $('#invite_member').on('hidden.bs.modal', function() {
+ self.clearFields();
+ });
+ },
handleSubmit: function(e) {
var invite_ids = this.state.invite_ids;
var count = invite_ids.length;
@@ -56,22 +85,8 @@ module.exports = React.createClass({
Client.inviteMembers(data,
function() {
+ $(this.refs.modal.getDOMNode()).attr('data-confirm', 'true');
$(this.refs.modal.getDOMNode()).modal('hide');
- for (var i = 0; i < invite_ids.length; i++) {
- var index = invite_ids[i];
- this.refs["email"+index].getDOMNode().value = "";
- if (config.AllowInviteNames) {
- this.refs["first_name"+index].getDOMNode().value = "";
- this.refs["last_name"+index].getDOMNode().value = "";
- }
- }
- this.setState({
- invite_ids: [0],
- id_count: 0,
- email_errors: {},
- first_name_errors: {},
- last_name_errors: {}
- });
}.bind(this),
function(err) {
this.setState({ server_error: err });
@@ -89,6 +104,26 @@ module.exports = React.createClass({
invite_ids.push(count);
this.setState({ invite_ids: invite_ids, id_count: count });
},
+ clearFields: function() {
+ var invite_ids = this.state.invite_ids;
+
+ for (var i = 0; i < invite_ids.length; i++) {
+ var index = invite_ids[i];
+ this.refs["email"+index].getDOMNode().value = "";
+ if (config.AllowInviteNames) {
+ this.refs["first_name"+index].getDOMNode().value = "";
+ this.refs["last_name"+index].getDOMNode().value = "";
+ }
+ }
+
+ this.setState({
+ invite_ids: [0],
+ id_count: 0,
+ email_errors: {},
+ first_name_errors: {},
+ last_name_errors: {}
+ });
+ },
removeInviteFields: function(index) {
var invite_ids = this.state.invite_ids;
var i = invite_ids.indexOf(index);
@@ -147,29 +182,38 @@ module.exports = React.createClass({
var server_error = this.state.server_error ? <div className='form-group has-error'><label className='control-label'>{ this.state.server_error }</label></div> : null;
return (
- <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>
- </div>
- <div ref="modalBody" className="modal-body">
- <form role="form">
- { invite_sections }
- </form>
- { server_error }
- <button type="button" className="btn btn-default" onClick={this.addInviteFields}>Add another</button>
- <br/>
- <br/>
- <label className='control-label'>People invited automatically join Town Square channel.</label>
- </div>
- <div className="modal-footer">
- <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
- <button onClick={this.handleSubmit} type="button" className="btn btn-primary">Send Invitations</button>
- </div>
- </div>
- </div>
+ <div>
+ <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>
+ </div>
+ <div ref="modalBody" className="modal-body">
+ <form role="form">
+ { invite_sections }
+ </form>
+ { server_error }
+ <button type="button" className="btn btn-default" onClick={this.addInviteFields}>Add another</button>
+ <br/>
+ <br/>
+ <label className='control-label'>People invited automatically join Town Square channel.</label>
+ </div>
+ <div className="modal-footer">
+ <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
+ <button onClick={this.handleSubmit} type="button" className="btn btn-primary">Send Invitations</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ <ConfirmModal
+ id="confirm_invite_modal"
+ parent_id="invite_member"
+ title="Discard Invitations?"
+ message="You have unsent invitations, are you sure you want to discard them?"
+ confirm_button="Yes, Discard"
+ />
</div>
);
} else {
diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx
index 8d82a4b62..65f1da1f8 100644
--- a/web/react/components/login.jsx
+++ b/web/react/components/login.jsx
@@ -52,20 +52,20 @@ var FindTeamDomain = React.createClass({
<div>
<span className="signup-team__name">{ config.SiteName }</span>
<br/>
- <span className="signup-team__subdomain">Enter your {strings.TeamPlural} domain.</span>
+ <span className="signup-team__subdomain">Enter your {strings.Team}'s domain.</span>
<br/>
<br/>
</div>
<form onSubmit={this.handleSubmit}>
<div className={server_error ? 'form-group has-error' : 'form-group'}>
{ server_error }
- <input type="text" className="form-control" name="domain" ref="domain" placeholder="teamdomain" />
+ <input type="text" className="form-control" name="domain" ref="domain" placeholder="team domain" />
</div>
<div className="form-group">
<button type="submit" className="btn btn-primary">Continue</button>
</div>
<div>
- <span>Don't remember your {strings.TeamPlural} domain? <a href="/find_team">Find it here</a></span>
+ <span>Don't remember your {strings.Team}'s domain? <a href="/find_team">Find it here</a></span>
</div>
<br/>
<br/>
@@ -74,7 +74,7 @@ var FindTeamDomain = React.createClass({
<br/>
<br/>
<div>
- <span>{"Want to create your own " + strings.Team + "?"} <a href="/" className="signup-team-login">Sign up now</a></span>
+ <span>{"Want to create your own " + strings.Team + "?"} <a href={utils.getHomeLink()} className="signup-team-login">Sign up now</a></span>
</div>
</form>
</div>
@@ -188,7 +188,7 @@ module.exports = React.createClass({
<a href="/reset_password">I forgot my password</a>
</div>
<div className="external-link">
- <span>{"Want to create your own " + strings.Team + "?"} <a href={config.HomeLink} className="signup-team-login">Sign up now</a></span>
+ <span>{"Want to create your own " + strings.Team + "?"} <a href={utils.getHomeLink()} className="signup-team-login">Sign up now</a></span>
</div>
</form>
</div>
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx
index 55fc32c33..3079917ec 100644
--- a/web/react/components/post_body.jsx
+++ b/web/react/components/post_body.jsx
@@ -85,20 +85,22 @@ module.exports = React.createClass({
var postFiles = [];
var images = [];
if (filenames) {
- for (var i = 0; i < filenames.length && i < Constants.MAX_DISPLAY_FILES; i++) {
+ for (var i = 0; i < filenames.length; i++) {
var fileInfo = utils.splitFileLocation(filenames[i]);
if (Object.keys(fileInfo).length === 0) continue;
var type = utils.getFileType(fileInfo.ext);
if (type === "image") {
- postFiles.push(
- <div className="post-image__column" key={filenames[i]}>
- <a href="#" onClick={this.handleImageClick} data-img-id={images.length.toString()} data-toggle="modal" data-target={"#" + postImageModalId }><div ref={filenames[i]} className="post__load" style={{backgroundImage: 'url(/static/images/load.gif)'}}></div></a>
- </div>
- );
+ if (i < Constants.MAX_DISPLAY_FILES) {
+ postFiles.push(
+ <div className="post-image__column" key={filenames[i]}>
+ <a href="#" onClick={this.handleImageClick} data-img-id={images.length.toString()} data-toggle="modal" data-target={"#" + postImageModalId }><div ref={filenames[i]} className="post__load" style={{backgroundImage: 'url(/static/images/load.gif)'}}></div></a>
+ </div>
+ );
+ }
images.push(filenames[i]);
- } else {
+ } else if (i < Constants.MAX_DISPLAY_FILES) {
postFiles.push(
<div className="post-image__column custom-file" key={fileInfo.name}>
<a href={fileInfo.path+"."+fileInfo.ext} download={fileInfo.name+"."+fileInfo.ext}>
diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx
index 066161a10..b038679e6 100644
--- a/web/react/components/signup_team_complete.jsx
+++ b/web/react/components/signup_team_complete.jsx
@@ -467,7 +467,8 @@ UsernamePage = React.createClass({
</div>
{ name_error }
</div>
- <p>{"Pick something " + strings.Team + "mates will recognize. Your username is how you will appear to others"}</p>
+ <p>{"Pick something " + strings.Team + "mates will recognize. Your username is how you will appear to others."}</p>
+ <p>It can be made of lowercase letters and numbers.</p>
<button className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button>&nbsp;
<button className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button>
</div>
diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx
index 0fcdc92b0..146419cf5 100644
--- a/web/react/components/signup_user_complete.jsx
+++ b/web/react/components/signup_user_complete.jsx
@@ -120,6 +120,7 @@ module.exports = React.createClass({
<img className="signup-team-logo" src="/static/images/logo.png" />
<h4>Welcome to { config.SiteName }</h4>
<p>{"Choose your username and password for the " + this.props.team_name + " " + strings.Team +"."}</p>
+ <p>Your username can be made of lowercase letters and numbers.</p>
<label className="control-label">Username</label>
<div className={ name_error ? "form-group has-error" : "form-group" }>
<input type="text" ref="name" className="form-control" placeholder="" maxLength="128" />
diff --git a/web/react/components/textbox.jsx b/web/react/components/textbox.jsx
index 45798809f..7a4762e07 100644
--- a/web/react/components/textbox.jsx
+++ b/web/react/components/textbox.jsx
@@ -204,7 +204,7 @@ module.exports = React.createClass({
// If there is a space after the last @, nothing to do.
if (lastSpace > atIndex || lastCharSpace > atIndex) {
- this.setState({ mentionText: '-1' });
+ this.updateMentionTab('-1', null);
return;
}
diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx
index 5e9504c2d..7d542a8b7 100644
--- a/web/react/components/user_settings.jsx
+++ b/web/react/components/user_settings.jsx
@@ -1057,7 +1057,7 @@ var AppearanceTab = React.createClass({
themeSection = (
<SettingItemMax
- title="Theme"
+ title="Theme Color"
inputs={inputs}
submit={this.submitTheme}
server_error={server_error}
@@ -1067,7 +1067,7 @@ var AppearanceTab = React.createClass({
} else {
themeSection = (
<SettingItemMin
- title="Theme"
+ title="Theme Color"
describe={this.state.theme}
updateSection={function(){self.props.updateSection("theme");}}
/>
diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx
index 0a3b1db3d..deb07409b 100644
--- a/web/react/utils/constants.jsx
+++ b/web/react/utils/constants.jsx
@@ -61,6 +61,7 @@ module.exports = {
"channel",
"internal",
"localhost",
+ "dockerhost",
"stag",
"post",
"cluster",
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index 72ed48faf..fb4f3a34e 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -28,6 +28,9 @@ module.exports.isTestDomain = function() {
if ((/^localhost/).test(window.location.hostname))
return true;
+ if ((/^dockerhost/).test(window.location.hostname))
+ return true;
+
if ((/^test/).test(window.location.hostname))
return true;
@@ -75,8 +78,14 @@ module.exports.getDomainWithOutSub = function() {
var parts = window.location.host.split(".");
- if (parts.length == 1)
- return "localhost:8065";
+ if (parts.length == 1) {
+ if (parts[0].indexOf("dockerhost") > -1) {
+ return "dockerhost:8065";
+ }
+ else {
+ return "localhost:8065";
+ }
+ }
return parts[1] + "." + parts[2];
}
@@ -357,9 +366,6 @@ module.exports.textToJsx = function(text, options) {
if (options && options['singleline']) {
var repRegex = new RegExp("\n", "g");
text = text.replace(repRegex, " ");
- } else {
- var repRegex = new RegExp("\n", "g");
- text = text.replace(repRegex, "<br>");
}
var searchTerm = ""
@@ -383,7 +389,7 @@ module.exports.textToJsx = function(text, options) {
implicitKeywords[keywordArray[i]] = true;
}
- var lines = text.split("<br>");
+ var lines = text.split("\n");
var urlMatcher = new LinkifyIt();
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
@@ -730,3 +736,15 @@ Image.prototype.load = function(url, progressCallback) {
};
Image.prototype.completedPercentage = 0;
+
+module.exports.getHomeLink = function() {
+ if (config.HomeLink != "") {
+ return config.HomeLink;
+ }
+ var parts = window.location.host.split(".");
+ if (parts.length <= 1) {
+ return window.location.protocol + "//" + window.location.host;
+ }
+ parts[0] = "www";
+ return window.location.protocol + "//" + parts.join(".");
+}