diff options
Diffstat (limited to 'web')
-rw-r--r-- | web/react/components/admin_console/admin_controller.jsx | 12 | ||||
-rw-r--r-- | web/react/components/admin_console/admin_sidebar.jsx | 1 | ||||
-rw-r--r-- | web/react/components/channel_header.jsx | 16 | ||||
-rw-r--r-- | web/react/components/msg_typing.jsx | 15 | ||||
-rw-r--r-- | web/react/components/post_list.jsx | 60 | ||||
-rw-r--r-- | web/react/components/sidebar.jsx | 92 | ||||
-rw-r--r-- | web/react/components/user_profile.jsx | 4 | ||||
-rw-r--r-- | web/react/components/view_image.jsx | 7 | ||||
-rw-r--r-- | web/react/pages/admin_console.jsx | 7 | ||||
-rw-r--r-- | web/react/stores/socket_store.jsx | 187 | ||||
-rw-r--r-- | web/react/utils/constants.jsx | 12 | ||||
-rw-r--r-- | web/templates/admin_console.html | 2 | ||||
-rw-r--r-- | web/web.go | 10 |
13 files changed, 262 insertions, 163 deletions
diff --git a/web/react/components/admin_console/admin_controller.jsx b/web/react/components/admin_console/admin_controller.jsx index f2fb8ac78..f770d166c 100644 --- a/web/react/components/admin_console/admin_controller.jsx +++ b/web/react/components/admin_console/admin_controller.jsx @@ -40,9 +40,13 @@ export default class AdminController extends React.Component { config: AdminStore.getConfig(), teams: AdminStore.getAllTeams(), selectedTeams, - selected: 'service_settings', - selectedTeam: null + selected: props.tab || 'service_settings', + selectedTeam: props.teamId || null }; + + if (!props.tab) { + history.replaceState(null, null, `/admin_console/${this.state.selected}`); + } } componentDidMount() { @@ -142,7 +146,9 @@ export default class AdminController extends React.Component { } else if (this.state.selected === 'service_settings') { tab = <ServiceSettingsTab config={this.state.config} />; } else if (this.state.selected === 'team_users') { - tab = <TeamUsersTab team={this.state.teams[this.state.selectedTeam]} />; + if (this.state.teams) { + tab = <TeamUsersTab team={this.state.teams[this.state.selectedTeam]} />; + } } } diff --git a/web/react/components/admin_console/admin_sidebar.jsx b/web/react/components/admin_console/admin_sidebar.jsx index 24913ab87..b0e01ff17 100644 --- a/web/react/components/admin_console/admin_sidebar.jsx +++ b/web/react/components/admin_console/admin_sidebar.jsx @@ -24,6 +24,7 @@ export default class AdminSidebar extends React.Component { handleClick(name, teamId, e) { e.preventDefault(); this.props.selectTab(name, teamId); + history.pushState({name: name, teamId: teamId}, null, `/admin_console/${name}/${teamId || ''}`); } isSelected(name, teamId) { diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx index 7582de6c4..1b709336f 100644 --- a/web/react/components/channel_header.jsx +++ b/web/react/components/channel_header.jsx @@ -4,7 +4,6 @@ const ChannelStore = require('../stores/channel_store.jsx'); const UserStore = require('../stores/user_store.jsx'); const PostStore = require('../stores/post_store.jsx'); -const SocketStore = require('../stores/socket_store.jsx'); const NavbarSearchBox = require('./search_bar.jsx'); const AsyncClient = require('../utils/async_client.jsx'); const Client = require('../utils/client.jsx'); @@ -25,7 +24,6 @@ export default class ChannelHeader extends React.Component { super(props); this.onListenerChange = this.onListenerChange.bind(this); - this.onSocketChange = this.onSocketChange.bind(this); this.handleLeave = this.handleLeave.bind(this); this.searchMentions = this.searchMentions.bind(this); @@ -45,7 +43,6 @@ export default class ChannelHeader extends React.Component { ChannelStore.addExtraInfoChangeListener(this.onListenerChange); PostStore.addSearchChangeListener(this.onListenerChange); UserStore.addChangeListener(this.onListenerChange); - SocketStore.addChangeListener(this.onSocketChange); } componentWillUnmount() { ChannelStore.removeChangeListener(this.onListenerChange); @@ -60,16 +57,9 @@ export default class ChannelHeader extends React.Component { } $('.channel-header__info .description').popover({placement: 'bottom', trigger: 'hover', html: true, delay: {show: 500, hide: 500}}); } - onSocketChange(msg) { - if (msg.action === 'new_user' || - msg.action === 'user_added' || - (msg.action === 'user_removed' && msg.user_id !== UserStore.getCurrentId())) { - AsyncClient.getChannelExtraInfo(true); - } - } handleLeave() { Client.leaveChannel(this.state.channel.id, - function handleLeaveSuccess() { + () => { AppDispatcher.handleViewAction({ type: ActionTypes.LEAVE_CHANNEL, id: this.state.channel.id @@ -77,8 +67,8 @@ export default class ChannelHeader extends React.Component { const townsquare = ChannelStore.getByName('town-square'); Utils.switchChannel(townsquare); - }.bind(this), - function handleLeaveError(err) { + }, + (err) => { AsyncClient.dispatchError(err, 'handleLeave'); } ); diff --git a/web/react/components/msg_typing.jsx b/web/react/components/msg_typing.jsx index 569942390..1bd23c55c 100644 --- a/web/react/components/msg_typing.jsx +++ b/web/react/components/msg_typing.jsx @@ -1,8 +1,11 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -var SocketStore = require('../stores/socket_store.jsx'); -var UserStore = require('../stores/user_store.jsx'); +const SocketStore = require('../stores/socket_store.jsx'); +const UserStore = require('../stores/user_store.jsx'); + +const Constants = require('../utils/constants.jsx'); +const SocketEvents = Constants.SocketEvents; export default class MsgTyping extends React.Component { constructor(props) { @@ -33,9 +36,9 @@ export default class MsgTyping extends React.Component { } onChange(msg) { - if (msg.action === 'typing' && - this.props.channelId === msg.channel_id && - this.props.parentId === msg.props.parent_id) { + if (msg.action === SocketEvents.TYPING && + this.props.channelId === msg.channel_id && + this.props.parentId === msg.props.parent_id) { this.lastTime = new Date().getTime(); var username = 'Someone'; @@ -52,7 +55,7 @@ export default class MsgTyping extends React.Component { } }.bind(this), 3000); } - } else if (msg.action === 'posted' && msg.channel_id === this.props.channelId) { + } else if (msg.action === SocketEvents.POSTED && msg.channel_id === this.props.channelId) { this.setState({text: ''}); } } diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index 29728d368..4402745e1 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -1,20 +1,24 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -var PostStore = require('../stores/post_store.jsx'); -var ChannelStore = require('../stores/channel_store.jsx'); -var UserStore = require('../stores/user_store.jsx'); -var PreferenceStore = require('../stores/preference_store.jsx'); -var UserProfile = require('./user_profile.jsx'); -var AsyncClient = require('../utils/async_client.jsx'); -var Post = require('./post.jsx'); -var LoadingScreen = require('./loading_screen.jsx'); -var SocketStore = require('../stores/socket_store.jsx'); -var utils = require('../utils/utils.jsx'); -var Client = require('../utils/client.jsx'); -var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); -var Constants = require('../utils/constants.jsx'); -var ActionTypes = Constants.ActionTypes; +const Post = require('./post.jsx'); +const UserProfile = require('./user_profile.jsx'); +const AsyncClient = require('../utils/async_client.jsx'); +const LoadingScreen = require('./loading_screen.jsx'); + +const PostStore = require('../stores/post_store.jsx'); +const ChannelStore = require('../stores/channel_store.jsx'); +const UserStore = require('../stores/user_store.jsx'); +const SocketStore = require('../stores/socket_store.jsx'); +const PreferenceStore = require('../stores/preference_store.jsx'); + +const utils = require('../utils/utils.jsx'); +const Client = require('../utils/client.jsx'); +const Constants = require('../utils/constants.jsx'); +const ActionTypes = Constants.ActionTypes; +const SocketEvents = Constants.SocketEvents; + +const AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); export default class PostList extends React.Component { constructor(props) { @@ -58,7 +62,7 @@ export default class PostList extends React.Component { } } - postList.order.sort(function postSort(a, b) { + postList.order.sort((a, b) => { if (postList.posts[a].create_at > postList.posts[b].create_at) { return -1; } @@ -82,7 +86,7 @@ export default class PostList extends React.Component { } return { - postList: postList + postList }; } componentDidMount() { @@ -263,14 +267,14 @@ export default class PostList extends React.Component { Client.getPosts( id, PostStore.getLatestUpdate(id), - function success() { + () => { this.loadInProgress = false; this.setState({isFirstLoadComplete: true}); - }.bind(this), - function fail() { + }, + () => { this.loadInProgress = false; this.setState({isFirstLoadComplete: true}); - }.bind(this) + } ); } onChange() { @@ -281,28 +285,16 @@ export default class PostList extends React.Component { } } onSocketChange(msg) { - var post; - if (msg.action === 'posted' || msg.action === 'post_edited') { - post = JSON.parse(msg.props.post); - PostStore.storePost(post); - } else if (msg.action === 'post_deleted') { + if (msg.action === SocketEvents.POST_DELETED) { var activeRoot = $(document.activeElement).closest('.comment-create-body')[0]; var activeRootPostId = ''; if (activeRoot && activeRoot.id.length > 0) { activeRootPostId = activeRoot.id; } - post = JSON.parse(msg.props.post); - - PostStore.storeUnseenDeletedPost(post); - PostStore.removePost(post, true); - PostStore.emitChange(); - if (activeRootPostId === msg.props.post_id && UserStore.getCurrentId() !== msg.user_id) { $('#post_deleted').modal('show'); } - } else if (msg.action === 'new_user') { - AsyncClient.getProfiles(); } } onTimeChange() { @@ -352,7 +344,7 @@ export default class PostList extends React.Component { data-title={channel.display_name} data-channelid={channel.id} > - <i className='fa fa-pencil'></i>Set a description + <i className='fa fa-pencil'></i>{'Set a description'} </a> </div> ); diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 6e4a53e1b..f88522fb9 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -2,7 +2,6 @@ // See License.txt for license information. const AsyncClient = require('../utils/async_client.jsx'); -const BrowserStore = require('../stores/browser_store.jsx'); const ChannelStore = require('../stores/channel_store.jsx'); const Client = require('../utils/client.jsx'); const Constants = require('../utils/constants.jsx'); @@ -11,7 +10,6 @@ const NewChannelFlow = require('./new_channel_flow.jsx'); const MoreDirectChannels = require('./more_direct_channels.jsx'); const SearchBox = require('./search_bar.jsx'); const SidebarHeader = require('./sidebar_header.jsx'); -const SocketStore = require('../stores/socket_store.jsx'); const TeamStore = require('../stores/team_store.jsx'); const UnreadChannelIndicator = require('./unread_channel_indicator.jsx'); const UserStore = require('../stores/user_store.jsx'); @@ -129,7 +127,6 @@ export default class Sidebar extends React.Component { UserStore.addChangeListener(this.onChange); UserStore.addStatusesChangeListener(this.onChange); TeamStore.addChangeListener(this.onChange); - SocketStore.addChangeListener(this.onSocketChange); PreferenceStore.addChangeListener(this.onChange); if ($(window).width() > 768) { @@ -162,7 +159,6 @@ export default class Sidebar extends React.Component { UserStore.removeChangeListener(this.onChange); UserStore.removeStatusesChangeListener(this.onChange); TeamStore.removeChangeListener(this.onChange); - SocketStore.removeChangeListener(this.onSocketChange); PreferenceStore.removeChangeListener(this.onChange); } onChange() { @@ -171,94 +167,6 @@ export default class Sidebar extends React.Component { this.setState(newState); } } - onSocketChange(msg) { - if (msg.action === 'posted') { - if (ChannelStore.getCurrentId() === msg.channel_id) { - if (window.isActive) { - AsyncClient.updateLastViewedAt(); - } - } else { - AsyncClient.getChannels(); - } - - if (UserStore.getCurrentId() !== msg.user_id) { - var mentions = []; - if (msg.props.mentions) { - mentions = JSON.parse(msg.props.mentions); - } - var channel = ChannelStore.get(msg.channel_id); - - const user = UserStore.getCurrentUser(); - const member = ChannelStore.getMember(msg.channel_id); - - var notifyLevel = member && member.notify_props ? member.notify_props.desktop : 'default'; - if (notifyLevel === 'default') { - notifyLevel = user.notify_props.desktop; - } - - if (notifyLevel === 'none') { - return; - } else if (notifyLevel === 'mention' && mentions.indexOf(user.id) === -1 && channel.type !== 'D') { - return; - } - - var username = 'Someone'; - if (UserStore.hasProfile(msg.user_id)) { - username = UserStore.getProfile(msg.user_id).username; - } - - var title = 'Posted'; - if (channel) { - title = channel.display_name; - } - - var repRegex = new RegExp('<br>', 'g'); - var post = JSON.parse(msg.props.post); - var msgProps = msg.props; - var notifyText = post.message.replace(repRegex, '\n').replace(/\n+/g, ' ').replace('<mention>', '').replace('</mention>', ''); - - if (notifyText.length > 50) { - notifyText = notifyText.substring(0, 49) + '...'; - } - - if (notifyText.length === 0) { - if (msgProps.image) { - Utils.notifyMe(title, username + ' uploaded an image', channel); - } else if (msgProps.otherFile) { - Utils.notifyMe(title, username + ' uploaded a file', channel); - } else { - Utils.notifyMe(title, username + ' did something new', channel); - } - } else { - Utils.notifyMe(title, username + ' wrote: ' + notifyText, channel); - } - if (!user.notify_props || user.notify_props.desktop_sound === 'true') { - Utils.ding(); - } - } - } else if (msg.action === 'viewed') { - if (ChannelStore.getCurrentId() !== msg.channel_id && UserStore.getCurrentId() === msg.user_id) { - AsyncClient.getChannel(msg.channel_id); - } - } else if (msg.action === 'user_added') { - if (UserStore.getCurrentId() === msg.user_id) { - AsyncClient.getChannel(msg.channel_id); - } - } else if (msg.action === 'user_removed') { - if (msg.user_id === UserStore.getCurrentId()) { - AsyncClient.getChannels(true); - - if (msg.props.remover !== msg.user_id && msg.props.channel_id === ChannelStore.getCurrentId() && $('#removed_from_channel').length > 0) { - var sentState = {}; - sentState.channelName = ChannelStore.getCurrent().display_name; - sentState.remover = UserStore.getProfile(msg.props.remover).username; - - BrowserStore.setItem('channel-removed-state', sentState); - $('#removed_from_channel').modal('show'); - } - } - } - } updateTitle() { const channel = ChannelStore.getCurrent(); if (channel) { diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx index da0c1aaf9..540331663 100644 --- a/web/react/components/user_profile.jsx +++ b/web/react/components/user_profile.jsx @@ -86,11 +86,11 @@ export default class UserProfile extends React.Component { dataContent.push( <div data-toggle='tooltip' - title="' + this.state.profile.email + '" + title={this.state.profile.email} key='user-popover-email' > <a - href="mailto:' + this.state.profile.email + '" + href={'mailto:' + this.state.profile.email} className='text-nowrap text-lowercase user-popover__email' > {this.state.profile.email} diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx index f75693470..322e68c17 100644 --- a/web/react/components/view_image.jsx +++ b/web/react/components/view_image.jsx @@ -6,6 +6,7 @@ const Utils = require('../utils/utils.jsx'); const Constants = require('../utils/constants.jsx'); const ViewImagePopoverBar = require('./view_image_popover_bar.jsx'); const Modal = ReactBootstrap.Modal; +const KeyCodes = Constants.KeyCodes; export default class ViewImageModal extends React.Component { constructor(props) { @@ -63,11 +64,11 @@ export default class ViewImageModal extends React.Component { this.loadImage(id); } handleKeyPress(e) { - if (!e) { + if (!e || !this.props.show) { return; - } else if (e.keyCode === 39) { + } else if (e.keyCode === KeyCodes.RIGHT) { this.handleNext(); - } else if (e.keyCode === 37) { + } else if (e.keyCode === KeyCodes.LEFT) { this.handlePrev(); } } diff --git a/web/react/pages/admin_console.jsx b/web/react/pages/admin_console.jsx index c89cb4edc..ea9ae06f4 100644 --- a/web/react/pages/admin_console.jsx +++ b/web/react/pages/admin_console.jsx @@ -5,9 +5,12 @@ var ErrorBar = require('../components/error_bar.jsx'); var SelectTeamModal = require('../components/admin_console/select_team_modal.jsx'); var AdminController = require('../components/admin_console/admin_controller.jsx'); -export function setupAdminConsolePage() { +export function setupAdminConsolePage(props) { ReactDOM.render( - <AdminController />, + <AdminController + tab={props.ActiveTab} + teamId={props.TeamId} + />, document.getElementById('admin_controller') ); diff --git a/web/react/stores/socket_store.jsx b/web/react/stores/socket_store.jsx index 77e7067ad..77951f214 100644 --- a/web/react/stores/socket_store.jsx +++ b/web/react/stores/socket_store.jsx @@ -1,15 +1,22 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); -var UserStore = require('./user_store.jsx'); -var ErrorStore = require('./error_store.jsx'); -var EventEmitter = require('events').EventEmitter; +const AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); +const UserStore = require('./user_store.jsx'); +const PostStore = require('./post_store.jsx'); +const ChannelStore = require('./channel_store.jsx'); +const BrowserStore = require('./browser_store.jsx'); +const ErrorStore = require('./error_store.jsx'); +const EventEmitter = require('events').EventEmitter; -var Constants = require('../utils/constants.jsx'); -var ActionTypes = Constants.ActionTypes; +const Utils = require('../utils/utils.jsx'); +const AsyncClient = require('../utils/async_client.jsx'); -var CHANGE_EVENT = 'change'; +const Constants = require('../utils/constants.jsx'); +const ActionTypes = Constants.ActionTypes; +const SocketEvents = Constants.SocketEvents; + +const CHANGE_EVENT = 'change'; var conn; @@ -94,6 +101,39 @@ class SocketStoreClass extends EventEmitter { removeChangeListener(callback) { this.removeListener(CHANGE_EVENT, callback); } + handleMessage(msg) { + switch (msg.action) { + case SocketEvents.POSTED: + handleNewPostEvent(msg); + break; + + case SocketEvents.POST_EDITED: + handlePostEditEvent(msg); + break; + + case SocketEvents.POST_DELETED: + handlePostDeleteEvent(msg); + break; + + case SocketEvents.NEW_USER: + handleNewUserEvent(); + break; + + case SocketEvents.USER_ADDED: + handleUserAddedEvent(msg); + break; + + case SocketEvents.USER_REMOVED: + handleUserRemovedEvent(msg); + break; + + case SocketEvents.CHANNEL_VIEWED: + handleChannelViewedEvent(msg); + break; + + default: + } + } sendMessage(msg) { if (conn && conn.readyState === WebSocket.OPEN) { conn.send(JSON.stringify(msg)); @@ -104,6 +144,138 @@ class SocketStoreClass extends EventEmitter { } } +function handleNewPostEvent(msg) { + // Store post + const post = JSON.parse(msg.props.post); + PostStore.storePost(post); + + // Update channel state + if (ChannelStore.getCurrentId() === msg.channel_id) { + if (window.isActive) { + AsyncClient.updateLastViewedAt(); + } + } else { + AsyncClient.getChannel(msg.channel_id); + } + + // Send desktop notification + if (UserStore.getCurrentId() !== msg.user_id) { + const msgProps = msg.props; + + let mentions = []; + if (msgProps.mentions) { + mentions = JSON.parse(msg.props.mentions); + } + + const channel = ChannelStore.get(msg.channel_id); + const user = UserStore.getCurrentUser(); + const member = ChannelStore.getMember(msg.channel_id); + + let notifyLevel = member && member.notify_props ? member.notify_props.desktop : 'default'; + if (notifyLevel === 'default') { + notifyLevel = user.notify_props.desktop; + } + + if (notifyLevel === 'none') { + return; + } else if (notifyLevel === 'mention' && mentions.indexOf(user.id) === -1 && channel.type !== 'D') { + return; + } + + let username = 'Someone'; + if (UserStore.hasProfile(msg.user_id)) { + username = UserStore.getProfile(msg.user_id).username; + } + + let title = 'Posted'; + if (channel) { + title = channel.display_name; + } + + let notifyText = post.message.replace(/\n+/g, ' '); + if (notifyText.length > 50) { + notifyText = notifyText.substring(0, 49) + '...'; + } + + if (notifyText.length === 0) { + if (msgProps.image) { + Utils.notifyMe(title, username + ' uploaded an image', channel); + } else if (msgProps.otherFile) { + Utils.notifyMe(title, username + ' uploaded a file', channel); + } else { + Utils.notifyMe(title, username + ' did something new', channel); + } + } else { + Utils.notifyMe(title, username + ' wrote: ' + notifyText, channel); + } + if (!user.notify_props || user.notify_props.desktop_sound === 'true') { + Utils.ding(); + } + } +} + +function handlePostEditEvent(msg) { + // Store post + const post = JSON.parse(msg.props.post); + PostStore.storePost(post); + + // Update channel state + if (ChannelStore.getCurrentId() === msg.channel_id) { + if (window.isActive) { + AsyncClient.updateLastViewedAt(); + } + } +} + +function handlePostDeleteEvent(msg) { + const post = JSON.parse(msg.props.post); + + PostStore.storeUnseenDeletedPost(post); + PostStore.removePost(post, true); + PostStore.emitChange(); +} + +function handleNewUserEvent() { + AsyncClient.getProfiles(); + AsyncClient.getChannelExtraInfo(true); +} + +function handleUserAddedEvent(msg) { + if (ChannelStore.getCurrentId() === msg.channel_id) { + AsyncClient.getChannelExtraInfo(true); + } + + if (UserStore.getCurrentId() === msg.user_id) { + AsyncClient.getChannel(msg.channel_id); + } +} + +function handleUserRemovedEvent(msg) { + if (UserStore.getCurrentId() === msg.user_id) { + AsyncClient.getChannels(); + + if (msg.props.remover_id !== msg.user_id && + msg.channel_id === ChannelStore.getCurrentId() && + $('#removed_from_channel').length > 0) { + var sentState = {}; + sentState.channelName = ChannelStore.getCurrent().display_name; + sentState.remover = UserStore.getProfile(msg.props.remover_id).username; + + BrowserStore.setItem('channel-removed-state', sentState); + $('#removed_from_channel').modal('show'); + } + } else if (ChannelStore.getCurrentId() === msg.channel_id) { + AsyncClient.getChannelExtraInfo(true); + } +} + +function handleChannelViewedEvent(msg) { + // Useful for when multiple devices have the app open to different channels + if (ChannelStore.getCurrentId() !== msg.channel_id && UserStore.getCurrentId() === msg.user_id) { + AsyncClient.getChannel(msg.channel_id); + } +} + var SocketStore = new SocketStoreClass(); SocketStore.dispatchToken = AppDispatcher.register((payload) => { @@ -111,6 +283,7 @@ SocketStore.dispatchToken = AppDispatcher.register((payload) => { switch (action.type) { case ActionTypes.RECIEVED_MSG: + SocketStore.handleMessage(action.msg); SocketStore.emitChange(action.msg); break; diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index b7b8d3c60..5eb8378ca 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -47,6 +47,18 @@ module.exports = { SERVER_ACTION: null, VIEW_ACTION: null }), + + SocketEvents: { + POSTED: 'posted', + POST_EDITED: 'post_edited', + POST_DELETED: 'post_deleted', + CHANNEL_VIEWED: 'channel_viewed', + NEW_USER: 'new_user', + USER_ADDED: 'user_added', + USER_REMOVED: 'user_removed', + TYPING: 'typing' + }, + SPECIAL_MENTIONS: ['all', 'channel'], CHARACTER_LIMIT: 4000, IMAGE_TYPES: ['jpg', 'gif', 'bmp', 'png', 'jpeg'], diff --git a/web/templates/admin_console.html b/web/templates/admin_console.html index a046478f6..574caf730 100644 --- a/web/templates/admin_console.html +++ b/web/templates/admin_console.html @@ -12,7 +12,7 @@ <div id='select_team_modal'></div> <script> - window.setup_admin_console_page(); + window.setup_admin_console_page({{ .Props }}); $(document).ready(function(){ $('[data-toggle="tooltip"]').tooltip(); diff --git a/web/web.go b/web/web.go index 00e00b3b9..f10c4f2a1 100644 --- a/web/web.go +++ b/web/web.go @@ -64,6 +64,9 @@ func InitWeb() { mainrouter.Handle("/signup/{service:[A-Za-z]+}/complete", api.AppHandlerIndependent(signupCompleteOAuth)).Methods("GET") mainrouter.Handle("/admin_console", api.UserRequired(adminConsole)).Methods("GET") + mainrouter.Handle("/admin_console/", api.UserRequired(adminConsole)).Methods("GET") + mainrouter.Handle("/admin_console/{tab:[A-Za-z0-9-_]+}", api.UserRequired(adminConsole)).Methods("GET") + mainrouter.Handle("/admin_console/{tab:[A-Za-z0-9-_]+}/{team:[A-Za-z0-9-]*}", api.UserRequired(adminConsole)).Methods("GET") mainrouter.Handle("/hooks/{id:[A-Za-z0-9]+}", api.ApiAppHandler(incomingWebhook)).Methods("POST") @@ -699,7 +702,14 @@ func adminConsole(c *api.Context, w http.ResponseWriter, r *http.Request) { return } + params := mux.Vars(r) + activeTab := params["tab"] + teamId := params["team"] + page := NewHtmlTemplatePage("admin_console", "Admin Console") + + page.Props["ActiveTab"] = activeTab + page.Props["TeamId"] = teamId page.Render(c, w) } |