diff --git a/pkg/ui/workspaces/cluster-ui/src/loading/loading.spec.tsx b/pkg/ui/workspaces/cluster-ui/src/loading/loading.spec.tsx
index b83240f802dd..25194c9aa602 100644
--- a/pkg/ui/workspaces/cluster-ui/src/loading/loading.spec.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/loading/loading.spec.tsx
@@ -15,6 +15,7 @@ import { Spinner, InlineAlert } from "@cockroachlabs/ui-components";
import { Loading } from "./loading";
const SomeComponent = () =>
Hello, world!
;
+const SomeCustomErrorComponent = () => Custom Error
;
describe("", () => {
describe("when error is null", () => {
@@ -73,8 +74,23 @@ describe("", () => {
);
assert.isFalse(wrapper.find(SomeComponent).exists());
assert.isFalse(wrapper.find(Spinner).exists());
+ assert.isFalse(wrapper.find(SomeCustomErrorComponent).exists());
assert.isTrue(wrapper.find(InlineAlert).exists());
});
+
+ it("render custom error when provided", () => {
+ const wrapper = mount(
+ }
+ renderError={() => }
+ />,
+ );
+ assert.isFalse(wrapper.find(SomeComponent).exists());
+ assert.isFalse(wrapper.find(Spinner).exists());
+ assert.isTrue(wrapper.find(SomeCustomErrorComponent).exists());
+ });
});
});
diff --git a/pkg/ui/workspaces/cluster-ui/src/loading/loading.tsx b/pkg/ui/workspaces/cluster-ui/src/loading/loading.tsx
index ec0fcf42f262..a7bea32f5585 100644
--- a/pkg/ui/workspaces/cluster-ui/src/loading/loading.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/loading/loading.tsx
@@ -29,6 +29,7 @@ interface LoadingProps {
render: () => any;
errorClassName?: string;
loadingClassName?: string;
+ renderError?: () => React.ReactElement;
}
const cx = classNames.bind(styles);
@@ -81,7 +82,11 @@ export const Loading: React.FC = props => {
} else {
return {
intent: "danger",
- description: {error.message},
+ description: props.renderError ? (
+ props.renderError()
+ ) : (
+ {error.message}
+ ),
};
}
})
diff --git a/pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetails.tsx
index 40450d93799d..bfe61db5ac4b 100644
--- a/pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetails.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetails.tsx
@@ -19,6 +19,7 @@ import { Link, RouteComponentProps } from "react-router-dom";
import { SessionInfo } from "./sessionsTable";
import { SummaryCard, SummaryCardItem } from "../summaryCard";
+import SQLActivityError from "../sqlActivity/errorComponent";
import { TimestampToMoment } from "src/util/convert";
import { Bytes, DATE_FORMAT } from "src/util/format";
@@ -207,6 +208,11 @@ export class SessionDetails extends React.Component {
loading={_.isNil(this.props.session)}
error={this.props.sessionError}
render={this.renderContent}
+ renderError={() =>
+ SQLActivityError({
+ statsType: "sessions",
+ })
+ }
/>
+ SQLActivityError({
+ statsType: "sessions",
+ })
+ }
/>
= props => {
+ return (
+
+ );
+};
+
+export default SQLActivityError;
diff --git a/pkg/ui/workspaces/cluster-ui/src/sqlActivity/sqlActivity.module.scss b/pkg/ui/workspaces/cluster-ui/src/sqlActivity/sqlActivity.module.scss
index 30b9152d3332..3854eff0b538 100644
--- a/pkg/ui/workspaces/cluster-ui/src/sqlActivity/sqlActivity.module.scss
+++ b/pkg/ui/workspaces/cluster-ui/src/sqlActivity/sqlActivity.module.scss
@@ -13,3 +13,8 @@
text-decoration: underline;
}
}
+
+.row {
+ display: flex;
+ flex-direction: row;
+}
diff --git a/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx
index 18ac90562766..56245594c557 100644
--- a/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx
@@ -66,6 +66,7 @@ import { NodeSummaryStats } from "../nodes";
import { UIConfigState } from "../store";
import moment, { Moment } from "moment";
import { StatementsRequest } from "src/api/statementsApi";
+import SQLActivityError from "../sqlActivity/errorComponent";
const { TabPane } = Tabs;
@@ -418,6 +419,11 @@ export class StatementDetails extends React.Component<
loading={_.isNil(this.props.statement)}
error={this.props.statementsError}
render={this.renderContent}
+ renderError={() =>
+ SQLActivityError({
+ statsType: "statements",
+ })
+ }
/>
diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx
index b9be2351ca80..9b0752c40a0a 100644
--- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx
@@ -65,6 +65,7 @@ import { UIConfigState } from "../store";
import { StatementsRequest } from "src/api/statementsApi";
import Long from "long";
import ClearStats from "../sqlActivity/clearStats";
+import SQLActivityError from "../sqlActivity/errorComponent";
import { commonStyles } from "../common";
const cx = classNames.bind(styles);
@@ -578,6 +579,11 @@ export class StatementsPage extends React.Component<
loading={isNil(this.props.statements)}
error={this.props.statementsError}
render={this.renderStatements}
+ renderError={() =>
+ SQLActivityError({
+ statsType: "statements",
+ })
+ }
/>
);
}}
+ renderError={() =>
+ SQLActivityError({
+ statsType: "transactions",
+ })
+ }
/>
);
diff --git a/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx b/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx
index 7c6c7e74c83c..154476b65f54 100644
--- a/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx
+++ b/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx
@@ -59,6 +59,7 @@ import {
StatisticTableColumnKeys,
} from "../statsTableUtil/statsTableUtil";
import ClearStats from "../sqlActivity/clearStats";
+import SQLActivityError from "../sqlActivity/errorComponent";
import { commonStyles } from "../common";
type IStatementsResponse = protos.cockroach.server.serverpb.IStatementsResponse;
@@ -449,6 +450,11 @@ export class TransactionsPage extends React.Component<
>
);
}}
+ renderError={() =>
+ SQLActivityError({
+ statsType: "transactions",
+ })
+ }
/>
);