diff --git a/frontend/src/metabase/components/ChannelSetupMessage.jsx b/frontend/src/metabase/components/ChannelSetupMessage.jsx index 136d229ce525..e089faf87c89 100644 --- a/frontend/src/metabase/components/ChannelSetupMessage.jsx +++ b/frontend/src/metabase/components/ChannelSetupMessage.jsx @@ -13,7 +13,7 @@ export default class ChannelSetupMessage extends Component { }; static defaultProps = { - channels: ["email", "Slack"], + channels: ["email"], }; render() { diff --git a/frontend/src/metabase/components/ChannelSetupModal.jsx b/frontend/src/metabase/components/ChannelSetupModal.jsx index 667e97c2f9e3..a270a7ad79d5 100644 --- a/frontend/src/metabase/components/ChannelSetupModal.jsx +++ b/frontend/src/metabase/components/ChannelSetupModal.jsx @@ -16,7 +16,7 @@ export default class ChannelSetupModal extends Component { }; static defaultProps = { - channels: ["email", "Slack"], + channels: ["email"], }; render() { diff --git a/frontend/src/metabase/components/CollectionLanding.jsx b/frontend/src/metabase/components/CollectionLanding.jsx index 7a732dbbfa8e..643edc5c634f 100644 --- a/frontend/src/metabase/components/CollectionLanding.jsx +++ b/frontend/src/metabase/components/CollectionLanding.jsx @@ -72,7 +72,7 @@ const DashboardEmptyState = () => ( const PulseEmptyState = () => ( } /> diff --git a/frontend/src/metabase/components/ItemTypeFilterBar.jsx b/frontend/src/metabase/components/ItemTypeFilterBar.jsx index d3fb6527fdd0..df69cd7b9b60 100644 --- a/frontend/src/metabase/components/ItemTypeFilterBar.jsx +++ b/frontend/src/metabase/components/ItemTypeFilterBar.jsx @@ -23,6 +23,11 @@ export const FILTERS = [ name: t`Questions`, filter: "card", icon: "beaker", + }, + { + name: t`Pulses`, + filter: "pulse", + icon: "pulse", } ]; diff --git a/frontend/src/metabase/containers/Overworld.jsx b/frontend/src/metabase/containers/Overworld.jsx index b68ac312b7d1..2e9db758697c 100644 --- a/frontend/src/metabase/containers/Overworld.jsx +++ b/frontend/src/metabase/containers/Overworld.jsx @@ -229,11 +229,11 @@ export class AdminPinMessage extends React.Component { const SectionHeading = ({ children }) => ( -
{children} -
+
); diff --git a/frontend/src/metabase/nav/containers/Navbar.jsx b/frontend/src/metabase/nav/containers/Navbar.jsx index 68982c809026..1e6d8cb55a35 100644 --- a/frontend/src/metabase/nav/containers/Navbar.jsx +++ b/frontend/src/metabase/nav/containers/Navbar.jsx @@ -29,11 +29,13 @@ import ProfileLink from "metabase/nav/components/ProfileLink.jsx"; import { getPath, getContext, getUser } from "../selectors"; import { entityListLoader } from "metabase/entities/containers/EntityListLoader"; +import {getMetadata} from "metabase/selectors/metadata"; const mapStateToProps = (state, props) => ({ path: getPath(state, props), context: getContext(state, props), user: getUser(state), + metadata: getMetadata(state) }); const mapDispatchToProps = { @@ -41,29 +43,29 @@ const mapDispatchToProps = { }; const AdminNavItem = ({ name, path, currentPath }) => ( -
  • - - {name} - -
  • +
  • + + {name} + +
  • ); const DefaultSearchColor = color(colors.brand) - .lighten(0.07) - .string(); + .lighten(0.07) + .string(); const ActiveSearchColor = color(colors.brand) - .lighten(0.1) - .string(); + .lighten(0.1) + .string(); const SearchWrapper = Flex.extend` ${width} background-color: ${props => - props.active ? ActiveSearchColor : DefaultSearchColor}; + props.active ? ActiveSearchColor : DefaultSearchColor}; border-radius: 6px; align-items: center; color: white; @@ -114,34 +116,34 @@ class SearchBar extends React.Component { render() { const { active, searchText } = this.state; return ( - this.setState({ active: false })} - > - this.setState({ active: true })} - active={active} + this.setState({ active: false })} > - - this.setState({ active: true })} - onChange={e => this.setState({ searchText: e.target.value })} - onKeyPress={e => { - if (e.key === "Enter" && (searchText || "").trim().length > 0) { - this.props.onChangeLocation({ - pathname: "search", - query: { q: searchText }, - }); - } - }} - /> - - + this.setState({ active: true })} + active={active} + > + + this.setState({ active: true })} + onChange={e => this.setState({ searchText: e.target.value })} + onKeyPress={e => { + if (e.key === "Enter" && (searchText || "").trim().length > 0) { + this.props.onChangeLocation({ + pathname: "search", + query: { q: searchText }, + }); + } + }} + /> + + ); } } @@ -187,138 +189,149 @@ export default class Navbar extends Component { renderAdminNav() { return ( - // NOTE: DO NOT REMOVE `Nav` CLASS FOR NOW, USED BY MODALS, FULLSCREEN DASHBOARD, ETC - // TODO: hide nav using state in redux instead? - ); } renderEmptyNav() { return ( - // NOTE: DO NOT REMOVE `Nav` CLASS FOR NOW, USED BY MODALS, FULLSCREEN DASHBOARD, ETC - // TODO: hide nav using state in redux instead? - + // NOTE: DO NOT REMOVE `Nav` CLASS FOR NOW, USED BY MODALS, FULLSCREEN DASHBOARD, ETC + // TODO: hide nav using state in redux instead? + ); } renderMainNav() { const hasDataAccess = - this.props.databases && this.props.databases.length > 0; + this.props.databases && this.props.databases.length > 0; + const hasSQLPermission = db => db.native_permissions === "write"; + const showSQLOption = this.props.databases && + this.props.databases.filter(hasSQLPermission).length > 0; + const itemsNav = [ + { + title: t`New dashboard`, + icon: `dashboard`, + action: () => this.setModal(MODAL_NEW_DASHBOARD), + event: `NavBar;New Dashboard Click;`, + }]; + if (showSQLOption) { + itemsNav.push({ + title: t`New pulse`, + icon: `pulse`, + link: Urls.newPulse(), + event: `NavBar;New Pulse Click;`, + }); + } return ( - - - - - - + + + + + + + + + {hasDataAccess && ( + + + + )} + - - - - {hasDataAccess && ( - - - - )} - this.setModal(MODAL_NEW_DASHBOARD), - event: `NavBar;New Dashboard Click;`, - }, - ]} - /> - + + + {this.renderModal()} - {this.renderModal()} - ); } @@ -326,14 +339,14 @@ export default class Navbar extends Component { const { modal } = this.state; if (modal) { return ( - this.setState({ modal: null })}> - {modal === MODAL_NEW_DASHBOARD ? ( - this.setState({ modal: null })} - /> - ) : null} - + this.setState({ modal: null })}> + {modal === MODAL_NEW_DASHBOARD ? ( + this.setState({ modal: null })} + /> + ) : null} + ); } else { return null; diff --git a/frontend/src/metabase/pulse/components/PulseEditChannels.jsx b/frontend/src/metabase/pulse/components/PulseEditChannels.jsx index 69f5caf18735..f70a5bda5cd0 100644 --- a/frontend/src/metabase/pulse/components/PulseEditChannels.jsx +++ b/frontend/src/metabase/pulse/components/PulseEditChannels.jsx @@ -256,39 +256,41 @@ export default class PulseEditChannels extends Component { let { pulse, user } = this.props; let channels = pulse.channels .map((c, i) => [c, i]) - .filter(([c, i]) => c.enabled && c.channel_type === channelSpec.type) + .filter(([c, i]) => c.enabled && c.channel_type === channelSpec.type && c.channel_type !== 'slack') .map(([channel, index]) => this.renderChannel(channel, index, channelSpec), ); - return ( -
  • -
    - {CHANNEL_ICONS[channelSpec.type] && ( - - )} -

    {channelSpec.name}

    - 0} - onChange={this.toggleChannel.bind(this, channelSpec.type)} - /> -
    - {channels.length > 0 && channelSpec.configured ? ( - - ) : channels.length > 0 && !channelSpec.configured ? ( -
    -

    {t`${ - channelSpec.name - } needs to be set up by an administrator.`}

    - -
    - ) : null} -
  • - ); + if (channelSpec.type === 'email') { + return ( +
  • +
    + {CHANNEL_ICONS[channelSpec.type] && ( + + )} +

    {channelSpec.name}

    + 0} + onChange={this.toggleChannel.bind(this, channelSpec.type)} + /> +
    + {channels.length > 0 && channelSpec.configured ? ( + + ) : channels.length > 0 && !channelSpec.configured ? ( +
    +

    {t`${ + channelSpec.name + } needs to be set up by an administrator.`}

    + +
    + ) : null} +
  • + ); + } } render() { @@ -296,7 +298,6 @@ export default class PulseEditChannels extends Component { // Default to show the default channels until full formInput is loaded let channels = formInput.channels || { email: { name: t`Email`, type: "email" }, - slack: { name: t`Slack`, type: "slack" }, }; return (