From 975d4ae91b99767a018faa8485fe682a0521bfe4 Mon Sep 17 00:00:00 2001 From: Nicolas Inchauspe Date: Fri, 24 Feb 2023 12:56:18 +0100 Subject: [PATCH] console: fix operations filters PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8097 GitOrigin-RevId: 33a72186a38094bbcdee85d87d0f0a05aadb1736 --- .../Services/Metrics/Metrics.module.scss | 62 ++++---- .../StatsPanel/Filter/DropdownComponent.js | 99 ------------- .../StatsPanel/Filter/DropdownComponent.tsx | 134 ++++++++++++++++++ .../StatsPanel/Filter/FilterInputComponent.js | 9 +- .../Filter/{Filters.js => Filters.tsx} | 29 ++-- ...GenerateFilters.js => GenerateFilters.tsx} | 98 +++++++------ 6 files changed, 249 insertions(+), 182 deletions(-) delete mode 100644 frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/DropdownComponent.js create mode 100644 frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/DropdownComponent.tsx rename frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/{Filters.js => Filters.tsx} (74%) rename frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/{GenerateFilters.js => GenerateFilters.tsx} (55%) diff --git a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/Metrics.module.scss b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/Metrics.module.scss index 0de8992c6d0..5a7f4f87446 100644 --- a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/Metrics.module.scss +++ b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/Metrics.module.scss @@ -711,50 +711,48 @@ vertical-align: middle; } .selectBox { + background-color: #ffffff; font-family: 'Gudea'; font-size: 15px; font-weight: bold; color: #505050; - padding: 16px 16px; - display: inline-block; + padding: 16px 20px; + display: flex; + flex-direction: row; align-items: center; + gap: 12px; .selectBoxRow { display: inline-block; } span { - min-width: 100px; - padding-right: 12px; + display: block; + flex-shrink: 1; + white-space: nowrap; } } .dropDownBtn { min-width: 180px; - button { - width: 100%; - border-radius: 2px; - border: solid 1px #dddddd; + width: 100%; + border-radius: 2px; + border: solid 1px #dddddd; + background-color: #ffffff; + font-family: 'Gudea'; + font-size: 15px; + font-weight: bold; + color: #505050; + padding: 7px 12px; + min-width: 140px; + display: flex; + align-items: center; + cursor: pointer; + position: relative; + &:focus { + outline: none; + border: solid 1px #f8c533; + } + &:hover { + border: solid 1px #f8c533; background-color: #ffffff; - font-family: 'Gudea'; - font-size: 15px; - font-weight: bold; - color: #505050; - padding: 7px 12px; - min-width: 140px; - display: flex; - align-items: center; - cursor: pointer; - position: relative; - img { - position: absolute; - right: 12px; - } - &:focus { - outline: none; - border: solid 1px #f8c533; - } - &:hover { - border: solid 1px #f8c533; - background-color: #ffffff; - } } span { padding-right: 0; @@ -787,6 +785,8 @@ /* common checkbox */ .commonCheckBox, .defaultCheckBox { + min-width: 110px; + input[type='checkbox'] { position: absolute; // take it out of document flow opacity: 0; // hide it @@ -836,7 +836,7 @@ content: ''; position: absolute; left: 7px; - top: 3px; + top: 5px; width: 5px; height: 10px; border: solid white; diff --git a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/DropdownComponent.js b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/DropdownComponent.js deleted file mode 100644 index a55c2a1b3ed..00000000000 --- a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/DropdownComponent.js +++ /dev/null @@ -1,99 +0,0 @@ -import React, { useState } from 'react'; -import Dropdown from 'react-bootstrap/lib/Dropdown'; -import MenuItem from 'react-bootstrap/lib/MenuItem'; - -import { SELECT_ALL_NAME_DISPLAY } from '../../constants'; -import styles from '../../Metrics.module.scss'; - -import dropdown from '../../images/drop-down.svg'; - -const DropdownComponent = props => { - /* Accepts children which can be a single Menu Items - * or array of Menu Items - * TODO: How to validate whether the childrens are only of Menu item type? - * */ - const [show, setShow] = useState(false); - const { - id, - displayValue, - options, - onChange, - selectedValues, - children, - selectAll, - } = props; - const selectedValuesList = - Object.keys(selectedValues).length === options.length - 1 - ? Object.assign({ ...selectedValues }, { 'Select All': true }) - : selectedValues; - const handleToggle = (isOpen, event, metadata) => { - if (isOpen || metadata.source !== 'select') { - setShow(isOpen); - } - }; - const handleChange = val => { - if ( - val === SELECT_ALL_NAME_DISPLAY && - Object.keys(selectedValuesList).length === options.length - ) { - selectAll(id, options, true); - } else if (val === SELECT_ALL_NAME_DISPLAY) { - selectAll(id, options); - } else { - onChange(val); - } - }; - - const renderTitle = title => { - if ( - title === 'Select All' && - Object.keys(selectedValuesList).length === options.length - ) { - return 'Unselect All'; - } - return title; - }; - - return ( - { - handleChange(e); - }} - className={styles.dropDownBtn} - > - - {displayValue} - {'Dropdown - - - {options.map((list, index) => { - return ( - -
- null} - checked={selectedValuesList[list.title] ? true : false} - /> - -
-
- ); - })} - {children} -
-
- ); -}; -export default DropdownComponent; diff --git a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/DropdownComponent.tsx b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/DropdownComponent.tsx new file mode 100644 index 00000000000..002355806a3 --- /dev/null +++ b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/DropdownComponent.tsx @@ -0,0 +1,134 @@ +import React, { useState, useEffect } from 'react'; +import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; +import clsx from 'clsx'; +import { FaChevronDown } from 'react-icons/fa'; + +import { SELECT_ALL_NAME_DISPLAY } from '../../constants'; +import styles from '../../Metrics.module.scss'; +import { v4 as uuid } from 'uuid'; + +const DropdownComponent = (props: any) => { + /* Accepts children which can be a single Menu Items + * or array of Menu Items + * TODO: How to validate whether the childrens are only of Menu item type? + * */ + const [componentId] = useState(uuid()); + const [show, setShow] = useState(false); + const { + id, + displayValue, + options, + onChange, + selectedValues, + children, + selectAll, + } = props; + const selectedValuesList = + Object.keys(selectedValues).length === options.length - 1 + ? Object.assign({ ...selectedValues }, { 'Select All': true }) + : selectedValues; + + // Force dropdown content to be same width as trigger + useEffect(() => { + const component = document.getElementById(componentId); + document.documentElement.style.setProperty( + `--radix-dropdown-menu-trigger-width-${componentId}`, + component?.offsetWidth + 'px' + ); + }, [displayValue, componentId]); + + const handleToggle = (open: boolean) => { + setShow(open); + }; + + const handleChange = (val: string) => { + if ( + val === SELECT_ALL_NAME_DISPLAY && + Object.keys(selectedValuesList).length === options.length + ) { + selectAll(id, options, true); + } else if (val === SELECT_ALL_NAME_DISPLAY) { + selectAll(id, options); + } else { + onChange(val); + } + }; + + const renderTitle = (title: string) => { + if ( + title === 'Select All' && + Object.keys(selectedValuesList).length === options.length + ) { + return 'Unselect All'; + } + return title; + }; + + return ( + + +
0 ? '' : 'text-gray-500' + } + > + {displayValue} +
+ +
+ + + {options.map((list: any, index: string) => { + return ( + handleChange(list.title as string)} + > +
+ {}} + checked={selectedValuesList[list?.title || ''] ? true : false} + /> + +
+
+ ); + })} + {children ? ( +
+ {children} +
+ ) : null} +
+
+ ); +}; +export default DropdownComponent; diff --git a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/FilterInputComponent.js b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/FilterInputComponent.js index 257225032e4..e317ad9a1fd 100644 --- a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/FilterInputComponent.js +++ b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/FilterInputComponent.js @@ -1,4 +1,5 @@ import React, { useState } from 'react'; +import clsx from 'clsx'; /* calls the onChange configured when enter is pressed * and clears the current input @@ -19,10 +20,14 @@ const FilterInputComponent = props => { } }; return ( -
+
{filterTitle} { +}: any) => { const [displayFilters, setFiltersDisplay] = useState(false); const renderSelectedFiltersCount = () => { return values.length > 0 ? `(${values.length})` : ''; @@ -28,7 +30,7 @@ const Filters = ({ if (values.length > 0) { return ( ); } @@ -36,8 +38,8 @@ const Filters = ({ }; const renderSelectedFilters = () => { if (values.length > 0) { - return values.map((f, i) => { - const composeFilterObj = o => { + return values.map((f: { value: any; type: any }, i: any) => { + const composeFilterObj = (o: { [x: string]: any }) => { const keyElements = Object.keys(o); if (keyElements.length > 0) { return keyElements.map(k => `${k}: ${o[k]}`).join(', '); @@ -53,7 +55,7 @@ const Filters = ({ return ( onChange(f.type, f.value)} /> ); @@ -69,8 +71,19 @@ const Filters = ({ return (
-
-
+
+ +
Filter -
+
Filters {renderSelectedFiltersCount()}
diff --git a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/GenerateFilters.js b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/GenerateFilters.tsx similarity index 55% rename from frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/GenerateFilters.js rename to frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/GenerateFilters.tsx index 64e8e50aa99..e6c9b9b646a 100644 --- a/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/GenerateFilters.js +++ b/frontend/libs/console/legacy-ee/src/lib/components/Services/Metrics/StatsPanel/Filter/GenerateFilters.tsx @@ -14,6 +14,7 @@ import FilterTypeInput from './FilterTypeInput'; import TimeRangeFilter from './TimeRangeFilter'; import FilterTypeCheckbox from './FilterTypeCheckbox'; import ComposeDropdownFilter from './ComposeDropdownFilter'; +import { DocumentNode } from 'graphql'; /* * Dropdown filters are not rendered. The pattern ensures that data for @@ -40,7 +41,7 @@ const GenerateFilters = ({ filters, values, selectAll, -}) => { +}: any) => { const filtersHtml = []; const [dropdownFilters, nonDropdownFilters] = splitByType( filters, @@ -50,47 +51,49 @@ const GenerateFilters = ({ return null; } const hOrderFn = compose(onChange); - nonDropdownFilters.forEach((filter, i) => { - const { type, value } = filter; - const onFilterChange = hOrderFn(value); - switch (type) { - case FILTER_TYPE_INPUT: - filtersHtml.push( - - ); - break; - case FILTER_TYPE_DROPDOWN_DEFAULT: - filtersHtml.push( - - ); - break; - case FILTER_TYPE_CHECKBOX: - filtersHtml.push( - - ); - break; - default: - console.error('Unsupported type'); + nonDropdownFilters.forEach( + (filter: { type: any; value: any }, i: React.Key | null | undefined) => { + const { type, value } = filter; + const onFilterChange = hOrderFn(value); + switch (type) { + case FILTER_TYPE_INPUT: + filtersHtml.push( + + ); + break; + case FILTER_TYPE_DROPDOWN_DEFAULT: + filtersHtml.push( + + ); + break; + case FILTER_TYPE_CHECKBOX: + filtersHtml.push( + + ); + break; + default: + console.error('Unsupported type'); + } } - }); + ); if (dropdownFilters.length > 0) { filtersHtml.push( @@ -109,7 +112,18 @@ const GenerateFilters = ({ ); } - return filtersHtml; + return ( +
+ {filtersHtml} +
+ ); }; export default GenerateFilters;