diff options
Diffstat (limited to 'web')
-rw-r--r-- | web/react/components/docs.jsx | 41 | ||||
-rw-r--r-- | web/react/components/posts_view.jsx | 17 | ||||
-rw-r--r-- | web/react/components/textbox.jsx | 15 | ||||
-rw-r--r-- | web/react/pages/docs.jsx | 16 | ||||
-rw-r--r-- | web/react/stores/browser_store.jsx | 2 | ||||
-rw-r--r-- | web/react/utils/async_client.jsx | 2 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_post.scss | 53 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_responsive.scss | 118 | ||||
l--------- | web/static/help/Messaging.md | 1 | ||||
-rw-r--r-- | web/templates/docs.html | 24 | ||||
-rw-r--r-- | web/web.go | 11 |
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") |