diff options
author | Harrison Healey <harrisonmhealey@gmail.com> | 2016-05-05 09:32:12 -0400 |
---|---|---|
committer | Christopher Speller <crspeller@gmail.com> | 2016-05-05 09:32:12 -0400 |
commit | 2c92540471004c79e317e8a0daf3e612560beda7 (patch) | |
tree | 2abed81a2b4340cfaeaed47e70a6b14d0129bc47 /webapp | |
parent | fcb5b70eb348368421464553066ef9c715c66ff0 (diff) | |
download | chat-2c92540471004c79e317e8a0daf3e612560beda7.tar.gz chat-2c92540471004c79e317e8a0daf3e612560beda7.tar.bz2 chat-2c92540471004c79e317e8a0daf3e612560beda7.zip |
PLT-2698 Integrations improvements (#2883)
* Fixed Integrations link to show up for non-admins (when enabled) and when only slash commands are enabled
* Updated BackstageSidebar to only show enabled integrations
* Added placeholder to integrations list when none exist
* Added loading spinner to integrations pages when they're loading
Diffstat (limited to 'webapp')
-rw-r--r-- | webapp/components/backstage/backstage_category.jsx | 4 | ||||
-rw-r--r-- | webapp/components/backstage/backstage_sidebar.jsx | 75 | ||||
-rw-r--r-- | webapp/components/backstage/installed_commands.jsx | 27 | ||||
-rw-r--r-- | webapp/components/backstage/installed_incoming_webhooks.jsx | 25 | ||||
-rw-r--r-- | webapp/components/backstage/installed_integrations.jsx | 25 | ||||
-rw-r--r-- | webapp/components/backstage/installed_outgoing_webhooks.jsx | 25 | ||||
-rw-r--r-- | webapp/components/navbar_dropdown.jsx | 28 | ||||
-rw-r--r-- | webapp/i18n/en.json | 3 |
8 files changed, 133 insertions, 79 deletions
diff --git a/webapp/components/backstage/backstage_category.jsx b/webapp/components/backstage/backstage_category.jsx index 913c7562c..8e6c8541b 100644 --- a/webapp/components/backstage/backstage_category.jsx +++ b/webapp/components/backstage/backstage_category.jsx @@ -40,6 +40,10 @@ export default class BackstageCategory extends React.Component { <ul className='sections'> { React.Children.map(children, (child) => { + if (!child) { + return child; + } + return React.cloneElement(child, { parentLink: link }); diff --git a/webapp/components/backstage/backstage_sidebar.jsx b/webapp/components/backstage/backstage_sidebar.jsx index 6f8e0b86a..4d8d8337d 100644 --- a/webapp/components/backstage/backstage_sidebar.jsx +++ b/webapp/components/backstage/backstage_sidebar.jsx @@ -10,6 +10,51 @@ import {FormattedMessage} from 'react-intl'; export default class BackstageSidebar extends React.Component { render() { + let incomingWebhooks = null; + if (window.mm_config.EnableIncomingWebhooks === 'true') { + incomingWebhooks = ( + <BackstageSection + name='incoming_webhooks' + title={( + <FormattedMessage + id='backstage_sidebar.integrations.incoming_webhooks' + defaultMessage='Incoming Webhooks' + /> + )} + /> + ); + } + + let outgoingWebhooks = null; + if (window.mm_config.EnableOutgoingWebhooks === 'true') { + outgoingWebhooks = ( + <BackstageSection + name='outgoing_webhooks' + title={( + <FormattedMessage + id='backstage_sidebar.integrations.outgoing_webhooks' + defaultMessage='Outgoing Webhooks' + /> + )} + /> + ); + } + + let commands = null; + if (window.mm_config.EnableCommands === 'true') { + commands = ( + <BackstageSection + name='commands' + title={( + <FormattedMessage + id='backstage_sidebar.integrations.commands' + defaultMessage='Slash Commands' + /> + )} + /> + ); + } + return ( <div className='backstage-sidebar'> <ul> @@ -24,33 +69,9 @@ export default class BackstageSidebar extends React.Component { /> } > - <BackstageSection - name='incoming_webhooks' - title={( - <FormattedMessage - id='backstage_sidebar.integrations.incoming_webhooks' - defaultMessage='Incoming Webhooks' - /> - )} - /> - <BackstageSection - name='outgoing_webhooks' - title={( - <FormattedMessage - id='backstage_sidebar.integrations.outgoing_webhooks' - defaultMessage='Outgoing Webhooks' - /> - )} - /> - <BackstageSection - name='commands' - title={( - <FormattedMessage - id='backstage_sidebar.integrations.commands' - defaultMessage='Slash Commands' - /> - )} - /> + {incomingWebhooks} + {outgoingWebhooks} + {commands} </BackstageCategory> </ul> </div> diff --git a/webapp/components/backstage/installed_commands.jsx b/webapp/components/backstage/installed_commands.jsx index 8b0cd59c8..71373e077 100644 --- a/webapp/components/backstage/installed_commands.jsx +++ b/webapp/components/backstage/installed_commands.jsx @@ -21,21 +21,16 @@ export default class InstalledCommands extends React.Component { this.deleteCommand = this.deleteCommand.bind(this); this.state = { - commands: [] + commands: IntegrationStore.getCommands(), + loading: !IntegrationStore.hasReceivedCommands() }; } - componentWillMount() { + componentDidMount() { IntegrationStore.addChangeListener(this.handleIntegrationChange); - if (window.mm_config.EnableCommands === 'true') { - if (IntegrationStore.hasReceivedCommands()) { - this.setState({ - commands: IntegrationStore.getCommands() - }); - } else { - AsyncClient.listTeamCommands(); - } + if (window.mm_config.EnableCommands === 'true' && this.state.loading) { + AsyncClient.listTeamCommands(); } } @@ -44,10 +39,9 @@ export default class InstalledCommands extends React.Component { } handleIntegrationChange() { - const commands = IntegrationStore.getCommands(); - this.setState({ - commands + commands: IntegrationStore.getCommands(), + loading: !IntegrationStore.hasReceivedCommands() }); } @@ -86,6 +80,13 @@ export default class InstalledCommands extends React.Component { /> } addLink={'/' + Utils.getTeamNameFromUrl() + '/settings/integrations/commands/add'} + emptyText={ + <FormattedMessage + id='installed_commands.empty' + defaultMessage='No slash commands found' + /> + } + loading={this.state.loading} > {commands} </InstalledIntegrations> diff --git a/webapp/components/backstage/installed_incoming_webhooks.jsx b/webapp/components/backstage/installed_incoming_webhooks.jsx index 0d6f900d1..389f65919 100644 --- a/webapp/components/backstage/installed_incoming_webhooks.jsx +++ b/webapp/components/backstage/installed_incoming_webhooks.jsx @@ -20,21 +20,16 @@ export default class InstalledIncomingWebhooks extends React.Component { this.deleteIncomingWebhook = this.deleteIncomingWebhook.bind(this); this.state = { - incomingWebhooks: [] + incomingWebhooks: IntegrationStore.getIncomingWebhooks(), + loading: !IntegrationStore.hasReceivedIncomingWebhooks() }; } - componentWillMount() { + componentDidMount() { IntegrationStore.addChangeListener(this.handleIntegrationChange); - if (window.mm_config.EnableIncomingWebhooks === 'true') { - if (IntegrationStore.hasReceivedIncomingWebhooks()) { - this.setState({ - incomingWebhooks: IntegrationStore.getIncomingWebhooks() - }); - } else { - AsyncClient.listIncomingHooks(); - } + if (window.mm_config.EnableIncomingWebhooks === 'true' && this.state.loading) { + AsyncClient.listIncomingHooks(); } } @@ -44,7 +39,8 @@ export default class InstalledIncomingWebhooks extends React.Component { handleIntegrationChange() { this.setState({ - incomingWebhooks: IntegrationStore.getIncomingWebhooks() + incomingWebhooks: IntegrationStore.getIncomingWebhooks(), + loading: !IntegrationStore.hasReceivedIncomingWebhooks() }); } @@ -78,6 +74,13 @@ export default class InstalledIncomingWebhooks extends React.Component { /> } addLink={'/' + Utils.getTeamNameFromUrl() + '/settings/integrations/incoming_webhooks/add'} + emptyText={ + <FormattedMessage + id='installed_incoming_webhooks.empty' + defaultMessage='No incoming webhooks found' + /> + } + loading={this.state.loading} > {incomingWebhooks} </InstalledIntegrations> diff --git a/webapp/components/backstage/installed_integrations.jsx b/webapp/components/backstage/installed_integrations.jsx index baf74447f..cff0611d7 100644 --- a/webapp/components/backstage/installed_integrations.jsx +++ b/webapp/components/backstage/installed_integrations.jsx @@ -6,6 +6,7 @@ import React from 'react'; import * as Utils from 'utils/utils.jsx'; import {Link} from 'react-router'; +import LoadingScreen from 'components/loading_screen.jsx'; export default class InstalledIntegrations extends React.Component { static get propTypes() { @@ -13,7 +14,9 @@ export default class InstalledIntegrations extends React.Component { children: React.PropTypes.node, header: React.PropTypes.node.isRequired, addLink: React.PropTypes.string.isRequired, - addText: React.PropTypes.node.isRequired + addText: React.PropTypes.node.isRequired, + emptyText: React.PropTypes.node.isRequired, + loading: React.PropTypes.bool.isRequired }; } @@ -36,9 +39,23 @@ export default class InstalledIntegrations extends React.Component { render() { const filter = this.state.filter.toLowerCase(); - const children = React.Children.map(this.props.children, (child) => { - return React.cloneElement(child, {filter}); - }); + let children; + + if (this.props.loading) { + children = <LoadingScreen/>; + } else { + children = React.Children.map(this.props.children, (child) => { + return React.cloneElement(child, {filter}); + }); + + if (children.length === 0) { + children = ( + <span className='backstage-list__item backstage-list_empty'> + {this.props.emptyText} + </span> + ); + } + } return ( <div className='backstage-content'> diff --git a/webapp/components/backstage/installed_outgoing_webhooks.jsx b/webapp/components/backstage/installed_outgoing_webhooks.jsx index 98992b081..e0817fda8 100644 --- a/webapp/components/backstage/installed_outgoing_webhooks.jsx +++ b/webapp/components/backstage/installed_outgoing_webhooks.jsx @@ -21,21 +21,16 @@ export default class InstalledOutgoingWebhooks extends React.Component { this.deleteOutgoingWebhook = this.deleteOutgoingWebhook.bind(this); this.state = { - outgoingWebhooks: [] + outgoingWebhooks: IntegrationStore.getOutgoingWebhooks(), + loading: !IntegrationStore.hasReceivedOutgoingWebhooks() }; } - componentWillMount() { + componentDidMount() { IntegrationStore.addChangeListener(this.handleIntegrationChange); - if (window.mm_config.EnableOutgoingWebhooks === 'true') { - if (IntegrationStore.hasReceivedOutgoingWebhooks()) { - this.setState({ - outgoingWebhooks: IntegrationStore.getOutgoingWebhooks() - }); - } else { - AsyncClient.listOutgoingHooks(); - } + if (window.mm_config.EnableOutgoingWebhooks === 'true' && this.state.loading) { + AsyncClient.listOutgoingHooks(); } } @@ -45,7 +40,8 @@ export default class InstalledOutgoingWebhooks extends React.Component { handleIntegrationChange() { this.setState({ - outgoingWebhooks: IntegrationStore.getOutgoingWebhooks() + outgoingWebhooks: IntegrationStore.getOutgoingWebhooks(), + loading: !IntegrationStore.hasReceivedOutgoingWebhooks() }); } @@ -84,6 +80,13 @@ export default class InstalledOutgoingWebhooks extends React.Component { /> } addLink={'/' + Utils.getTeamNameFromUrl() + '/settings/integrations/outgoing_webhooks/add'} + emptyText={ + <FormattedMessage + id='installed_outgoing_webhooks.empty' + defaultMessage='No outgoing webhooks found' + /> + } + loading={this.state.loading} > {outgoingWebhooks} </InstalledIntegrations> diff --git a/webapp/components/navbar_dropdown.jsx b/webapp/components/navbar_dropdown.jsx index 71c1f0d5b..967c5a95c 100644 --- a/webapp/components/navbar_dropdown.jsx +++ b/webapp/components/navbar_dropdown.jsx @@ -143,19 +143,21 @@ export default class NavbarDropdown extends React.Component { ); } - if (window.mm_config.EnableIncomingWebhooks === 'true' || window.mm_config.EnableOutgoingWebhooks === 'true') { - if (isAdmin || window.EnableAdminOnlyIntegrations !== 'true') { - integrationsLink = ( - <li> - <Link to={'/' + Utils.getTeamNameFromUrl() + '/settings/integrations'}> - <FormattedMessage - id='navbar_dropdown.integrations' - defaultMessage='Integrations' - /> - </Link> - </li> - ); - } + const integrationsEnabled = + window.mm_config.EnableIncomingWebhooks === 'true' || + window.mm_config.EnableOutgoingWebhooks === 'true' || + window.mm_config.EnableCommands === 'true'; + if (integrationsEnabled && (isAdmin || window.EnableOnlyAdminIntegrations !== 'true')) { + integrationsLink = ( + <li> + <Link to={'/' + Utils.getTeamNameFromUrl() + '/settings/integrations'}> + <FormattedMessage + id='navbar_dropdown.integrations' + defaultMessage='Integrations' + /> + </Link> + </li> + ); } if (isSystemAdmin) { diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index d2bf7608e..6156a1ef7 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -902,8 +902,10 @@ "get_team_invite_link_modal.helpDisabled": "User creation has been disabled for your team. Please ask your team administrator for details.", "get_team_invite_link_modal.title": "Team Invite Link", "installed_commands.add": "Add Slash Command", + "installed_commands.empty": "No commands found", "installed_commands.header": "Slash Commands", "installed_incoming_webhooks.add": "Add Incoming Webhook", + "installed_incoming_webhooks.empty": "No incoming webhooks found", "installed_incoming_webhooks.header": "Incoming Webhooks", "installed_integrations.creation": "Created by {creator} on {createAt, date, full}", "installed_integrations.delete": "Delete", @@ -912,6 +914,7 @@ "installed_integrations.token": "Token: {token}", "installed_integrations.url": "URL: {url}", "installed_outgoing_webhooks.add": "Add Outgoing Webhook", + "installed_outgoing_webhooks.empty": "No outgoing webhooks found", "installed_outgoing_webhooks.header": "Outgoing Webhooks", "integrations.command.description": "Slash commands send events to external integrations", "integrations.command.title": "Slash Command", |