summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/react/components/docs.jsx41
-rw-r--r--web/react/components/posts_view.jsx17
-rw-r--r--web/react/components/textbox.jsx15
-rw-r--r--web/react/pages/docs.jsx16
-rw-r--r--web/react/stores/browser_store.jsx2
-rw-r--r--web/react/utils/async_client.jsx2
-rw-r--r--web/sass-files/sass/partials/_post.scss53
-rw-r--r--web/sass-files/sass/partials/_responsive.scss118
l---------web/static/help/Messaging.md1
-rw-r--r--web/templates/docs.html24
-rw-r--r--web/web.go11
11 files changed, 228 insertions, 72 deletions
diff --git a/web/react/components/docs.jsx b/web/react/components/docs.jsx
new file mode 100644
index 000000000..68baa6dad
--- /dev/null
+++ b/web/react/components/docs.jsx
@@ -0,0 +1,41 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+const TextFormatting = require('../utils/text_formatting.jsx');
+const UserStore = require('../stores/user_store.jsx');
+
+export default class Docs extends React.Component {
+ constructor(props) {
+ super(props);
+ UserStore.setCurrentUser(global.window.mm_user || {});
+
+ this.state = {text: ''};
+ const errorState = {text: '## 404'};
+
+ if (props.site) {
+ $.get('/static/help/' + props.site + '.md').then((response) => {
+ this.setState({text: response});
+ }, () => {
+ this.setState(errorState);
+ });
+ } else {
+ this.setState(errorState);
+ }
+ }
+
+ render() {
+ return (
+ <div
+ dangerouslySetInnerHTML={{__html: TextFormatting.formatText(this.state.text)}}
+ >
+ </div>
+ );
+ }
+}
+
+Docs.defaultProps = {
+ site: ''
+};
+Docs.propTypes = {
+ site: React.PropTypes.string
+};
diff --git a/web/react/components/posts_view.jsx b/web/react/components/posts_view.jsx
index 087ca1df2..ec8223203 100644
--- a/web/react/components/posts_view.jsx
+++ b/web/react/components/posts_view.jsx
@@ -83,9 +83,14 @@ export default class PostsView extends React.Component {
let hideProfilePic = false;
if (prevPost) {
- sameUser = prevPost.user_id === post.user_id && post.create_at - prevPost.create_at <= 1000 * 60 * 5;
+ const postIsComment = Utils.isComment(post);
+ const prevPostIsComment = Utils.isComment(prevPost);
+ const postFromWebhook = Boolean(post.props && post.props.from_webhook);
+ const prevPostFromWebhook = Boolean(prevPost.props && prevPost.props.from_webhook);
- sameRoot = Utils.isComment(post) && (prevPost.id === post.root_id || prevPost.root_id === post.root_id);
+ sameUser = prevPost.user_id === post.user_id && postFromWebhook === prevPostFromWebhook &&
+ post.create_at - prevPost.create_at <= 1000 * 60 * 5;
+ sameRoot = (postIsComment && (prevPost.id === post.root_id || prevPost.root_id === post.root_id)) || (!postIsComment && !prevPostIsComment && sameUser);
// hide the profile pic if:
// the previous post was made by the same user as the current post,
@@ -94,10 +99,10 @@ export default class PostsView extends React.Component {
// the current post is not from a webhook
// and the previous post is not from a webhook
if ((prevPost.user_id === post.user_id) &&
- !Utils.isComment(prevPost) &&
- !Utils.isComment(post) &&
- (!post.props || !post.props.from_webhook) &&
- (!prevPost.props || !prevPost.props.from_webhook)) {
+ !prevPostIsComment &&
+ !postIsComment &&
+ !postFromWebhook &&
+ !prevPostFromWebhook) {
hideProfilePic = true;
}
}
diff --git a/web/react/components/textbox.jsx b/web/react/components/textbox.jsx
index e6530b941..1a5269baa 100644
--- a/web/react/components/textbox.jsx
+++ b/web/react/components/textbox.jsx
@@ -295,6 +295,13 @@ export default class Textbox extends React.Component {
this.resize();
}
+ showHelp(e) {
+ e.preventDefault();
+ e.target.blur();
+
+ global.window.open('/docs/Messaging');
+ }
+
render() {
const previewLinkVisible = this.props.messageText.length > 0;
@@ -336,11 +343,17 @@ export default class Textbox extends React.Component {
>
</div>
<a
+ onClick={this.showHelp}
+ className='textbox-help-link'
+ >
+ {'Help'}
+ </a>
+ <a
style={{visibility: previewLinkVisible ? 'visible' : 'hidden'}}
onClick={this.showPreview}
className='textbox-preview-link'
>
- {this.state.preview ? 'Edit message' : 'Preview'}
+ {this.state.preview ? 'Edit' : 'Preview'}
</a>
</div>
);
diff --git a/web/react/pages/docs.jsx b/web/react/pages/docs.jsx
new file mode 100644
index 000000000..ed2b6d0c9
--- /dev/null
+++ b/web/react/pages/docs.jsx
@@ -0,0 +1,16 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+var Docs = require('../components/docs.jsx');
+
+function setupDocumentationPage(props) {
+ ReactDOM.render(
+ <Docs
+ site={props.Site}
+ />,
+ document.getElementById('docs')
+ );
+}
+
+global.window.mm_user = global.window.mm_user || {};
+global.window.setup_documentation_page = setupDocumentationPage;
diff --git a/web/react/stores/browser_store.jsx b/web/react/stores/browser_store.jsx
index 8e86ce32f..2e3a26cff 100644
--- a/web/react/stores/browser_store.jsx
+++ b/web/react/stores/browser_store.jsx
@@ -72,7 +72,7 @@ class BrowserStoreClass {
console.log('An error occurred while setting local storage, clearing all props'); //eslint-disable-line no-console
localStorage.clear();
sessionStorage.clear();
- window.location.href = window.location.href;
+ window.location.reload(true);
}
}
diff --git a/web/react/utils/async_client.jsx b/web/react/utils/async_client.jsx
index 205c7461c..b39648bf0 100644
--- a/web/react/utils/async_client.jsx
+++ b/web/react/utils/async_client.jsx
@@ -63,7 +63,7 @@ export function getChannels(force, updateLastViewed, checkVersion) {
if (serverVersion !== BrowserStore.getLastServerVersion()) {
BrowserStore.setLastServerVersion(serverVersion);
- window.location.href = window.location.href;
+ window.location.reload(true);
console.log('Detected version update refreshing the page'); //eslint-disable-line no-console
}
}
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index e2981e914..fad6f5074 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -47,20 +47,25 @@ body.ios {
.textarea-wrapper {
position:relative;
- .textbox-preview-area {
- position: absolute;
- z-index: 2;
- top: 0;
- left: 0;
- box-shadow: none;
- }
- .textbox-preview-link {
- position: absolute;
- z-index: 3;
- bottom: -23px;
- right: 0;
+ .textbox-preview-area {
+ position: absolute;
+ z-index: 2;
+ top: 0;
+ left: 0;
+ box-shadow: none;
+ }
+ .textbox-preview-link, .textbox-help-link {
+ position: absolute;
+ z-index: 3;
+ bottom: -23px;
font-size: 13px;
- cursor: pointer;
+ cursor: pointer;
+ }
+ .textbox-preview-link {
+ right: 45px;
+ }
+ .textbox-help-link {
+ right: 0;
}
min-height:36px;
}
@@ -393,6 +398,15 @@ body.ios {
.post-body {
@include border-radius(0 4px 4px 0);
}
+ .post-body {
+ border-left: 4px solid #EEE;
+ width: 570px;
+ margin-left: 30px;
+ padding-left: 10px;
+ .post-link {
+ display: none;
+ }
+ }
}
}
&.same--root {
@@ -408,13 +422,12 @@ body.ios {
.post__content {
padding: 0;
}
- .post-body {
- border-left: 4px solid #EEE;
- width: 570px;
- margin-left: 30px;
- padding-left: 10px;
- .post-link {
- display: none;
+ &.same--user {
+ .post__content {
+ padding-left: 46px;
+ }
+ .post-header-post {
+ visibility: hidden;
}
}
}
diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss
index a4bdc3e92..aad991035 100644
--- a/web/sass-files/sass/partials/_responsive.scss
+++ b/web/sass-files/sass/partials/_responsive.scss
@@ -9,25 +9,26 @@
}
}
.post {
- &.same--root {
- margin-left: 60px;
- padding-left: 10px;
- border-left: 4px solid #EEE;
- div.post-profile-img__container {
- .post-profile-img {
- display: none;
- }
- }
- .post__content {
- width: 825px;
- }
- .post-body {
- width: 736px;
- border: none;
- margin: 3px 0 0;
- }
- }
&.post--comment {
+ &.same--root {
+ margin-left: 104px;
+ padding-left: 10px;
+ border-left: 4px solid #EEE;
+ div.post-profile-img__container {
+ .post-profile-img {
+ display: none;
+ }
+ }
+ .post__content {
+ width: 825px;
+ margin-left: 0;
+ }
+ .post-body {
+ width: 736px;
+ border: none;
+ margin: 3px 0 0;
+ }
+ }
&.other--root {
.post-comment {
margin-left: 0;
@@ -105,34 +106,61 @@
}
}
.post {
- &.same--root {
- margin-left: 60px;
- padding-left: 10px;
- border-left: 4px solid #EEE;
- div.post-profile-img__container {
- .post-profile-img {
- display: none;
- }
- }
- .post__content {
- width: 825px;
- }
- .post-body {
- width: 736px;
- border: none;
- margin: 3px 0 0;
- }
- }
+ &.same--root.same--user {
+ .post-header-post {
+ visibility: hidden;
+ width: 100%;
+ position: relative;
+ top: -5px;
+ .post-header-col.post-header__name {
+ display: none;
+ }
+ }
+ .post-body {
+ top: -15px;
+ margin-bottom: -10px;
+ }
+ &:hover .post-header-post {
+ visibility: visible;
+ }
+ }
+
&.post--comment {
&.other--root {
.post-comment {
margin-left: 0;
}
}
- &.same--root {
- margin-top: 5px;
- margin-bottom: 5px;
- }
+ &.same--root {
+ margin-top: 5px;
+ margin-bottom: 5px;
+ margin-left: 104px;
+ padding-left: 10px;
+ border-left: 4px solid #EEE;
+ div.post-profile-img__container {
+ .post-profile-img {
+ display: none;
+ }
+ }
+ .post-body {
+ margin-left: 0;
+ border-left: 0;
+ }
+ &.same--user {
+ .post__content {
+ margin-left: 0;
+ padding-left: 0;
+ }
+ }
+ }
+ .post__content {
+ width: 810px;
+ }
+ .post-body {
+ width: 736px;
+ border: none;
+ margin: 3px 0 0;
+ }
}
.post__content {
width: 880px;
@@ -358,9 +386,6 @@
}
}
.post {
- &.same--root {
- margin-left: 25px;
- }
&:hover {
background: none;
.post-header .post-header-col.post-header__reply {
@@ -370,7 +395,11 @@
}
}
&.post--comment {
+ &.same--root {
+ margin-left: 25px;
+ }
&.other--root {
+ margin-left: 0;
&:hover {
background: none;
}
@@ -381,6 +410,9 @@
content: '...';
}
}
+ &.same--root.same--user .post__content{
+ padding-left: 0;
+ }
}
.signup-team__container {
padding: 30px 0;
diff --git a/web/static/help/Messaging.md b/web/static/help/Messaging.md
new file mode 120000
index 000000000..f74c0b879
--- /dev/null
+++ b/web/static/help/Messaging.md
@@ -0,0 +1 @@
+../../../doc/help/Messaging.md \ No newline at end of file
diff --git a/web/templates/docs.html b/web/templates/docs.html
new file mode 100644
index 000000000..21659e810
--- /dev/null
+++ b/web/templates/docs.html
@@ -0,0 +1,24 @@
+{{define "docs"}}
+<!DOCTYPE html>
+<html>
+{{template "head" . }}
+<body class="white">
+<div class="container-fluid">
+ <div class="inner__wrap">
+ <div class="row content">
+ <div class="col-sm-12">
+ <div id="docs"></div>
+ </div>
+ <div class="footer-push"></div>
+ </div>
+ <div class="row footer">
+ {{template "footer" . }}
+ </div>
+ </div>
+</div>
+<script>
+ window.setup_documentation_page({{ .Props }});
+</script>
+</body>
+</html>
+{{end}}
diff --git a/web/web.go b/web/web.go
index 02ceb69ba..477bd8b27 100644
--- a/web/web.go
+++ b/web/web.go
@@ -80,6 +80,8 @@ func InitWeb() {
mainrouter.Handle("/hooks/{id:[A-Za-z0-9]+}", api.ApiAppHandler(incomingWebhook)).Methods("POST")
+ mainrouter.Handle("/docs/{doc:[A-Za-z0-9]+}", api.AppHandlerIndependent(docs)).Methods("GET")
+
// ----------------------------------------------------------------------------------------------
// *ANYTHING* team specific should go below this line
// ----------------------------------------------------------------------------------------------
@@ -494,6 +496,15 @@ func findTeam(c *api.Context, w http.ResponseWriter, r *http.Request) {
page.Render(c, w)
}
+func docs(c *api.Context, w http.ResponseWriter, r *http.Request) {
+ params := mux.Vars(r)
+ doc := params["doc"]
+
+ page := NewHtmlTemplatePage("docs", "Documentation")
+ page.Props["Site"] = doc
+ page.Render(c, w)
+}
+
func resetPassword(c *api.Context, w http.ResponseWriter, r *http.Request) {
isResetLink := true
hash := r.URL.Query().Get("h")