Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui: add manual refresh option to the Active Executions in SQL Activity #103786

Merged
merged 1 commit into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

export * from "./refreshControl";
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

@import "src/core/index.module";

.refresh-timestamp {
vertical-align: middle;
}

.refresh-icon {
margin-left: 12px;
margin-right: 6px;
vertical-align: middle;
}

.refresh-text {
color: $colors--primary-blue-3;
vertical-align: middle;
margin-right: 12px;
}

.ant-switch-checked {
background-color: $colors--primary-blue-3;
}

.refresh-button {
align-items: center;
}

.refresh-divider {
border-left: 1px solid $colors--neutral-4;
padding-left: 12px;
height: $line-height--large;
display: inline-flex;
align-items: center;
vertical-align: middle;
}

.auto-refresh-label {
padding-right: 8px;
vertical-align: middle;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import { Switch } from "antd";
import "antd/lib/switch/style";
import React from "react";
import classNames from "classnames/bind";
import styles from "./refreshControl.module.scss";
import RefreshIcon from "src/icon/refreshIcon";
import { Timestamp } from "src/timestamp";
import { Moment } from "moment-timezone";
import { DATE_WITH_SECONDS_FORMAT_24_TZ, capitalize } from "src/util";
import { ExecutionType } from "../types";

const cx = classNames.bind(styles);

interface RefreshControlProps {
isAutoRefreshEnabled: boolean;
onToggleAutoRefresh: () => void;
onManualRefresh: () => void;
lastRefreshTimestamp: Moment;
execType: ExecutionType;
}

const REFRESH_BUTTON_COLOR = "#0055FF";

interface RefreshButtonProps {
onManualRefresh: () => void;
}

// RefreshButton consists of the RefreshIcon and the text "Refresh".
const RefreshButton: React.FC<RefreshButtonProps> = ({ onManualRefresh }) => (
<span className={cx("refresh-button")} onClick={onManualRefresh}>
<RefreshIcon color={REFRESH_BUTTON_COLOR} className={cx("refresh-icon")} />
<span className={cx("refresh-text")}>Refresh</span>
</span>
);

export const RefreshControl: React.FC<RefreshControlProps> = ({
isAutoRefreshEnabled,
onToggleAutoRefresh,
onManualRefresh,
lastRefreshTimestamp,
execType,
}) => {
return (
<div>
<span className={cx("refresh-timestamp")}>
<span>Active {capitalize(execType)} Executions As Of: </span>
{lastRefreshTimestamp && lastRefreshTimestamp.isValid() ? (
<Timestamp
time={lastRefreshTimestamp}
format={DATE_WITH_SECONDS_FORMAT_24_TZ}
/>
) : (
"N/A"
)}
</span>
<RefreshButton onManualRefresh={onManualRefresh} />
<span className={cx("refresh-divider")}>
<span className={cx("auto-refresh-label")}>Auto Refresh: </span>
<Switch
className={cx(`ant-switch-${isAutoRefreshEnabled ? "checked" : ""}`)}
checkedChildren={"On"}
unCheckedChildren={"Off"}
checked={isAutoRefreshEnabled}
onClick={onToggleAutoRefresh}
/>
</span>
</div>
);
};

export default RefreshControl;
45 changes: 45 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/icon/refreshIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import * as React from "react";

interface IconProps {
className?: string;
color?: string;
}

const RefreshIcon = ({ className, color }: IconProps) => (
<svg
className={className}
width="18"
height="18"
viewBox="0 0 24 24"
fill={color || "#394455"}
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_11029_22359)">
<path
d="M1.77601 11.9912C1.77601 8.58278 3.43606 5.47461 6.17336 3.58499V7.04636H7.93937V0H0.893012V1.766H5.78484C2.19985 3.92053 0.0100098 7.7351 0.0100098 11.9912C0.0100098 17.5364 3.93054 22.4636 9.33451 23.6821L9.72303 21.9514C5.11376 20.9095 1.77601 16.7064 1.77601 11.9735V11.9912Z"
fill={color || "#394455"}
/>
<path
d="M23.9924 11.9912C23.9924 6.35762 20.1601 1.53642 14.6678 0.300221L14.2793 2.03091C18.8886 3.07285 22.2263 7.27594 22.2263 12.0088C22.2263 15.4172 20.5663 18.5254 17.829 20.415V16.9536H16.063V24H23.1094V22.234H18.2175C21.8025 20.0795 23.9924 16.2649 23.9924 12.0088V11.9912Z"
fill={color || "#394455"}
/>
</g>
<defs>
<clipPath id="clip0_11029_22359">
<rect width="24" height="24" fill="white" />
</clipPath>
</defs>
</svg>
);

export default RefreshIcon;
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ import {
ActiveStatementsViewStateProps,
AppState,
SortSetting,
analyticsActions,
} from "src";
import {
selectActiveStatements,
selectAppName,
selectClusterLocksMaxApiSizeReached,
} from "src/selectors/activeExecutions.selectors";
import { actions as localStorageActions } from "src/store/localStorage";
import {
LocalStorageKeys,
actions as localStorageActions,
} from "src/store/localStorage";
import { actions as sessionsActions } from "src/store/sessions";
import { selectIsTenant } from "src/store/uiConfig";
import { localStorageSelector } from "../store/utils/selectors";
Expand All @@ -33,6 +37,12 @@ export const selectSortSetting = (state: AppState): SortSetting =>
export const selectFilters = (state: AppState): ActiveStatementFilters =>
localStorageSelector(state)["filters/ActiveStatementsPage"];

export const selectIsAutoRefreshEnabled = (state: AppState): boolean => {
return localStorageSelector(state)[
LocalStorageKeys.ACTIVE_EXECUTIONS_IS_AUTOREFRESH_ENABLED
];
};

const selectLocalStorageColumns = (state: AppState) => {
const localStorage = localStorageSelector(state);
return localStorage["showColumns/ActiveStatementsPage"];
Expand All @@ -58,6 +68,8 @@ export const mapStateToActiveStatementsPageProps = (
internalAppNamePrefix: selectAppName(state),
isTenant: selectIsTenant(state),
maxSizeApiReached: selectClusterLocksMaxApiSizeReached(state),
isAutoRefreshEnabled: selectIsAutoRefreshEnabled(state),
lastUpdated: state.adminUI?.sessions.lastUpdated,
});

export const mapDispatchToActiveStatementsPageProps = (
Expand Down Expand Up @@ -86,4 +98,28 @@ export const mapDispatchToActiveStatementsPageProps = (
value: ss,
}),
),
onAutoRefreshToggle: (isEnabled: boolean) => {
dispatch(
localStorageActions.update({
key: LocalStorageKeys.ACTIVE_EXECUTIONS_IS_AUTOREFRESH_ENABLED,
value: isEnabled,
}),
);
dispatch(
analyticsActions.track({
name: "Auto Refresh Toggle",
page: "Statements",
value: isEnabled,
}),
);
},
onManualRefresh: () => {
dispatch(sessionsActions.refresh());
dispatch(
analyticsActions.track({
name: "Manual Refresh",
page: "Statements",
}),
);
},
});
Loading