Skip to content

Commit

Permalink
ui: Statement Diagnostics History Empty
Browse files Browse the repository at this point in the history
added back lost functionality (link to statements details, tooltip with shortenedStatement, some css)
added loading state
change onClick prop of <Empty/> to handle both callback function or url string

Resolves: #46576

Release note (ui): new design of empty state on Diagnostics report
  • Loading branch information
vladlos committed Apr 27, 2020
1 parent bbe8b79 commit 09afd2f
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 26 deletions.
5 changes: 2 additions & 3 deletions pkg/ui/src/components/empty/empty.tsx
Expand Up @@ -20,8 +20,7 @@ export interface IEmptyProps {
link?: string;
anchor?: string;
backgroundImage?: string;
onClick?: () => void;
btnType?: "button" | "anchor";
onClick?: (() => void) | string;
}

export const Empty = ({
Expand Down Expand Up @@ -52,7 +51,7 @@ export const Empty = ({
<footer className="cl-empty-view__footer">
<Button
type="primary"
onClick={onClick}
onClick={() => typeof onClick === "string" ? window.open(onClick) : onClick()}
>
{label}
</Button>
Expand Down
5 changes: 5 additions & 0 deletions pkg/ui/src/redux/statements/statementsSelectors.ts
Expand Up @@ -38,6 +38,11 @@ export const selectStatementDiagnosticsReports = createSelector(
diagnosticsReports => diagnosticsReports,
);

export const statementDiagnosticsReportsInFlight = createSelector(
(state: AdminUIState) => state.cachedData.statementDiagnosticsReports.inFlight,
inFlight => inFlight,
);

type StatementDiagnosticsDictionary = {
[statementFingerprint: string]: IStatementDiagnosticsReport;
};
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/src/views/jobs/jobTable.tsx
Expand Up @@ -159,7 +159,7 @@ export class JobTable extends React.Component<JobTableProps, JobTableState> {
title: "There are no jobs to display.",
description: "The jobs page provides details about backup/restore jobs, schema changes, user-created table statistics, automatic table statistics jobs and changefeeds.",
label: "Learn more",
onClick: () => window.open(jobTable),
onClick: jobTable,
}}
pagination={pagination}
/>
Expand Down
Expand Up @@ -14,15 +14,17 @@ import { connect } from "react-redux";
import moment from "moment";
import { Action, Dispatch } from "redux";
import Long from "long";
import { Link } from "react-router-dom";
import { isUndefined } from "lodash";

import { Button, DownloadFile, DownloadFileRef, Text, TextTypes } from "src/components";
import { Button, DownloadFile, DownloadFileRef, Text, TextTypes, Tooltip } from "src/components";
import HeaderSection from "src/views/shared/components/headerSection";
import { AdminUIState } from "src/redux/state";
import { getStatementDiagnostics } from "src/util/api";
import { trustIcon } from "src/util/trust";
import DownloadIcon from "!!raw-loader!assets/download.svg";
import {
selectStatementDiagnosticsReports,
selectStatementDiagnosticsReports, selectStatementByFingerprint, statementDiagnosticsReportsInFlight,
} from "src/redux/statements/statementsSelectors";
import {
invalidateStatementDiagnosticsRequests,
Expand All @@ -39,6 +41,9 @@ import {
import { SortedTable, ColumnDescriptor } from "src/views/shared/components/sortedtable";
import { SortSetting } from "src/views/shared/components/sortabletable";
import { statementsTable } from "src/util/docs";
import { summarize } from "src/util/sql/summarize";
import { shortStatement } from "src/views/statements/statementsTable";
import { trackDownloadDiagnosticsBundle } from "src/util/analytics";

type StatementDiagnosticsHistoryViewProps = MapStateToProps & MapDispatchToProps;

Expand All @@ -51,6 +56,31 @@ interface StatementDiagnosticsHistoryViewState {

class StatementDiagnosticsHistoryTable extends SortedTable<{}> {}

const StatementColumn: React.FC<{ fingerprint: string }> = ({ fingerprint }) => {
const summary = summarize(fingerprint);
const shortenedStatement = shortStatement(summary, fingerprint);
const showTooltip = fingerprint !== shortenedStatement;

if (showTooltip) {
return (
<Text textType={TextTypes.Code}>
<Tooltip
placement="bottom"
title={
<pre className="cl-table-link__description">{ fingerprint }</pre>
}
overlayClassName="cl-table-link__statement-tooltip--fixed-width"
>
{shortenedStatement}
</Tooltip>
</Text>
);
}
return (
<Text textType={TextTypes.Code}>{shortenedStatement}</Text>
);
};

class StatementDiagnosticsHistoryView extends React.Component<StatementDiagnosticsHistoryViewProps, StatementDiagnosticsHistoryViewState> {
columns: ColumnDescriptor<IStatementDiagnosticsReport>[] = [
{
Expand All @@ -60,7 +90,25 @@ class StatementDiagnosticsHistoryView extends React.Component<StatementDiagnosti
},
{
title: "Statement",
cell: record => <Text textType={TextTypes.Code}>{record.statement_fingerprint}</Text>,
cell: record => {
const { getStatementByFingerprint } = this.props;
const fingerprint = record.statement_fingerprint;
const statement = getStatementByFingerprint(fingerprint);
const { implicit_txn: implicitTxn = "true", query } = statement?.key?.key_data || {};

if (isUndefined(query)) {
return <StatementColumn fingerprint={fingerprint} />;
}

return (
<Link
to={ `/statement/${implicitTxn}/${encodeURIComponent(query)}` }
className="crl-statements-diagnostics-view__statements-link"
>
<StatementColumn fingerprint={fingerprint} />
</Link>
);
},
sort: record => record.statement_fingerprint,
},
{
Expand All @@ -80,20 +128,22 @@ class StatementDiagnosticsHistoryView extends React.Component<StatementDiagnosti
if (record.completed) {
return (
<div className="crl-statements-diagnostics-view__actions-column cell--show-on-hover nodes-table__link">
<Button
onClick={() => this.getStatementDiagnostics(record.statement_diagnostics_id)}
size="small"
type="flat"
iconPosition="left"
icon={() => (
<span
className="crl-statements-diagnostics-view__icon"
dangerouslySetInnerHTML={ trustIcon(DownloadIcon) }
/>
)}
>
Download
</Button>
<a href={`_admin/v1/stmtbundle/${record.statement_diagnostics_id}`}
onClick={() => trackDownloadDiagnosticsBundle(record.statement_fingerprint)}>
<Button
size="small"
type="flat"
iconPosition="left"
icon={() => (
<span
className="crl-statements-diagnostics-view__icon"
dangerouslySetInnerHTML={ trustIcon(DownloadIcon) }
/>
)}
>
Bundle (.zip)
</Button>
</a>
</div>
);
}
Expand Down Expand Up @@ -150,7 +200,7 @@ class StatementDiagnosticsHistoryView extends React.Component<StatementDiagnosti
}

render() {
const { diagnosticsReports } = this.props;
const { diagnosticsReports, loading } = this.props;
const dataSource = diagnosticsReports.map((diagnosticsReport, idx) => ({
...diagnosticsReport,
key: idx,
Expand All @@ -171,12 +221,13 @@ class StatementDiagnosticsHistoryView extends React.Component<StatementDiagnosti
className="statements-table"
data={dataSource}
columns={this.columns}
empty={dataSource.length === 0}
loading={loading}
empty={!loading && dataSource.length === 0}
emptyProps={{
title: "There are no statement diagnostics to display.",
description: "Statement diagnostics can help when troubleshooting issues with specific queries. The diagnostic bundle can be activated from individual statement pages and will include EXPLAIN plans, table statistics, and traces.",
label: "Learn more",
onClick: () => window.open(statementsTable),
onClick: statementsTable,
}}
sortSetting={this.state.sortSetting}
onChangeSortSetting={this.changeSortSetting}
Expand All @@ -188,15 +239,19 @@ class StatementDiagnosticsHistoryView extends React.Component<StatementDiagnosti
}

interface MapStateToProps {
loading: boolean;
diagnosticsReports: IStatementDiagnosticsReport[];
getStatementByFingerprint: (fingerprint: string) => ReturnType<typeof selectStatementByFingerprint>;
}

interface MapDispatchToProps {
refresh: () => void;
}

const mapStateToProps = (state: AdminUIState): MapStateToProps => ({
loading: statementDiagnosticsReportsInFlight(state),
diagnosticsReports: selectStatementDiagnosticsReports(state) || [],
getStatementByFingerprint: (fingerprint: string) => selectStatementByFingerprint(state, fingerprint),
});

const mapDispatchToProps = (dispatch: Dispatch<Action, AdminUIState>): MapDispatchToProps => ({
Expand Down
Expand Up @@ -15,7 +15,7 @@
background $colors--white
padding $spacing-medium-small

& .crl-table-wrapper .ant-table-row:hover .nodes-table__link
& .crl-table-wrapper .sort-table__row:hover .nodes-table__link
color $colors--primary-blue-3
text-decoration underline

Expand Down
Expand Up @@ -66,6 +66,10 @@
&__row
border-top 1px solid transparent
border-bottom 1px solid $table-border
.cell--show-on-hover
visibility hidden
&:hover .cell--show-on-hover
visibility visible
&.drawer-active
background-color $background-color
.cl-table-link__tooltip
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/src/views/statements/statementsPage.tsx
Expand Up @@ -283,7 +283,7 @@ export class StatementsPage extends React.Component<StatementsPageProps, Stateme
title: "There are no statements since this page was last cleared.",
description: "Statements help you identify frequently executed or high latency SQL statements. Statements are cleared every hour by default, or according to your configuration.",
label: "Learn more",
onClick: () => window.open(statementsTable),
onClick: statementsTable,
}}
sortSetting={this.state.sortSetting}
onChangeSortSetting={this.changeSortSetting}
Expand Down

0 comments on commit 09afd2f

Please sign in to comment.