From 951cad98d3f1507440f38bb009d6c30f4ac246b0 Mon Sep 17 00:00:00 2001 From: Kerry <kerrya@element.io> Date: Thu, 29 Sep 2022 09:22:00 +0200 Subject: [PATCH] Device manager - extract filtered device list header (#9323) * extract filtered device list header * stylelint --- res/css/_components.pcss | 1 + .../settings/devices/_FilteredDeviceList.pcss | 20 --------- .../devices/_FilteredDeviceListHeader.pcss | 36 ++++++++++++++++ .../settings/devices/FilteredDeviceList.tsx | 8 ++-- .../devices/FilteredDeviceListHeader.tsx | 42 +++++++++++++++++++ src/i18n/strings/en_EN.json | 1 + .../devices/FilteredDeviceListHeader-test.tsx | 39 +++++++++++++++++ .../FilteredDeviceListHeader-test.tsx.snap | 19 +++++++++ .../tabs/user/SessionManagerTab-test.tsx | 2 +- .../SessionManagerTab-test.tsx.snap | 4 +- 10 files changed, 144 insertions(+), 28 deletions(-) create mode 100644 res/css/components/views/settings/devices/_FilteredDeviceListHeader.pcss create mode 100644 src/components/views/settings/devices/FilteredDeviceListHeader.tsx create mode 100644 test/components/views/settings/devices/FilteredDeviceListHeader-test.tsx create mode 100644 test/components/views/settings/devices/__snapshots__/FilteredDeviceListHeader-test.tsx.snap diff --git a/res/css/_components.pcss b/res/css/_components.pcss index 96e5a1a50f..6996d33cee 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -36,6 +36,7 @@ @import "./components/views/settings/devices/_DeviceTile.pcss"; @import "./components/views/settings/devices/_DeviceType.pcss"; @import "./components/views/settings/devices/_FilteredDeviceList.pcss"; +@import "./components/views/settings/devices/_FilteredDeviceListHeader.pcss"; @import "./components/views/settings/devices/_SecurityRecommendations.pcss"; @import "./components/views/settings/devices/_SelectableDeviceTile.pcss"; @import "./components/views/settings/shared/_SettingsSubsection.pcss"; diff --git a/res/css/components/views/settings/devices/_FilteredDeviceList.pcss b/res/css/components/views/settings/devices/_FilteredDeviceList.pcss index 01c8df787e..4b23271225 100644 --- a/res/css/components/views/settings/devices/_FilteredDeviceList.pcss +++ b/res/css/components/views/settings/devices/_FilteredDeviceList.pcss @@ -20,26 +20,6 @@ limitations under the License. } } -.mx_FilteredDeviceList_header { - display: flex; - flex-direction: row; - align-items: center; - box-sizing: border-box; - - width: 100%; - height: 48px; - padding: 0 $spacing-16; - margin-bottom: $spacing-32; - - background-color: $system; - border-radius: 8px; - color: $secondary-content; -} - -.mx_FilteredDeviceList_headerLabel { - flex: 1 1 100%; -} - .mx_FilteredDeviceList_list { list-style-type: none; display: grid; diff --git a/res/css/components/views/settings/devices/_FilteredDeviceListHeader.pcss b/res/css/components/views/settings/devices/_FilteredDeviceListHeader.pcss new file mode 100644 index 0000000000..2cdbcf356f --- /dev/null +++ b/res/css/components/views/settings/devices/_FilteredDeviceListHeader.pcss @@ -0,0 +1,36 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_FilteredDeviceListHeader { + display: flex; + flex-direction: row; + align-items: center; + box-sizing: border-box; + gap: $spacing-8; + + width: 100%; + height: 48px; + padding: 0 $spacing-16; + margin-bottom: $spacing-32; + + background-color: $system; + border-radius: 8px; + color: $secondary-content; +} + +.mx_FilteredDeviceListHeader_label { + flex: 1 1 100%; +} diff --git a/src/components/views/settings/devices/FilteredDeviceList.tsx b/src/components/views/settings/devices/FilteredDeviceList.tsx index 7affee684c..5ec0a428d0 100644 --- a/src/components/views/settings/devices/FilteredDeviceList.tsx +++ b/src/components/views/settings/devices/FilteredDeviceList.tsx @@ -36,6 +36,7 @@ import { DeviceWithVerification, } from './types'; import { DevicesState } from './useOwnDevices'; +import FilteredDeviceListHeader from './FilteredDeviceListHeader'; interface Props { devices: DevicesDictionary; @@ -242,10 +243,7 @@ export const FilteredDeviceList = }; return <div className='mx_FilteredDeviceList' ref={ref}> - <div className='mx_FilteredDeviceList_header'> - <span className='mx_FilteredDeviceList_headerLabel'> - { _t('Sessions') } - </span> + <FilteredDeviceListHeader selectedDeviceCount={0}> <FilterDropdown<DeviceFilterKey> id='device-list-filter' label={_t('Filter devices')} @@ -254,7 +252,7 @@ export const FilteredDeviceList = options={options} selectedLabel={_t('Show')} /> - </div> + </FilteredDeviceListHeader> { !!sortedDevices.length ? <FilterSecurityCard filter={filter} /> : <NoResults filter={filter} clearFilter={() => onFilterChange(undefined)} /> diff --git a/src/components/views/settings/devices/FilteredDeviceListHeader.tsx b/src/components/views/settings/devices/FilteredDeviceListHeader.tsx new file mode 100644 index 0000000000..6ecee4c8d2 --- /dev/null +++ b/src/components/views/settings/devices/FilteredDeviceListHeader.tsx @@ -0,0 +1,42 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { HTMLProps } from 'react'; + +import { _t } from '../../../../languageHandler'; + +interface Props extends Omit<HTMLProps<HTMLDivElement>, 'className'> { + selectedDeviceCount: number; + children?: React.ReactNode; +} + +const FilteredDeviceListHeader: React.FC<Props> = ({ + selectedDeviceCount, + children, + ...rest +}) => { + return <div className='mx_FilteredDeviceListHeader' {...rest}> + <span className='mx_FilteredDeviceListHeader_label'> + { selectedDeviceCount > 0 + ? _t('%(selectedDeviceCount)s sessions selected', { selectedDeviceCount }) + : _t('Sessions') + } + </span> + { children } + </div>; +}; + +export default FilteredDeviceListHeader; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b8a7361175..c1b25cb2ab 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1753,6 +1753,7 @@ "Inactive for %(inactiveAgeDays)s days or longer": "Inactive for %(inactiveAgeDays)s days or longer", "Filter devices": "Filter devices", "Show": "Show", + "%(selectedDeviceCount)s sessions selected": "%(selectedDeviceCount)s sessions selected", "Security recommendations": "Security recommendations", "Improve your account security by following these recommendations": "Improve your account security by following these recommendations", "View all": "View all", diff --git a/test/components/views/settings/devices/FilteredDeviceListHeader-test.tsx b/test/components/views/settings/devices/FilteredDeviceListHeader-test.tsx new file mode 100644 index 0000000000..8f7ecdc924 --- /dev/null +++ b/test/components/views/settings/devices/FilteredDeviceListHeader-test.tsx @@ -0,0 +1,39 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { render } from '@testing-library/react'; +import React from 'react'; + +import FilteredDeviceListHeader from '../../../../../src/components/views/settings/devices/FilteredDeviceListHeader'; + +describe('<FilteredDeviceListHeader />', () => { + const defaultProps = { + selectedDeviceCount: 0, + children: <div>test</div>, + ['data-testid']: 'test123', + }; + const getComponent = (props = {}) => (<FilteredDeviceListHeader {...defaultProps} {...props} />); + + it('renders correctly when no devices are selected', () => { + const { container } = render(getComponent()); + expect(container).toMatchSnapshot(); + }); + + it('renders correctly when some devices are selected', () => { + const { getByText } = render(getComponent({ selectedDeviceCount: 2 })); + expect(getByText('2 sessions selected')).toBeTruthy(); + }); +}); diff --git a/test/components/views/settings/devices/__snapshots__/FilteredDeviceListHeader-test.tsx.snap b/test/components/views/settings/devices/__snapshots__/FilteredDeviceListHeader-test.tsx.snap new file mode 100644 index 0000000000..f474cca811 --- /dev/null +++ b/test/components/views/settings/devices/__snapshots__/FilteredDeviceListHeader-test.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<FilteredDeviceListHeader /> renders correctly when no devices are selected 1`] = ` +<div> + <div + class="mx_FilteredDeviceListHeader" + data-testid="test123" + > + <span + class="mx_FilteredDeviceListHeader_label" + > + Sessions + </span> + <div> + test + </div> + </div> +</div> +`; diff --git a/test/components/views/settings/tabs/user/SessionManagerTab-test.tsx b/test/components/views/settings/tabs/user/SessionManagerTab-test.tsx index 5c1d5586aa..70bb171b12 100644 --- a/test/components/views/settings/tabs/user/SessionManagerTab-test.tsx +++ b/test/components/views/settings/tabs/user/SessionManagerTab-test.tsx @@ -279,7 +279,7 @@ describe('<SessionManagerTab />', () => { await flushPromisesWithFakeTimers(); // unverified filter is set - expect(container.querySelector('.mx_FilteredDeviceList_header')).toMatchSnapshot(); + expect(container.querySelector('.mx_FilteredDeviceListHeader')).toMatchSnapshot(); }); describe('device detail expansion', () => { diff --git a/test/components/views/settings/tabs/user/__snapshots__/SessionManagerTab-test.tsx.snap b/test/components/views/settings/tabs/user/__snapshots__/SessionManagerTab-test.tsx.snap index f4f120d0a5..32af1a3fa6 100644 --- a/test/components/views/settings/tabs/user/__snapshots__/SessionManagerTab-test.tsx.snap +++ b/test/components/views/settings/tabs/user/__snapshots__/SessionManagerTab-test.tsx.snap @@ -17,10 +17,10 @@ exports[`<SessionManagerTab /> Sign out Signs out of current device 1`] = ` exports[`<SessionManagerTab /> goes to filtered list from security recommendations 1`] = ` <div - class="mx_FilteredDeviceList_header" + class="mx_FilteredDeviceListHeader" > <span - class="mx_FilteredDeviceList_headerLabel" + class="mx_FilteredDeviceListHeader_label" > Sessions </span>