diff --git a/pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.module.scss b/pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.module.scss index 783f972f1d5d..7fb0090321d3 100644 --- a/pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.module.scss +++ b/pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.module.scss @@ -127,3 +127,29 @@ $dropdown-hover-color: darken($colors--background, 2.5%); .hide { display: none; } + +.badges-area { + display: flex; + margin-bottom: 5px; +} + +.badge-wrapper { + background-color: $colors--neutral-2; + border-radius: 3px; + color: $colors--neutral-7; + display: flex; + font-family: $font-family--semi-bold; + font-size: $font-size--small; + line-height: $line-height--small; + margin-bottom: 5px; + margin-right: 5px; + padding: 3px 7px; + width: fit-content; +} + +.close-area { + margin-top: 4px; + margin-left: 5px; + width: 12px; + cursor: pointer; +} diff --git a/pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.tsx b/pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.tsx index 985e5fc3b62f..698410d260d3 100644 --- a/pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.tsx @@ -11,7 +11,7 @@ import React from "react"; import Select from "react-select"; import { Button } from "../button"; -import { CaretDown } from "@cockroachlabs/icons"; +import { CaretDown, Cancel } from "@cockroachlabs/icons"; import { Input } from "antd"; import "antd/lib/input/style"; import { History } from "history"; @@ -26,6 +26,7 @@ import { hidden, caretDown, checkbox, + badge, } from "./filterClasses"; import { MultiSelectCheckbox } from "../multiSelectCheckbox/multiSelectCheckbox"; import { syncHistory } from "../util"; @@ -246,7 +247,7 @@ export const updateFiltersQueryParamsOnTab = ( }; /** - * The State of the filter that is consider inactive. + * The State of the filter that is considered inactive. * It's different from defaultFilters because we don't want to take * timeUnit into consideration. * For example, if the timeUnit changes, but the timeValue is still 0, @@ -264,6 +265,7 @@ export const inactiveFiltersState: Required> = { workloadInsightType: "", schemaInsightType: "", executionStatus: "", + username: "", }; export const calculateActiveFilters = (filters: Filters): number => { @@ -462,7 +464,7 @@ export class Filter extends React.Component { }); const appFilter = (
-
Application Name
+
{getLabelFromKey("app")}
{ }); const dbFilter = (
-
Database
+
{getLabelFromKey("database")}
{ }); const usernameFilter = (
-
User Name
+
{getLabelFromKey("username")}
{ }); const sessionStatusFilter = (
-
Session Status
+
+ {getLabelFromKey("sessionStatus")} +
{ ); const executionStatusFilter = (
-
Execution Status
+
+ {getLabelFromKey("executionStatus")} +
{ }); const schemaInsightTypeFilter = (
-
Schema Insight Type
+
+ {getLabelFromKey("schemaInsightType")} +
{ ); const workloadInsightTypeFilter = (
-
Workload Insight Type
+
+ {getLabelFromKey("workloadInsightType")} +
{ ); const regionsFilter = (
-
Region
+
{getLabelFromKey("regions")}
{ }); const nodesFilter = (
-
Node
+
{getLabelFromKey("nodes")}
{ }); const sqlTypeFilter = (
-
Statement Type
+
{getLabelFromKey("sqlType")}
{ ); } } + +interface SelectedFilterProps { + filters: Filters; + onRemoveFilter: (filters: Filters) => void; +} +export function SelectedFilters( + props: SelectedFilterProps, +): React.ReactElement { + const { filters, onRemoveFilter } = props; + const badges = Object.keys(filters).map(filter => { + if ( + filters[filter] != null && + filters[filter] !== inactiveFiltersState[filter] && + filter !== "timeUnit" + ) { + return ( + + ); + } + return null; + }); + + return
{badges}
; +} + +function removeFilter( + filters: Filters, + filter: string, + onRemoveFilter: (filters: Filters) => void, +): void { + filters[filter] = inactiveFiltersState[filter]; + onRemoveFilter(filters); +} +interface FilterBadgeProps { + filters: Filters; + name: string; + values: string | boolean; + unit: string; + onRemoveFilter: (filters: Filters) => void; +} +function FilterBadge(props: FilterBadgeProps): React.ReactElement { + const { filters, name, values, onRemoveFilter } = props; + const unit = name === "timeNumber" ? props.unit : ""; + let value = `${getLabelFromKey(name)}: ${values.toString()} ${unit}`; + if (value.length > 100) { + value = value.substring(0, 100) + "..."; + } + return ( +
+ {value} + removeFilter(filters, name, onRemoveFilter)} + /> +
+ ); +} + +function getLabelFromKey(key: string): string { + switch (key) { + case "app": + return "Application Name"; + case "database": + return "Database"; + case "executionStatus": + return "Execution Status"; + case "fullScan": + return "Full Scan"; + case "nodes": + return "Node"; + case "regions": + return "Region"; + case "schemaInsightType": + return "Schema Insight Type"; + case "sessionStatus": + return "Session Status"; + case "sqlType": + return "Statement Type"; + case "timeNumber": + return "Runs Longer Than"; + case "username": + return "User Name"; + case "workloadInsightType": + return "Workload Insight Type"; + default: + return key; + } +} diff --git a/pkg/ui/workspaces/cluster-ui/src/queryFilter/filterClasses.ts b/pkg/ui/workspaces/cluster-ui/src/queryFilter/filterClasses.ts index d329d106a7a6..a0ea0d441264 100644 --- a/pkg/ui/workspaces/cluster-ui/src/queryFilter/filterClasses.ts +++ b/pkg/ui/workspaces/cluster-ui/src/queryFilter/filterClasses.ts @@ -39,3 +39,9 @@ export const applyBtn = { wrapper: cx("apply-btn__wrapper"), btn: cx("apply-btn__btn"), }; + +export const badge = { + area: cx("badges-area"), + wrapper: cx("badge-wrapper"), + closeArea: cx("close-area"), +}; diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx index eeb7484fd62b..4ca29ae304f1 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx @@ -29,6 +29,7 @@ import { Filter, Filters, handleFiltersFromQueryString, + SelectedFilters, updateFiltersQueryParamsOnTab, } from "../queryFilter"; @@ -525,6 +526,10 @@ export class StatementsPage extends React.Component< onClearFilters={this.onClearFilters} />
+