Skip to content
Snippets Groups Projects
Commit 46367b52 authored by Atte Keinänen's avatar Atte Keinänen
Browse files

Add 'Metabase is no fun without any data' state to new question flow

parent f41163d8
No related branches found
No related tags found
No related merge requests found
import React from "react";
import React, { Component } from "react";
import EmptyState from "metabase/components/EmptyState.jsx";
import { getUser } from "metabase/selectors/user";
import { connect } from "react-redux";
/*
* AdminAwareEmptyState is a component that can
* 1) Produce a custom message for admins in empty results
*/
const AdminAwareEmptyState = ({user, title, message, adminMessage, icon, image, imageHeight, imageClassName, action, adminAction, link, adminLink, onActionClick, smallDescription = false}) =>
<EmptyState
title={title}
message={user && user.is_superuser ?
adminMessage || message :
message
}
icon={icon}
image={image}
action={user && user.is_superuser ?
adminAction || action :
action
}
link={user && user.is_superuser ?
adminLink || link :
link
}
imageHeight={imageHeight}
imageClassName={imageClassName}
onActionClick={onActionClick}
smallDescription={smallDescription}
/>
const mapStateToProps = (state, props) => ({
user: getUser(state, props),
});
@connect(mapStateToProps, null)
class AdminAwareEmptyState extends Component {
render() {
const {user, title, message, adminMessage, icon, image, imageHeight, imageClassName, action, adminAction, link, adminLink, onActionClick, smallDescription = false} = this.props;
return (
<EmptyState
title={title}
message={user && user.is_superuser ?
adminMessage || message :
message
}
icon={icon}
image={image}
action={user && user.is_superuser ?
adminAction || action :
action
}
link={user && user.is_superuser ?
adminLink || link :
link
}
imageHeight={imageHeight}
imageClassName={imageClassName}
onActionClick={onActionClick}
smallDescription={smallDescription}
/>
)
}
}
export default AdminAwareEmptyState;
\ No newline at end of file
......@@ -19,6 +19,7 @@ import NativeQuery from "metabase-lib/lib/queries/NativeQuery";
import { getCurrentQuery, getPlainNativeQuery } from "metabase/new_query/selectors";
import { getUserIsAdmin } from "metabase/selectors/user";
import { push } from "react-router-redux";
import NoDatabasesEmptyState from "metabase/reference/databases/NoDatabasesEmptyState";
const mapStateToProps = state => ({
query: getCurrentQuery(state),
......@@ -55,45 +56,72 @@ type Props = {
fetchSegments: () => void,
}
const allOptionsVisibleState = {
loaded: true,
hasDatabases: true,
showMetricOption: true,
showTableOption: true,
showSQLOption: true
}
export class NewQueryOptions extends Component {
props: Props
state = {
showMetricOption: false,
showSegmentOption: false,
showSQLOption: false
constructor(props) {
super(props)
// By default, show all options instantly to admins
this.state = props.isAdmin ? allOptionsVisibleState : {
loaded: false,
hasDatabases: false,
showMetricOption: false,
showTableOption: false,
showSQLOption: false
}
}
determinePaths () {
determineWhichOptionsToShow() {
const { isAdmin, metadata, push } = this.props
const showMetricOption = isAdmin || metadata.metricsList().length > 0
const showSegmentOption = isAdmin || metadata.segmentsList().length > 0
// util to check if the user has write permission to a db
const hasSQLPermission = (db) => db.native_permissions === "write"
// to be able to use SQL the user must have write permissions on at least one db
const showSQLOption = isAdmin || metadata.databasesList().filter(hasSQLPermission).length > 0
// if we can only show one option then we should just redirect
if(!showMetricOption && !showSQLOption && !showSegmentOption) {
push(this.getGuiQueryUrl())
const hasDatabases = metadata.databasesList().length > 0
console.log(metadata.databasesList())
if (!hasDatabases) {
this.setState({ loaded: true, hasDatabases: false })
} else if (isAdmin) {
this.setState(allOptionsVisibleState)
} else {
const showMetricOption = metadata.metricsList().length > 0
const showTableOption = metadata.segmentsList().length > 0
// to be able to use SQL the user must have write permissions on at least one db
const hasSQLPermission = (db) => db.native_permissions === "write"
const showSQLOption = metadata.databasesList().filter(hasSQLPermission).length > 0
// if we can only show one option then we should just redirect
const redirectToQueryBuilder =
!showMetricOption && !showSQLOption && !showTableOption
if (redirectToQueryBuilder) {
push(this.getGuiQueryUrl())
} else {
this.setState({
loaded: true,
showMetricOption,
showTableOption,
showSQLOption,
})
}
}
this.setState({
showMetricOption,
showSegmentOption,
showSQLOption,
})
}
async componentWillMount() {
await this.props.fetchDatabases()
await this.props.fetchMetrics()
await this.props.fetchSegments()
await this.props.resetQuery();
this.props.resetQuery();
this.determinePaths()
Promise.all([
this.props.fetchDatabases(),
this.props.fetchMetrics(),
this.props.fetchSegments()
]).then(() => this.determineWhichOptionsToShow())
}
getGuiQueryUrl = () => {
......@@ -105,20 +133,28 @@ export class NewQueryOptions extends Component {
}
render() {
const { query, metadataFetched, isAdmin, metricSearchUrl } = this.props
const { showMetricOption, showSQLOption } = this.state
const showCustomInsteadOfNewQuestionText = showMetricOption || isAdmin
const { isAdmin, metricSearchUrl } = this.props
const { loaded, hasDatabases, showMetricOption, showTableOption, showSQLOption } = this.state
const showCustomInsteadOfNewQuestionText = showMetricOption || showTableOption || isAdmin
if (!query || (!isAdmin && (!metadataFetched.metrics || !metadataFetched.segments))) {
if (!loaded) {
return <LoadingAndErrorWrapper loading={true}/>
}
if (!hasDatabases) {
return (
<div className="full-height flex align-center justify-center">
<NoDatabasesEmptyState/>
</div>
)
}
return (
<div className="full-height flex">
<div className="wrapper wrapper--trim lg-wrapper--trim xl-wrapper--trim flex-full px1 mt4 mb2 align-center">
<div className="flex align-center justify-center" style={{minHeight: "100%"}}>
<ol className="flex-full Grid Grid--guttersXl Grid--full sm-Grid--normal">
{ (showMetricOption || isAdmin) &&
{ showMetricOption &&
<li className="Grid-cell">
<NewQueryOption
image="/app/img/questions_illustration"
......@@ -138,7 +174,7 @@ export class NewQueryOptions extends Component {
to={this.getGuiQueryUrl}
/>
</li>
{ (showSQLOption || isAdmin) &&
{ showSQLOption &&
<li className="Grid-cell">
<NewQueryOption
image="/app/img/sql_illustration"
......
......@@ -9,7 +9,6 @@ import S from "metabase/components/List.css";
import List from "metabase/components/List.jsx";
import ListItem from "metabase/components/ListItem.jsx";
import AdminAwareEmptyState from "metabase/components/AdminAwareEmptyState.jsx";
import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper.jsx";
......@@ -22,15 +21,7 @@ import {
} from "../selectors";
import * as metadataActions from "metabase/redux/metadata";
const emptyStateData = {
title: "Metabase is no fun without any data",
adminMessage: "Your databases will appear here once you connect one",
message: "Databases will appear here once your admins have added some",
image: "app/assets/img/databases-list",
adminAction: "Connect a database",
adminLink: "/admin/databases/create"
}
import NoDatabasesEmptyState from "metabase/reference/databases/NoDatabasesEmptyState";
const mapStateToProps = (state, props) => ({
entities: getDatabases(state, props),
......@@ -88,7 +79,7 @@ export default class DatabaseList extends Component {
</div>
:
<div className={S.empty}>
<AdminAwareEmptyState {...emptyStateData}/>
<NoDatabasesEmptyState />
</div>
}
</LoadingAndErrorWrapper>
......
import * as React from "react";
import AdminAwareEmptyState from "metabase/components/AdminAwareEmptyState";
const NoDatabasesEmptyState = (user) =>
<AdminAwareEmptyState
title={"Metabase is no fun without any data"}
adminMessage={"Your databases will appear here once you connect one"}
message={"Databases will appear here once your admins have added some"}
image={"app/assets/img/databases-list"}
adminAction={"Connect a database"}
adminLink={"/admin/databases/create"}
user={user}
/>
export default NoDatabasesEmptyState
\ No newline at end of file
......@@ -30,7 +30,7 @@ const emptyStateData = {
message: "Metrics will appear here once your admins have created some",
image: "app/assets/img/metrics-list",
adminAction: "Learn how to create metrics",
adminLink: "http://www.metabase.com/docs/latest/administration-guide/06-segments-and-metrics.html"
adminLink: "http://www.metabase.com/docs/latest/administration-guide/07-segments-and-metrics.html"
}
const mapStateToProps = (state, props) => ({
......
......@@ -29,7 +29,7 @@ const emptyStateData = {
message: "Segments will appear here once your admins have created some",
image: "app/assets/img/segments-list",
adminAction: "Learn how to create segments",
adminLink: "http://www.metabase.com/docs/latest/administration-guide/06-segments-and-metrics.html"
adminLink: "http://www.metabase.com/docs/latest/administration-guide/07-segments-and-metrics.html"
}
const mapStateToProps = (state, props) => ({
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment