Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into qp-refactor-9
Browse files Browse the repository at this point in the history
  • Loading branch information
iethree committed Oct 19, 2018
2 parents 8a5eed1 + f1fef96 commit a6c4691
Show file tree
Hide file tree
Showing 91 changed files with 4,049 additions and 717 deletions.
12 changes: 12 additions & 0 deletions frontend/src/metabase/admin/routes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IndexRoute, IndexRedirect } from "react-router";
import { t } from "c-3po";

import { withBackground } from "metabase/hoc/Background";
import { ModalRoute } from "metabase/hoc/ModalRoute";

// Settings
import SettingsEditorApp from "metabase/admin/settings/containers/SettingsEditorApp.jsx";
Expand All @@ -21,6 +22,9 @@ import AdminPeopleApp from "metabase/admin/people/containers/AdminPeopleApp.jsx"
import FieldApp from "metabase/admin/datamodel/containers/FieldApp.jsx";
import TableSettingsApp from "metabase/admin/datamodel/containers/TableSettingsApp.jsx";

import TasksApp from "metabase/admin/tasks/containers/TasksApp";
import TaskModal from "metabase/admin/tasks/containers/TaskModal";

// People
import PeopleListingApp from "metabase/admin/people/containers/PeopleListingApp.jsx";
import GroupsListingApp from "metabase/admin/people/containers/GroupsListingApp.jsx";
Expand Down Expand Up @@ -75,6 +79,14 @@ const getRoutes = (store, IsAdmin) => (
</Route>
</Route>

{/* Troubleshooting */}
<Route path="troubleshooting" title={t`Troubleshooting`}>
<IndexRedirect to="tasks" />
<Route path="tasks" component={TasksApp}>
<ModalRoute path=":taskId" modal={TaskModal} />
</Route>
</Route>

{/* SETTINGS */}
<Route path="settings" title={t`Settings`}>
<IndexRedirect to="/admin/settings/setup" />
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/metabase/admin/settings/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ const SECTIONS = [
display_name: t`Enable Nested Queries`,
type: "boolean",
},
{
key: "enable-xrays",
display_name: t`Enable X-ray features`,
type: "boolean",
},
],
},
{
Expand Down
27 changes: 27 additions & 0 deletions frontend/src/metabase/admin/tasks/containers/TaskModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import { t } from "c-3po";
import { connect } from "react-redux";
import { goBack } from "react-router-redux";

import { entityObjectLoader } from "metabase/entities/containers/EntityObjectLoader";

import Code from "metabase/components/Code";
import ModalContent from "metabase/components/ModalContent";

@entityObjectLoader({
entityType: "tasks",
entityId: (state, props) => props.params.taskId,
})
@connect(null, { goBack })
class TaskModal extends React.Component {
render() {
const { object } = this.props;
return (
<ModalContent title={t`Task details`} onClose={() => this.props.goBack()}>
<Code>{JSON.stringify(object.task_details)}</Code>
</ModalContent>
);
}
}

export default TaskModal;
97 changes: 97 additions & 0 deletions frontend/src/metabase/admin/tasks/containers/TasksApp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from "react";
import { t } from "c-3po";
import { Box, Flex } from "grid-styled";

import { entityListLoader } from "metabase/entities/containers/EntityListLoader";

import AdminHeader from "metabase/components/AdminHeader";
import Icon, { IconWrapper } from "metabase/components/Icon";
import Link from "metabase/components/Link";
import Tooltip from "metabase/components/Tooltip";

@entityListLoader({
entityType: "tasks",
pageSize: 50,
})
class TasksApp extends React.Component {
constructor(props) {
super(props);
this.state = {
offset: this.props.entityQuery.offset,
};
}
render() {
const {
tasks,
page,
pageSize,
onNextPage,
onPreviousPage,
children,
} = this.props;
return (
<Box p={3}>
<Flex align="center">
<Flex align="center">
<AdminHeader title={t`Troubleshooting logs`} />
<Tooltip
tooltip={t`Trying to get to the bottom of something? This section shows logs of Metabase's background tasks, which can help shed light on what's going on.`}
>
<Icon
name="info"
ml={1}
style={{ marginTop: 5 }}
className="text-brand-hover cursor-pointer text-medium"
/>
</Tooltip>
</Flex>
<Flex align="center" ml="auto">
<span className="text-bold mr1">
{page * pageSize + 1} - {page * pageSize + tasks.length}
</span>
<IconWrapper onClick={onPreviousPage} disabled={!onPreviousPage}>
<Icon name="chevronleft" />
</IconWrapper>
<IconWrapper small onClick={onNextPage} disabled={!onNextPage}>
<Icon name="chevronright" />
</IconWrapper>
</Flex>
</Flex>

<table className="ContentTable mt2">
<thead>
<th>{t`Task`}</th>
<th>{t`DB ID`}</th>
<th>{t`Started at`}</th>
<th>{t`Ended at`}</th>
<th>{t`Duration (ms)`}</th>
<th>{t`Details`}</th>
</thead>
<tbody>
{tasks.map(task => (
<tr key={task.id}>
<td className="text-bold">{task.task}</td>
<td>{task.db_id}</td>
<td>{task.started_at}</td>
<td>{task.ended_at}</td>
<td>{task.duration}</td>
<td>
<Link
className="link text-bold"
to={`/admin/troubleshooting/tasks/${task.id}`}
>{t`View`}</Link>
</td>
</tr>
))}
</tbody>
</table>
{
// render 'children' so that the invididual task modals show up
children
}
</Box>
);
}
}

export default TasksApp;
33 changes: 20 additions & 13 deletions frontend/src/metabase/components/BrowseApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import React from "react";
import { Box, Flex } from "grid-styled";
import { t } from "c-3po";
import BrowserCrumbs from "metabase/components/BrowserCrumbs";
import { connect } from "react-redux";

import EntityItem from "metabase/components/EntityItem";
import EntityListLoader from "metabase/entities/containers/EntityListLoader";
import EntityObjectLoader from "metabase/entities/containers/EntityObjectLoader";

import { normal } from "metabase/lib/colors";
import Question from "metabase-lib/lib/Question";
import { getXraysEnabled } from "metabase/selectors/settings";

import Card from "metabase/components/Card";
import { Grid, GridItem } from "metabase/components/Grid";
Expand Down Expand Up @@ -136,6 +138,9 @@ export class SchemaBrowser extends React.Component {
}
}

@connect(state => ({
xraysEnabled: getXraysEnabled(state),
}))
export class TableBrowser extends React.Component {
render() {
const { dbId, schemaName } = this.props.params;
Expand Down Expand Up @@ -185,19 +190,21 @@ export class TableBrowser extends React.Component {
</Link>
<Box ml="auto" mr={1} className="hover-child">
<Flex align="center">
<Tooltip tooltip={t`X-ray this table`}>
<Link
to={`auto/dashboard/table/${table.id}`}
data-metabase-event={`${ANALYTICS_CONTEXT};Table Item;X-ray Click`}
>
<Icon
name="bolt"
mx={1}
color={normal.yellow}
size={20}
/>
</Link>
</Tooltip>
{this.props.xraysEnabled && (
<Tooltip tooltip={t`X-ray this table`}>
<Link
to={`auto/dashboard/table/${table.id}`}
data-metabase-event={`${ANALYTICS_CONTEXT};Table Item;X-ray Click`}
>
<Icon
name="bolt"
mx={1}
color={normal.yellow}
size={20}
/>
</Link>
</Tooltip>
)}
<Tooltip tooltip={t`Learn about this table`}>
<Link
to={`reference/databases/${dbId}/tables/${
Expand Down
97 changes: 97 additions & 0 deletions frontend/src/metabase/components/ColorRangePicker.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* @flow */

import React from "react";

import PopoverWithTrigger from "metabase/components/PopoverWithTrigger";

import { getColorScale } from "metabase/lib/colors";

import d3 from "d3";
import cx from "classnames";

import type { ColorString } from "metabase/lib/colors";

type Props = {
value: ColorString[],
onChange: (ColorString[]) => void,
ranges: ColorString[][],
className?: string,
style?: { [key: string]: any },
sections?: number,
quantile?: boolean,
columns?: number,
};

const ColorRangePicker = ({
value,
onChange,
ranges,
className,
style,
sections = 5,
quantile = false,
columns = 2,
}: Props) => (
<PopoverWithTrigger
triggerElement={
<ColorRangePreview
colors={value}
className={cx(className, "bordered rounded overflow-hidden")}
style={{ height: 30, ...style }}
sections={sections}
quantile={quantile}
/>
}
>
{({ onClose }) => (
<div className="pt1 mr1 flex flex-wrap" style={{ width: 300 }}>
{ranges.map(range => (
<div
className={"mb1 pl1"}
style={{ flex: `1 1 ${Math.round(100 / columns)}%` }}
>
<ColorRangePreview
colors={range}
onClick={() => {
onChange(range);
onClose();
}}
className={cx("bordered rounded overflow-hidden cursor-pointer")}
style={{ height: 30 }}
sections={sections}
quantile={quantile}
/>
</div>
))}
</div>
)}
</PopoverWithTrigger>
);

type ColorRangePreviewProps = {
colors: ColorString[],
sections?: number,
quantile?: boolean,
className?: string,
};

export const ColorRangePreview = ({
colors = [],
sections = 5,
quantile = false,
className,
...props
}: ColorRangePreviewProps) => {
const scale = getColorScale([0, sections - 1], colors, quantile);
return (
<div className={cx(className, "flex")} {...props}>
{d3
.range(0, sections)
.map(value => (
<div className="flex-full" style={{ background: scale(value) }} />
))}
</div>
);
};

export default ColorRangePicker;
6 changes: 4 additions & 2 deletions frontend/src/metabase/components/ProgressBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Props = {
percentage: number,
animated: boolean,
color: string,
height: number,
};

export default class ProgressBar extends Component {
Expand All @@ -16,17 +17,18 @@ export default class ProgressBar extends Component {
static defaultProps = {
animated: false,
color: colors["brand"],
height: 10,
};

render() {
const { percentage, animated, color } = this.props;
const { percentage, animated, color, height } = this.props;

const width = percentage * 100;

const wrapperStyles = cxs({
position: "relative",
border: `1px solid ${color}`,
height: 10,
height,
borderRadius: 99,
});

Expand Down
Loading

0 comments on commit a6c4691

Please sign in to comment.