diff options
Diffstat (limited to 'webapp')
-rw-r--r-- | webapp/components/navbar.jsx | 11 | ||||
-rw-r--r-- | webapp/components/rhs_comment.jsx | 12 | ||||
-rw-r--r-- | webapp/components/rhs_root_post.jsx | 5 | ||||
-rw-r--r-- | webapp/components/rhs_thread.jsx | 39 | ||||
-rw-r--r-- | webapp/components/sidebar_right.jsx | 65 | ||||
-rw-r--r-- | webapp/i18n/en.json | 4 | ||||
-rw-r--r-- | webapp/i18n/es.json | 2 | ||||
-rw-r--r-- | webapp/package.json | 1 | ||||
-rw-r--r-- | webapp/root.jsx | 27 |
9 files changed, 107 insertions, 59 deletions
diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx index fb3b25957..520f05ed0 100644 --- a/webapp/components/navbar.jsx +++ b/webapp/components/navbar.jsx @@ -8,6 +8,7 @@ import MessageWrapper from './message_wrapper.jsx'; import NotifyCounts from './notify_counts.jsx'; import ChannelInfoModal from './channel_info_modal.jsx'; import ChannelInviteModal from './channel_invite_modal.jsx'; +import ChannelMembersModal from './channel_members_modal.jsx'; import ChannelNotificationsModal from './channel_notifications_modal.jsx'; import DeleteChannelModal from './delete_channel_modal.jsx'; import RenameChannelModal from './rename_channel_modal.jsx'; @@ -433,6 +434,7 @@ export default class Navbar extends React.Component { var editChannelHeaderModal = null; var editChannelPurposeModal = null; let renameChannelModal = null; + let channelMembersModal = null; if (channel) { popoverContent = ( @@ -523,6 +525,14 @@ export default class Navbar extends React.Component { channel={channel} /> ); + + channelMembersModal = ( + <ChannelMembersModal + show={this.state.showMembersModal} + onModalDismissed={() => this.setState({showMembersModal: false})} + channel={channel} + /> + ); } var collapseButtons = this.createCollapseButtons(currentId); @@ -556,6 +566,7 @@ export default class Navbar extends React.Component { {editChannelHeaderModal} {editChannelPurposeModal} {renameChannelModal} + {channelMembersModal} </div> ); } diff --git a/webapp/components/rhs_comment.jsx b/webapp/components/rhs_comment.jsx index 29986d415..de99eb37d 100644 --- a/webapp/components/rhs_comment.jsx +++ b/webapp/components/rhs_comment.jsx @@ -5,7 +5,6 @@ import ReactDOM from 'react-dom'; import PostStore from 'stores/post_store.jsx'; import ChannelStore from 'stores/channel_store.jsx'; import UserProfile from './user_profile.jsx'; -import UserStore from 'stores/user_store.jsx'; import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; @@ -97,8 +96,8 @@ class RhsComment extends React.Component { return ''; } - var isOwner = UserStore.getCurrentId() === post.user_id; - var isAdmin = Utils.isAdmin(UserStore.getCurrentUser().roles); + const isOwner = this.props.currentUser.id === post.user_id; + const isAdmin = Utils.isAdmin(this.props.currentUser.roles); var dropdownContents = []; @@ -193,11 +192,11 @@ class RhsComment extends React.Component { var post = this.props.post; var currentUserCss = ''; - if (UserStore.getCurrentId() === post.user_id) { + if (this.props.currentUser === post.user_id) { currentUserCss = 'current--user'; } - var timestamp = UserStore.getCurrentUser().update_at; + var timestamp = this.props.currentUser.update_at; let loading; let postClass = ''; @@ -305,7 +304,8 @@ RhsComment.defaultProps = { RhsComment.propTypes = { intl: intlShape.isRequired, post: React.PropTypes.object, - user: React.PropTypes.object + user: React.PropTypes.object.isRequired, + currentUser: React.PropTypes.object.isRequired }; export default injectIntl(RhsComment); diff --git a/webapp/components/rhs_root_post.jsx b/webapp/components/rhs_root_post.jsx index a2c7ee7f8..1aa4a555f 100644 --- a/webapp/components/rhs_root_post.jsx +++ b/webapp/components/rhs_root_post.jsx @@ -55,8 +55,8 @@ export default class RhsRootPost extends React.Component { render() { const post = this.props.post; const user = this.props.user; - var isOwner = user.id === post.user_id; - var isAdmin = Utils.isAdmin(user.roles); + var isOwner = this.props.currentUser.id === post.user_id; + var isAdmin = Utils.isAdmin(this.props.currentUser.roles); var timestamp = UserStore.getProfile(post.user_id).update_at; var channel = ChannelStore.get(post.channel_id); @@ -286,5 +286,6 @@ RhsRootPost.defaultProps = { RhsRootPost.propTypes = { post: React.PropTypes.object.isRequired, user: React.PropTypes.object.isRequired, + currentUser: React.PropTypes.object.isRequired, commentCount: React.PropTypes.number }; diff --git a/webapp/components/rhs_thread.jsx b/webapp/components/rhs_thread.jsx index cc900f8e7..2760765eb 100644 --- a/webapp/components/rhs_thread.jsx +++ b/webapp/components/rhs_thread.jsx @@ -130,7 +130,7 @@ export default class RhsThread extends React.Component { } // sort failed posts to bottom, followed by pending, and then regular posts - postsArray.sort(function postSort(a, b) { + postsArray.sort((a, b) => { if ((a.state === Constants.POST_LOADING || a.state === Constants.POST_FAILED) && (b.state !== Constants.POST_LOADING && b.state !== Constants.POST_FAILED)) { return 1; } @@ -182,24 +182,26 @@ export default class RhsThread extends React.Component { post={selected} commentCount={postsArray.length} user={profile} + currentUser={this.props.currentUser} /> <div className='post-right-comments-container'> - {postsArray.map(function mapPosts(comPost) { - let p; - if (UserStore.getCurrentId() === comPost.user_id) { - p = UserStore.getCurrentUser(); - } else { - p = profiles[comPost.user_id]; - } - return ( - <Comment - ref={comPost.id} - key={comPost.id + 'commentKey'} - post={comPost} - user={p} - /> - ); - })} + {postsArray.map((comPost) => { + let p; + if (UserStore.getCurrentId() === comPost.user_id) { + p = UserStore.getCurrentUser(); + } else { + p = profiles[comPost.user_id]; + } + return ( + <Comment + ref={comPost.id} + key={comPost.id + 'commentKey'} + post={comPost} + user={p} + currentUser={this.props.currentUser} + /> + ); + })} </div> <div className='post-create__container'> <CreateComment @@ -221,5 +223,6 @@ RhsThread.defaultProps = { RhsThread.propTypes = { fromSearch: React.PropTypes.string, - isMentionSearch: React.PropTypes.bool + isMentionSearch: React.PropTypes.bool, + currentUser: React.PropTypes.object.isRequired }; diff --git a/webapp/components/sidebar_right.jsx b/webapp/components/sidebar_right.jsx index 1b3286963..a2e3914f3 100644 --- a/webapp/components/sidebar_right.jsx +++ b/webapp/components/sidebar_right.jsx @@ -8,6 +8,7 @@ import SearchResults from './search_results.jsx'; import RhsThread from './rhs_thread.jsx'; import SearchStore from 'stores/search_store.jsx'; import PostStore from 'stores/post_store.jsx'; +import UserStore from 'stores/user_store.jsx'; import * as Utils from 'utils/utils.jsx'; const SIDEBAR_SCROLL_DELAY = 500; @@ -22,33 +23,38 @@ export default class SidebarRight extends React.Component { this.onSelectedChange = this.onSelectedChange.bind(this); this.onSearchChange = this.onSearchChange.bind(this); + this.onUserChange = this.onUserChange.bind(this); this.onShowSearch = this.onShowSearch.bind(this); this.doStrangeThings = this.doStrangeThings.bind(this); - this.state = this.getStateFromStores(); - } - getStateFromStores() { - return { - search_visible: SearchStore.getSearchResults() != null, - post_right_visible: PostStore.getSelectedPost() != null, - is_mention_search: SearchStore.getIsMentionSearch() + this.state = { + searchVisible: !!SearchStore.getSearchResults(), + isMentionSearch: SearchStore.getIsMentionSearch(), + postRightVisible: !!PostStore.getSelectedPost(), + fromSearch: false, + currentUser: UserStore.getCurrentUser() }; } componentDidMount() { SearchStore.addSearchChangeListener(this.onSearchChange); PostStore.addSelectedPostChangeListener(this.onSelectedChange); SearchStore.addShowSearchListener(this.onShowSearch); + UserStore.addChangeListener(this.onUserChange); this.doStrangeThings(); } componentWillUnmount() { SearchStore.removeSearchChangeListener(this.onSearchChange); PostStore.removeSelectedPostChangeListener(this.onSelectedChange); SearchStore.removeShowSearchListener(this.onShowSearch); + UserStore.removeChangeListener(this.onUserChange); + } + shouldComponentUpdate(nextProps, nextState) { + return !Utils.areObjectsEqual(nextState, this.state); } componentWillUpdate(nextProps, nextState) { - const isOpen = this.state.search_visible || this.state.post_right_visible; - const willOpen = nextState.search_visible || nextState.post_right_visible; + const isOpen = this.state.searchVisible || this.state.postRightVisible; + const willOpen = nextState.searchVisible || nextState.postRightVisible; if (!isOpen && willOpen) { setTimeout(() => PostStore.jumpPostsViewSidebarOpen(), SIDEBAR_SCROLL_DELAY); @@ -66,7 +72,7 @@ export default class SidebarRight extends React.Component { $('.sidebar--right').addClass('move--left'); //$('.sidebar--right').prepend('<div class="sidebar__overlay"></div>'); - if (this.state.search_visible || this.state.post_right_visible) { + if (this.state.searchVisible || this.state.postRightVisible) { if (windowWidth > 960) { velocity($('.inner-wrap'), {marginRight: sidebarRightWidth}, {duration: 500, easing: 'easeOutSine'}); velocity($('.sidebar--right'), {translateX: 0}, {duration: 500, easing: 'easeOutSine'}); @@ -98,35 +104,40 @@ export default class SidebarRight extends React.Component { this.doStrangeThings(); } onSelectedChange(fromSearch) { - var newState = this.getStateFromStores(fromSearch); - newState.from_search = fromSearch; - if (!Utils.areObjectsEqual(newState, this.state)) { - this.setState(newState); - } + this.setState({ + postRightVisible: !!PostStore.getSelectedPost(), + fromSearch + }); } onSearchChange() { - var newState = this.getStateFromStores(); - if (!Utils.areObjectsEqual(newState, this.state)) { - this.setState(newState); - } + this.setState({ + searchVisible: !!SearchStore.getSearchResults(), + isMentionSearch: SearchStore.getIsMentionSearch() + }); + } + onUserChange() { + this.setState({ + currentUser: UserStore.getCurrentUser() + }); } onShowSearch() { - if (!this.state.search_visible) { + if (!this.state.searchVisible) { this.setState({ - search_visible: true + searchVisible: true }); } } render() { - var content = ''; + let content = null; - if (this.state.search_visible) { - content = <SearchResults isMentionSearch={this.state.is_mention_search}/>; - } else if (this.state.post_right_visible) { + if (this.state.searchVisible) { + content = <SearchResults isMentionSearch={this.state.isMentionSearch}/>; + } else if (this.state.postRightVisible) { content = ( <RhsThread - fromSearch={this.state.from_search} - isMentionSearch={this.state.is_mention_search} + fromSearch={this.state.fromSearch} + isMentionSearch={this.state.isMentionSearch} + currentUser={this.state.currentUser} /> ); } diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index e4485dc29..d9411df07 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -410,6 +410,8 @@ "admin.support.emailTitle": "Support email:", "admin.support.helpDesc": "Link to help documentation from team site main menu. Typically not changed unless your organization chooses to create custom documentation.", "admin.support.helpTitle": "Help link:", + "admin.support.noteDescription": "If linking to an external site, URLs should begin with http:// or https://.", + "admin.support.noteTitle": "Note:", "admin.support.privacyDesc": "Link to Privacy Policy available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.", "admin.support.privacyTitle": "Privacy Policy link:", "admin.support.problemDesc": "Link to help documentation from team site main menu. By default this points to the peer-to-peer troubleshooting forum where users can search for, find and request help with technical issues.", @@ -419,8 +421,6 @@ "admin.support.termsDesc": "Link to Terms of Service available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.", "admin.support.termsTitle": "Terms of Service link:", "admin.support.title": "Legal and Support Settings", - "admin.support.noteTitle": "Note:", - "admin.support.noteDescription": "If linking to an external site, URLs should begin with http:// or https://.", "admin.system_analytics.activeUsers": "Active Users With Posts", "admin.system_analytics.title": "the System", "admin.system_analytics.totalPosts": "Total Posts", diff --git a/webapp/i18n/es.json b/webapp/i18n/es.json index 021b41051..8852dd3c6 100644 --- a/webapp/i18n/es.json +++ b/webapp/i18n/es.json @@ -410,6 +410,8 @@ "admin.support.emailTitle": "Correo electrónico de Soporte:", "admin.support.helpDesc": "Enlace con la documentación de ayuda para el equipo desde el menú principal. Normalmente no cambia a menos que tu organización decida crear una documentación personalizada.", "admin.support.helpTitle": "Enlace de Ayuda:", + "admin.support.noteDescription": "Si se enlaza a un sitio externo, las URLs deben comenzar con http:// o https://.", + "admin.support.noteTitle": "Nota:", "admin.support.privacyDesc": "Enlace para las políticas de Privacidad disponible para los usuarios en versión de escritorio y movil. Al dejarlo en blanco esconderá la opción que muestra el aviso.", "admin.support.privacyTitle": "Enlace de políticas de Privacidad:", "admin.support.problemDesc": "Enlace con la documentación de ayuda para el equipo desde el menú principal. Como predeterminado esto apunta a un foro de ayuda donde los usuarios pueden buscar, encontrar y solicitar ayuda sobre temas técnicos.", diff --git a/webapp/package.json b/webapp/package.json index 0c3e9313e..cdfba8ef0 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -11,6 +11,7 @@ "fastclick": "1.0.6", "flux": "2.1.1", "highlight.js": "9.2.0", + "intl": "1.1.0", "jasny-bootstrap": "3.1.3", "jquery": "2.2.1", "keymirror": "0.1.1", diff --git a/webapp/root.jsx b/webapp/root.jsx index 2ce220f1d..b0a6ae1ac 100644 --- a/webapp/root.jsx +++ b/webapp/root.jsx @@ -109,11 +109,30 @@ function preRenderSetup(callwhendone) { } ); - addLocaleData(enLocaleData); - addLocaleData(esLocaleData); - addLocaleData(ptLocaleData); + function afterIntl() { + addLocaleData(enLocaleData); + addLocaleData(esLocaleData); + addLocaleData(ptLocaleData); - $.when(d1, d2).done(callwhendone); + $.when(d1, d2).done(callwhendone); + } + + if (global.Intl) { + afterIntl(); + } else { + require.ensure([ + 'intl', + 'intl/locale-data/jsonp/en.js', + 'intl/locale-data/jsonp/es.js', + 'intl/locale-data/jsonp/pt.js' + ], (require) => { + require('intl'); + require('intl/locale-data/jsonp/en.js'); + require('intl/locale-data/jsonp/es.js'); + require('intl/locale-data/jsonp/pt.js'); + afterIntl(); + }); + } } function preLoggedIn(nextState, replace, callback) { |