diff --git a/packages/manager/.changeset/pr-11118-upcoming-features-1729486113842.md b/packages/manager/.changeset/pr-11118-upcoming-features-1729486113842.md new file mode 100644 index 00000000000..dba2806a662 --- /dev/null +++ b/packages/manager/.changeset/pr-11118-upcoming-features-1729486113842.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Add title / label for all global filters in ACLP ([#11118](https://github.com/linode/manager/pull/11118)) diff --git a/packages/manager/cypress/e2e/core/cloudpulse/dbaas-widgets-verification.spec.ts b/packages/manager/cypress/e2e/core/cloudpulse/dbaas-widgets-verification.spec.ts index b5b479ced6d..d1f1181337d 100644 --- a/packages/manager/cypress/e2e/core/cloudpulse/dbaas-widgets-verification.spec.ts +++ b/packages/manager/cypress/e2e/core/cloudpulse/dbaas-widgets-verification.spec.ts @@ -167,21 +167,21 @@ describe('Integration Tests for DBaaS Dashboard ', () => { // Selecting a dashboard from the autocomplete input. ui.autocomplete - .findByLabel('Select a Dashboard') + .findByLabel('Dashboard') .should('be.visible') .type(`${dashboardName}{enter}`) .should('be.visible'); // Select a time duration from the autocomplete input. ui.autocomplete - .findByLabel('Select a Time Duration') + .findByLabel('Time Range') .should('be.visible') .type(`${timeDurationToSelect}{enter}`) .should('be.visible'); //Select a Engine from the autocomplete input. ui.autocomplete - .findByLabel('Select an Engine') + .findByLabel('Database Engine') .should('be.visible') .type(`${engine}{enter}`) .should('be.visible'); @@ -191,7 +191,7 @@ describe('Integration Tests for DBaaS Dashboard ', () => { // Select a resource from the autocomplete input. ui.autocomplete - .findByLabel('Select a Resource') + .findByLabel('Database Clusters') .should('be.visible') .type(`${clusterName}{enter}`) .click(); @@ -199,7 +199,7 @@ describe('Integration Tests for DBaaS Dashboard ', () => { //Select a Node from the autocomplete input. ui.autocomplete - .findByLabel('Select a Node Type') + .findByLabel('Node Type') .should('be.visible') .type(`${nodeType}{enter}`); diff --git a/packages/manager/cypress/e2e/core/cloudpulse/linode-widget-verification.spec.ts b/packages/manager/cypress/e2e/core/cloudpulse/linode-widget-verification.spec.ts index dd95d49c7f2..11106e45858 100644 --- a/packages/manager/cypress/e2e/core/cloudpulse/linode-widget-verification.spec.ts +++ b/packages/manager/cypress/e2e/core/cloudpulse/linode-widget-verification.spec.ts @@ -139,14 +139,14 @@ describe('Integration Tests for Linode Dashboard ', () => { // Selecting a dashboard from the autocomplete input. ui.autocomplete - .findByLabel('Select a Dashboard') + .findByLabel('Dashboard') .should('be.visible') .type(`${dashboardName}{enter}`) .should('be.visible'); // Select a time duration from the autocomplete input. ui.autocomplete - .findByLabel('Select a Time Duration') + .findByLabel('Time Range') .should('be.visible') .type(`${timeDurationToSelect}{enter}`) .should('be.visible'); @@ -156,7 +156,7 @@ describe('Integration Tests for Linode Dashboard ', () => { // Select a resource from the autocomplete input. ui.autocomplete - .findByLabel('Select a Resource') + .findByLabel('Resources') .should('be.visible') .type(`${resource}{enter}`) .click(); diff --git a/packages/manager/cypress/support/util/cloudpulse.ts b/packages/manager/cypress/support/util/cloudpulse.ts index 78c36f4b8d4..a760bc84f39 100644 --- a/packages/manager/cypress/support/util/cloudpulse.ts +++ b/packages/manager/cypress/support/util/cloudpulse.ts @@ -1,13 +1,10 @@ // Function to generate random values based on the number of points import type { CloudPulseMetricsResponseData } from '@linode/api-v4'; +import type { Labels } from 'src/features/CloudPulse/shared/CloudPulseTimeRangeSelect'; + export const generateRandomMetricsData = ( - time: - | 'Last 7 Days' - | 'Last 12 Hours' - | 'Last 24 Hours' - | 'Last 30 Days' - | 'Last 30 Minutes', + time: Labels, granularityData: '1 day' | '1 hr' | '5 min' | 'Auto' ): CloudPulseMetricsResponseData => { const currentTime = Math.floor(Date.now() / 1000); diff --git a/packages/manager/src/components/Autocomplete/Autocomplete.styles.tsx b/packages/manager/src/components/Autocomplete/Autocomplete.styles.tsx index 9f31b39af99..5e4c9989e51 100644 --- a/packages/manager/src/components/Autocomplete/Autocomplete.styles.tsx +++ b/packages/manager/src/components/Autocomplete/Autocomplete.styles.tsx @@ -44,7 +44,7 @@ export const SelectedIcon = styled(DoneIcon, { })); export const CustomPopper = (props: PopperProps) => { - const { style, ...rest } = props; + const { placement, style, ...rest } = props; const updatedStyle = { ...style, @@ -58,9 +58,13 @@ export const CustomPopper = (props: PopperProps) => { return ( ); diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.tsx b/packages/manager/src/components/RegionSelect/RegionSelect.tsx index 5d67de51d21..1a107f1aa3f 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.tsx +++ b/packages/manager/src/components/RegionSelect/RegionSelect.tsx @@ -51,6 +51,7 @@ export const RegionSelect = < helperText, ignoreAccountAvailability, label, + noMarginTop, onChange, placeholder, regionFilter, @@ -172,6 +173,7 @@ export const RegionSelect = < label={label ?? 'Region'} loading={accountAvailabilityLoading} loadingText="Loading regions..." + noMarginTop={noMarginTop} noOptionsText="No results" onChange={onChange} options={regionOptions} diff --git a/packages/manager/src/features/CloudPulse/Overview/GlobalFilters.test.tsx b/packages/manager/src/features/CloudPulse/Overview/GlobalFilters.test.tsx index bdb9bc34884..286c95377e1 100644 --- a/packages/manager/src/features/CloudPulse/Overview/GlobalFilters.test.tsx +++ b/packages/manager/src/features/CloudPulse/Overview/GlobalFilters.test.tsx @@ -35,7 +35,7 @@ describe('Global filters component test', () => { expect(timeRangeSelect).toBeInTheDocument(); expect( - screen.getByRole('combobox', { name: 'Select a Time Duration' }) + screen.getByRole('combobox', { name: 'Time Range' }) ).toHaveAttribute('value', 'Last 30 Minutes'); }); }); diff --git a/packages/manager/src/features/CloudPulse/Overview/GlobalFilters.tsx b/packages/manager/src/features/CloudPulse/Overview/GlobalFilters.tsx index 320e8e1280d..5da22919834 100644 --- a/packages/manager/src/features/CloudPulse/Overview/GlobalFilters.tsx +++ b/packages/manager/src/features/CloudPulse/Overview/GlobalFilters.tsx @@ -107,13 +107,14 @@ export const GlobalFilters = React.memo((props: GlobalFilterProperties) => { defaultValue={preferences?.timeDuration} handleStatsChange={handleTimeRangeChange} hideLabel - label="Select Time Range" + label="Time Range" savePreferences /> { expect(regionConfig).toBeDefined(); if (regionConfig) { - const result = getRegionProperties( + const { + handleRegionChange, + label, + selectedDashboard, + } = getRegionProperties( { config: regionConfig, dashboard: mockDashboard, @@ -39,20 +43,26 @@ it('test getRegionProperties method', () => { }, vi.fn() ); - expect(result['handleRegionChange']).toBeDefined(); - expect(result['selectedDashboard']).toEqual(mockDashboard); + const { name } = regionConfig.configuration; + expect(handleRegionChange).toBeDefined(); + expect(selectedDashboard).toEqual(mockDashboard); + expect(label).toEqual(name); } }); it('test getTimeDuratonProperties method', () => { const timeDurationConfig = linodeConfig?.filters.find( - (filterObj) => filterObj.name === 'Time Duration' + ({ name }) => name === 'Time Range' ); expect(timeDurationConfig).toBeDefined(); if (timeDurationConfig) { - const result = getTimeDurationProperties( + const { + handleStatsChange, + label, + savePreferences, + } = getTimeDurationProperties( { config: timeDurationConfig, dashboard: mockDashboard, @@ -60,8 +70,10 @@ it('test getTimeDuratonProperties method', () => { }, vi.fn() ); - expect(result['handleStatsChange']).toBeDefined(); - expect(result['savePreferences']).toEqual(true); + const { name } = timeDurationConfig.configuration; + expect(handleStatsChange).toBeDefined(); + expect(savePreferences).toEqual(true); + expect(label).toEqual(name); } }); @@ -73,7 +85,13 @@ it('test getResourceSelectionProperties method', () => { expect(resourceSelectionConfig).toBeDefined(); if (resourceSelectionConfig) { - const result = getResourcesProperties( + const { + disabled, + handleResourcesSelection, + label, + savePreferences, + xFilter, + } = getResourcesProperties( { config: resourceSelectionConfig, dashboard: mockDashboard, @@ -82,12 +100,12 @@ it('test getResourceSelectionProperties method', () => { }, vi.fn() ); - expect(result['handleResourcesSelection']).toBeDefined(); - expect(result['savePreferences']).toEqual(false); - expect(result['disabled']).toEqual(false); - expect(JSON.stringify(result['xFilter'])).toEqual( - '{"+and":[{"region":"us-east"}]}' - ); + const { name } = resourceSelectionConfig.configuration; + expect(handleResourcesSelection).toBeDefined(); + expect(savePreferences).toEqual(false); + expect(disabled).toEqual(false); + expect(JSON.stringify(xFilter)).toEqual('{"+and":[{"region":"us-east"}]}'); + expect(label).toEqual(name); } }); @@ -99,7 +117,13 @@ it('test getResourceSelectionProperties method with disabled true', () => { expect(resourceSelectionConfig).toBeDefined(); if (resourceSelectionConfig) { - const result = getResourcesProperties( + const { + disabled, + handleResourcesSelection, + label, + savePreferences, + xFilter, + } = getResourcesProperties( { config: resourceSelectionConfig, dashboard: mockDashboard, @@ -108,10 +132,12 @@ it('test getResourceSelectionProperties method with disabled true', () => { }, vi.fn() ); - expect(result['handleResourcesSelection']).toBeDefined(); - expect(result['savePreferences']).toEqual(false); - expect(result['disabled']).toEqual(true); - expect(JSON.stringify(result['xFilter'])).toEqual('{"+and":[]}'); + const { name } = resourceSelectionConfig.configuration; + expect(handleResourcesSelection).toBeDefined(); + expect(savePreferences).toEqual(false); + expect(disabled).toEqual(true); + expect(JSON.stringify(xFilter)).toEqual('{"+and":[]}'); + expect(label).toEqual(name); } }); @@ -201,7 +227,14 @@ it('test getCustomSelectProperties method', () => { expect(customSelectEngineConfig).toBeDefined(); if (customSelectEngineConfig) { - let result = getCustomSelectProperties( + const { + clearDependentSelections, + disabled, + isMultiSelect, + label, + options, + savePreferences, + } = getCustomSelectProperties( { config: customSelectEngineConfig, dashboard: { ...mockDashboard, service_type: 'dbaas' }, @@ -210,13 +243,14 @@ it('test getCustomSelectProperties method', () => { vi.fn() ); - expect(result.options).toBeDefined(); - expect(result.options?.length).toEqual(2); - expect(result.savePreferences).toEqual(false); - expect(result.isMultiSelect).toEqual(false); - expect(result.disabled).toEqual(false); - expect(result.clearDependentSelections).toBeDefined(); - expect(result.clearDependentSelections?.includes(RESOURCES)).toBe(true); + expect(options).toBeDefined(); + expect(options?.length).toEqual(2); + expect(savePreferences).toEqual(false); + expect(isMultiSelect).toEqual(false); + expect(label).toEqual(customSelectEngineConfig.configuration.name); + expect(disabled).toEqual(false); + expect(clearDependentSelections).toBeDefined(); + expect(clearDependentSelections?.includes(RESOURCES)).toBe(true); customSelectEngineConfig.configuration.type = CloudPulseSelectTypes.dynamic; customSelectEngineConfig.configuration.apiV4QueryKey = @@ -224,7 +258,12 @@ it('test getCustomSelectProperties method', () => { customSelectEngineConfig.configuration.isMultiSelect = true; customSelectEngineConfig.configuration.options = undefined; - result = getCustomSelectProperties( + const { + apiV4QueryKey, + isMultiSelect: isMultiSelectApi, + savePreferences: savePreferencesApi, + type, + } = getCustomSelectProperties( { config: customSelectEngineConfig, dashboard: mockDashboard, @@ -233,10 +272,13 @@ it('test getCustomSelectProperties method', () => { vi.fn() ); - expect(result.apiV4QueryKey).toEqual(databaseQueries.engines); - expect(result.type).toEqual(CloudPulseSelectTypes.dynamic); - expect(result.savePreferences).toEqual(false); - expect(result.isMultiSelect).toEqual(true); + const { name } = customSelectEngineConfig.configuration; + + expect(apiV4QueryKey).toEqual(databaseQueries.engines); + expect(type).toEqual(CloudPulseSelectTypes.dynamic); + expect(savePreferencesApi).toEqual(false); + expect(isMultiSelectApi).toEqual(true); + expect(label).toEqual(name); } }); diff --git a/packages/manager/src/features/CloudPulse/Utils/FilterBuilder.ts b/packages/manager/src/features/CloudPulse/Utils/FilterBuilder.ts index dc9ec47fe01..e058b2e3d03 100644 --- a/packages/manager/src/features/CloudPulse/Utils/FilterBuilder.ts +++ b/packages/manager/src/features/CloudPulse/Utils/FilterBuilder.ts @@ -56,11 +56,12 @@ export const getRegionProperties = ( props: CloudPulseFilterProperties, handleRegionChange: (region: string | undefined, savePref?: boolean) => void ): CloudPulseRegionSelectProps => { - const { placeholder } = props.config.configuration; + const { name: label, placeholder } = props.config.configuration; const { dashboard, isServiceAnalyticsIntegration, preferences } = props; return { defaultValue: preferences?.[REGION], handleRegionChange, + label, placeholder, savePreferences: !isServiceAnalyticsIntegration, selectedDashboard: dashboard, @@ -84,7 +85,7 @@ export const getResourcesProperties = ( savePref?: boolean ) => void ): CloudPulseResourcesSelectProps => { - const { filterKey, placeholder } = props.config.configuration; + const { filterKey, name: label, placeholder } = props.config.configuration; const { config, dashboard, @@ -100,6 +101,7 @@ export const getResourcesProperties = ( dashboard ), handleResourcesSelection: handleResourceChange, + label, placeholder, resourceType: dashboard.service_type, savePreferences: !isServiceAnalyticsIntegration, @@ -129,6 +131,7 @@ export const getCustomSelectProperties = ( filterType, isMultiSelect, maxSelections, + name: label, options, placeholder, } = props.config.configuration; @@ -156,6 +159,7 @@ export const getCustomSelectProperties = ( filterType, handleSelectionChange: handleCustomSelectChange, isMultiSelect, + label, maxSelections, options, placeholder, @@ -183,13 +187,14 @@ export const getTimeDurationProperties = ( savePref?: boolean ) => void ): CloudPulseTimeRangeSelectProps => { - const { placeholder } = props.config.configuration; + const { name: label, placeholder } = props.config.configuration; const { isServiceAnalyticsIntegration, preferences } = props; const timeDuration = preferences?.timeDuration; return { defaultValue: timeDuration, handleStatsChange: handleTimeRangeChange, + label, placeholder, savePreferences: !isServiceAnalyticsIntegration, }; diff --git a/packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts b/packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts index 9034ab46ca8..55c96678749 100644 --- a/packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts +++ b/packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts @@ -2,7 +2,7 @@ import { CloudPulseSelectTypes } from './models'; import type { CloudPulseServiceTypeFilterMap } from './models'; -const TIME_DURATION = 'Time Duration'; +const TIME_DURATION = 'Time Range'; export const LINODE_CONFIG: Readonly = { filters: [ @@ -26,9 +26,9 @@ export const LINODE_CONFIG: Readonly = { isFilterable: true, isMetricsFilter: true, isMultiSelect: true, - name: 'Resource', + name: 'Resources', neededInServicePage: false, - placeholder: 'Select a Resource', + placeholder: 'Select Resources', priority: 2, }, name: 'Resources', @@ -60,7 +60,7 @@ export const DBAAS_CONFIG: Readonly = { isFilterable: false, // isFilterable -- this determines whethere you need to pass it metrics api isMetricsFilter: false, // if it is false, it will go as a part of filter params, else global filter isMultiSelect: false, - name: 'DB Engine', + name: 'Database Engine', neededInServicePage: false, options: [ { @@ -72,7 +72,7 @@ export const DBAAS_CONFIG: Readonly = { label: 'PostgreSQL', }, ], - placeholder: 'Select an Engine', + placeholder: 'Select a Database Engine', priority: 2, type: CloudPulseSelectTypes.static, }, @@ -98,9 +98,9 @@ export const DBAAS_CONFIG: Readonly = { isFilterable: true, isMetricsFilter: true, isMultiSelect: true, - name: 'Resource', + name: 'Database Clusters', neededInServicePage: false, - placeholder: 'Select a DB Cluster', + placeholder: 'Select Database Clusters', priority: 3, }, name: 'Resources', diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseComponentRenderer.test.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseComponentRenderer.test.tsx index 1b907419a46..dd74c70a1ef 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseComponentRenderer.test.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseComponentRenderer.test.tsx @@ -81,6 +81,6 @@ describe('ComponentRenderer component tests', () => { })} ); - expect(getByPlaceholderText('Select a Resource')).toBeDefined(); + expect(getByPlaceholderText('Select Resources')).toBeDefined(); }); }); diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseCustomSelect.test.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseCustomSelect.test.tsx index 78ae7c77efe..59f92338cf9 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseCustomSelect.test.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseCustomSelect.test.tsx @@ -56,12 +56,14 @@ describe('CloudPulseCustomSelect component tests', () => { filterKey="testfilter" filterType="number" handleSelectionChange={vi.fn()} + label="Test" options={mockOptions} placeholder={testFilter} type={CloudPulseSelectTypes.static} /> ); expect(screen.queryByPlaceholderText(testFilter)).toBeNull(); + expect(screen.getByLabelText('Test')).toBeInTheDocument(); const keyDown = screen.getByTestId(keyboardArrowDownIcon); fireEvent.click(keyDown); fireEvent.click(screen.getByText('Test1')); @@ -76,12 +78,14 @@ describe('CloudPulseCustomSelect component tests', () => { filterType="number" handleSelectionChange={vi.fn()} isMultiSelect={true} + label="CustomTest" options={[...mockOptions]} placeholder={testFilter} type={CloudPulseSelectTypes.static} /> ); expect(screen.queryByPlaceholderText(testFilter)).toBeNull(); + expect(screen.getByLabelText('CustomTest')).toBeInTheDocument(); const keyDown = screen.getByTestId(keyboardArrowDownIcon); fireEvent.click(keyDown); expect(screen.getAllByText('Test1').length).toEqual(2); // here it should be 2 @@ -105,11 +109,13 @@ describe('CloudPulseCustomSelect component tests', () => { filterKey="testfilter" filterType="number" handleSelectionChange={selectionChnage} + label="Test" placeholder={testFilter} type={CloudPulseSelectTypes.dynamic} /> ); expect(screen.queryByPlaceholderText(testFilter)).toBeNull(); + expect(screen.getByLabelText('Test')).toBeInTheDocument(); const keyDown = screen.getByTestId(keyboardArrowDownIcon); fireEvent.click(keyDown); fireEvent.click(screen.getByText('Test1')); @@ -131,11 +137,13 @@ describe('CloudPulseCustomSelect component tests', () => { filterType="number" handleSelectionChange={selectionChnage} isMultiSelect={true} + label="Test" placeholder={testFilter} type={CloudPulseSelectTypes.dynamic} /> ); expect(screen.queryByPlaceholderText(testFilter)).toBeNull(); + expect(screen.getByLabelText('Test')).toBeInTheDocument(); const keyDown = screen.getByTestId(keyboardArrowDownIcon); fireEvent.click(keyDown); expect(screen.getAllByText('Test1').length).toEqual(2); // here it should be 2 diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseCustomSelect.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseCustomSelect.tsx index 4d25327a3ea..95c413c4adc 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseCustomSelect.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseCustomSelect.tsx @@ -81,6 +81,8 @@ export interface CloudPulseCustomSelectProps { */ isMultiSelect?: boolean; + label: string; + /** * The maximum selections that the user can make incase of multiselect */ @@ -126,6 +128,7 @@ export const CloudPulseCustomSelect = React.memo( filterKey, handleSelectionChange, isMultiSelect, + label, maxSelections, options, placeholder, @@ -227,15 +230,18 @@ export const CloudPulseCustomSelect = React.memo( ? '' : placeholder || 'Select a Value' } - textFieldProps={{ - hideLabel: true, + slotProps={{ + popper: { + placement: 'bottom', + }, }} autoHighlight disabled={isAutoCompleteDisabled} errorText={staticErrorText} isOptionEqualToValue={(option, value) => option.label === value.label} - label={placeholder || 'Select a Value'} + label={label || 'Select a Value'} multiple={isMultiSelect} + noMarginTop onChange={handleChange} value={selectedResource ?? (isMultiSelect ? [] : null)} /> diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.test.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.test.tsx index 006dc05afb6..ec2c10bacc5 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.test.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.test.tsx @@ -32,7 +32,7 @@ describe('CloudPulseDashboardFilterBuilder component tests', () => { /> ); - expect(getByPlaceholderText('Select an Engine')).toBeDefined(); + expect(getByPlaceholderText('Select a Database Engine')).toBeDefined(); expect(getByPlaceholderText('Select a Region')).toBeDefined(); }); }); diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx index 73bb56016ad..4444f942a57 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx @@ -292,10 +292,11 @@ export const CloudPulseDashboardFilterBuilder = React.memo( } sx={{ justifyContent: 'start', - m: 0, + m: theme.spacing(0), + marginBottom: theme.spacing(showFilter ? 1 : 0), minHeight: 'auto', minWidth: 'auto', - p: 0, + p: theme.spacing(0), svg: { color: theme.color.grey4, }, @@ -306,13 +307,13 @@ export const CloudPulseDashboardFilterBuilder = React.memo( diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardSelect.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardSelect.tsx index 81526099c4d..19828bc4328 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardSelect.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardSelect.tsx @@ -102,9 +102,6 @@ export const CloudPulseDashboardSelect = React.memo( {params.children} )} - textFieldProps={{ - hideLabel: true, - }} autoHighlight clearOnBlur data-testid="cloudpulse-dashboard-select" @@ -113,8 +110,9 @@ export const CloudPulseDashboardSelect = React.memo( fullWidth groupBy={(option: Dashboard) => option.service_type} isOptionEqualToValue={(option, value) => option.id === value.id} - label="Select a Dashboard" + label="Dashboard" loading={dashboardsLoading || serviceTypesLoading} + noMarginTop options={getSortedDashboardsList(dashboardsList ?? [])} placeholder={placeHolder} value={selectedDashboard ?? null} // Undefined is not allowed for uncontrolled component diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseRegionSelect.test.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseRegionSelect.test.tsx index fc49edf0f0a..3b571880994 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseRegionSelect.test.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseRegionSelect.test.tsx @@ -10,6 +10,7 @@ import type { Region } from '@linode/api-v4'; const props: CloudPulseRegionSelectProps = { handleRegionChange: vi.fn(), + label: 'Region', selectedDashboard: undefined, }; @@ -19,9 +20,11 @@ describe('CloudPulseRegionSelect', () => { } as ReturnType); it('should render a Region Select component', () => { - const { getByTestId } = renderWithTheme( + const { getByLabelText, getByTestId } = renderWithTheme( ); + const { label } = props; + expect(getByLabelText(label)).toBeInTheDocument(); expect(getByTestId('region-select')).toBeInTheDocument(); }); }); diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseRegionSelect.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseRegionSelect.tsx index 7f775d3eb87..6a6b7bc388c 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseRegionSelect.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseRegionSelect.tsx @@ -8,6 +8,7 @@ import type { Dashboard, FilterValue } from '@linode/api-v4'; export interface CloudPulseRegionSelectProps { defaultValue?: FilterValue; handleRegionChange: (region: string | undefined, savePref?: boolean) => void; + label: string; placeholder?: string; savePreferences?: boolean; selectedDashboard: Dashboard | undefined; @@ -20,6 +21,7 @@ export const CloudPulseRegionSelect = React.memo( const { defaultValue, handleRegionChange, + label, placeholder, savePreferences, selectedDashboard, @@ -44,15 +46,13 @@ export const CloudPulseRegionSelect = React.memo( setSelectedRegion(region?.id); handleRegionChange(region?.id, savePreferences); }} - textFieldProps={{ - hideLabel: true, - }} currentCapability={undefined} data-testid="region-select" disableClearable={false} disabled={!selectedDashboard || !regions} fullWidth - label="Select a Region" + label={label || 'Region'} + noMarginTop placeholder={placeholder ?? 'Select a Region'} regions={regions ? regions : []} value={selectedRegion} diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseResourcesSelect.test.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseResourcesSelect.test.tsx index 019d038369b..23aaecb35ac 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseResourcesSelect.test.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseResourcesSelect.test.tsx @@ -33,12 +33,14 @@ describe('CloudPulseResourcesSelect component tests', () => { const { getByPlaceholderText, getByTestId } = renderWithTheme( ); expect(getByTestId('resource-select')).toBeInTheDocument(); - expect(getByPlaceholderText('Select a Resource')).toBeInTheDocument(); + expect(screen.getByLabelText('Resources')).toBeInTheDocument(); + expect(getByPlaceholderText('Select Resources')).toBeInTheDocument(); }), it('should render resources happy path', () => { queryMocks.useResourcesQuery.mockReturnValue({ @@ -50,11 +52,13 @@ describe('CloudPulseResourcesSelect component tests', () => { renderWithTheme( ); fireEvent.click(screen.getByRole('button', { name: 'Open' })); + expect(screen.getByLabelText('Resources')).toBeInTheDocument(); expect( screen.getByRole('option', { name: 'linode-3', @@ -77,12 +81,14 @@ describe('CloudPulseResourcesSelect component tests', () => { renderWithTheme( ); fireEvent.click(screen.getByRole('button', { name: 'Open' })); fireEvent.click(screen.getByRole('option', { name: SELECT_ALL })); + expect(screen.getByLabelText('Resources')).toBeInTheDocument(); expect( screen.getByRole('option', { name: 'linode-5', @@ -105,6 +111,7 @@ describe('CloudPulseResourcesSelect component tests', () => { renderWithTheme( @@ -112,6 +119,7 @@ describe('CloudPulseResourcesSelect component tests', () => { fireEvent.click(screen.getByRole('button', { name: 'Open' })); fireEvent.click(screen.getByRole('option', { name: SELECT_ALL })); fireEvent.click(screen.getByRole('option', { name: 'Deselect All' })); + expect(screen.getByLabelText('Resources')).toBeInTheDocument(); expect( screen.getByRole('option', { name: 'linode-7', @@ -134,6 +142,7 @@ describe('CloudPulseResourcesSelect component tests', () => { renderWithTheme( @@ -141,6 +150,7 @@ describe('CloudPulseResourcesSelect component tests', () => { fireEvent.click(screen.getByRole('button', { name: 'Open' })); fireEvent.click(screen.getByRole('option', { name: 'linode-9' })); fireEvent.click(screen.getByRole('option', { name: 'linode-10' })); + expect(screen.getByLabelText('Resources')).toBeInTheDocument(); expect( screen.getByRole('option', { @@ -175,6 +185,7 @@ describe('CloudPulseResourcesSelect component tests', () => { void; + label: string; placeholder?: string; region?: string; resourceType: string | undefined; @@ -34,6 +35,7 @@ export const CloudPulseResourcesSelect = React.memo( defaultValue, disabled, handleResourcesSelection, + label, placeholder, region, resourceType, @@ -103,7 +105,7 @@ export const CloudPulseResourcesSelect = React.memo( isAutocompleteOpen.current = true; }} placeholder={ - selectedResources?.length ? '' : placeholder || 'Select a Resource' + selectedResources?.length ? '' : placeholder || 'Select Resources' } textFieldProps={{ InputProps: { @@ -115,16 +117,16 @@ export const CloudPulseResourcesSelect = React.memo( }, }, }, - hideLabel: true, }} autoHighlight clearOnBlur data-testid="resource-select" disabled={disabled || isLoading} isOptionEqualToValue={(option, value) => option.id === value.id} - label="Select a Resource" + label={label || 'Resources'} limitTags={2} multiple + noMarginTop options={getResourcesList} value={selectedResources ?? []} /> diff --git a/packages/manager/src/features/CloudPulse/shared/CloudPulseTimeRangeSelect.tsx b/packages/manager/src/features/CloudPulse/shared/CloudPulseTimeRangeSelect.tsx index 6a37d417c1a..c0e74b2d2b6 100644 --- a/packages/manager/src/features/CloudPulse/shared/CloudPulseTimeRangeSelect.tsx +++ b/packages/manager/src/features/CloudPulse/shared/CloudPulseTimeRangeSelect.tsx @@ -36,7 +36,7 @@ export type Labels = export const CloudPulseTimeRangeSelect = React.memo( (props: CloudPulseTimeRangeSelectProps) => { - const { defaultValue, handleStatsChange, savePreferences } = props; + const { defaultValue, handleStatsChange, label, savePreferences } = props; const options = generateSelectOptions(); const getDefaultValue = React.useCallback((): Item => { if (!savePreferences) { @@ -80,15 +80,13 @@ export const CloudPulseTimeRangeSelect = React.memo( onChange={(e, value: Item) => { handleChange(value); }} - textFieldProps={{ - hideLabel: true, - }} autoHighlight data-testid="cloudpulse-time-duration" disableClearable fullWidth isOptionEqualToValue={(option, value) => option.value === value.value} - label="Select a Time Duration" + label={label || 'Time Range'} + noMarginTop options={options} value={selectedTimeRange} />