Device manager - scroll to filtered list from security recommendations (PSG-640) (#9227)
* scroll to filtered list from security recommendations * test sessionmanager scroll to * stable snapshot * fix strict errors * prtidy * use smooth scrolling
This commit is contained in:
parent
0d6a550c33
commit
54a66bd242
8 changed files with 201 additions and 91 deletions
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ForwardedRef, forwardRef } from 'react';
|
||||
|
||||
import { _t } from '../../../../languageHandler';
|
||||
import AccessibleButton from '../../elements/AccessibleButton';
|
||||
|
@ -150,70 +150,69 @@ const DeviceListItem: React.FC<{
|
|||
* Filtered list of devices
|
||||
* Sorted by latest activity descending
|
||||
*/
|
||||
const FilteredDeviceList: React.FC<Props> = ({
|
||||
devices,
|
||||
filter,
|
||||
expandedDeviceIds,
|
||||
onFilterChange,
|
||||
onDeviceExpandToggle,
|
||||
}) => {
|
||||
const sortedDevices = getFilteredSortedDevices(devices, filter);
|
||||
export const FilteredDeviceList =
|
||||
forwardRef(({
|
||||
devices,
|
||||
filter,
|
||||
expandedDeviceIds,
|
||||
onFilterChange,
|
||||
onDeviceExpandToggle,
|
||||
}: Props, ref: ForwardedRef<HTMLDivElement>) => {
|
||||
const sortedDevices = getFilteredSortedDevices(devices, filter);
|
||||
|
||||
const options: FilterDropdownOption<DeviceFilterKey>[] = [
|
||||
{ id: ALL_FILTER_ID, label: _t('All') },
|
||||
{
|
||||
id: DeviceSecurityVariation.Verified,
|
||||
label: _t('Verified'),
|
||||
description: _t('Ready for secure messaging'),
|
||||
},
|
||||
{
|
||||
id: DeviceSecurityVariation.Unverified,
|
||||
label: _t('Unverified'),
|
||||
description: _t('Not ready for secure messaging'),
|
||||
},
|
||||
{
|
||||
id: DeviceSecurityVariation.Inactive,
|
||||
label: _t('Inactive'),
|
||||
description: _t(
|
||||
'Inactive for %(inactiveAgeDays)s days or longer',
|
||||
{ inactiveAgeDays: INACTIVE_DEVICE_AGE_DAYS },
|
||||
),
|
||||
},
|
||||
];
|
||||
const options: FilterDropdownOption<DeviceFilterKey>[] = [
|
||||
{ id: ALL_FILTER_ID, label: _t('All') },
|
||||
{
|
||||
id: DeviceSecurityVariation.Verified,
|
||||
label: _t('Verified'),
|
||||
description: _t('Ready for secure messaging'),
|
||||
},
|
||||
{
|
||||
id: DeviceSecurityVariation.Unverified,
|
||||
label: _t('Unverified'),
|
||||
description: _t('Not ready for secure messaging'),
|
||||
},
|
||||
{
|
||||
id: DeviceSecurityVariation.Inactive,
|
||||
label: _t('Inactive'),
|
||||
description: _t(
|
||||
'Inactive for %(inactiveAgeDays)s days or longer',
|
||||
{ inactiveAgeDays: INACTIVE_DEVICE_AGE_DAYS },
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const onFilterOptionChange = (filterId: DeviceFilterKey) => {
|
||||
onFilterChange(filterId === ALL_FILTER_ID ? undefined : filterId as DeviceSecurityVariation);
|
||||
};
|
||||
const onFilterOptionChange = (filterId: DeviceFilterKey) => {
|
||||
onFilterChange(filterId === ALL_FILTER_ID ? undefined : filterId as DeviceSecurityVariation);
|
||||
};
|
||||
|
||||
return <div className='mx_FilteredDeviceList'>
|
||||
<div className='mx_FilteredDeviceList_header'>
|
||||
<span className='mx_FilteredDeviceList_headerLabel'>
|
||||
{ _t('Sessions') }
|
||||
</span>
|
||||
<FilterDropdown<DeviceFilterKey>
|
||||
id='device-list-filter'
|
||||
label={_t('Filter devices')}
|
||||
value={filter || ALL_FILTER_ID}
|
||||
onOptionChange={onFilterOptionChange}
|
||||
options={options}
|
||||
selectedLabel={_t('Show')}
|
||||
/>
|
||||
</div>
|
||||
{ !!sortedDevices.length
|
||||
? <FilterSecurityCard filter={filter} />
|
||||
: <NoResults filter={filter} clearFilter={() => onFilterChange(undefined)} />
|
||||
}
|
||||
<ol className='mx_FilteredDeviceList_list'>
|
||||
{ sortedDevices.map((device) => <DeviceListItem
|
||||
key={device.device_id}
|
||||
device={device}
|
||||
isExpanded={expandedDeviceIds.includes(device.device_id)}
|
||||
onDeviceExpandToggle={() => onDeviceExpandToggle(device.device_id)}
|
||||
/>,
|
||||
) }
|
||||
</ol>
|
||||
</div>
|
||||
;
|
||||
};
|
||||
return <div className='mx_FilteredDeviceList' ref={ref}>
|
||||
<div className='mx_FilteredDeviceList_header'>
|
||||
<span className='mx_FilteredDeviceList_headerLabel'>
|
||||
{ _t('Sessions') }
|
||||
</span>
|
||||
<FilterDropdown<DeviceFilterKey>
|
||||
id='device-list-filter'
|
||||
label={_t('Filter devices')}
|
||||
value={filter || ALL_FILTER_ID}
|
||||
onOptionChange={onFilterOptionChange}
|
||||
options={options}
|
||||
selectedLabel={_t('Show')}
|
||||
/>
|
||||
</div>
|
||||
{ !!sortedDevices.length
|
||||
? <FilterSecurityCard filter={filter} />
|
||||
: <NoResults filter={filter} clearFilter={() => onFilterChange(undefined)} />
|
||||
}
|
||||
<ol className='mx_FilteredDeviceList_list'>
|
||||
{ sortedDevices.map((device) => <DeviceListItem
|
||||
key={device.device_id}
|
||||
device={device}
|
||||
isExpanded={expandedDeviceIds.includes(device.device_id)}
|
||||
onDeviceExpandToggle={() => onDeviceExpandToggle(device.device_id)}
|
||||
/>,
|
||||
) }
|
||||
</ol>
|
||||
</div>;
|
||||
});
|
||||
|
||||
export default FilteredDeviceList;
|
||||
|
|
|
@ -29,9 +29,13 @@ import {
|
|||
|
||||
interface Props {
|
||||
devices: DevicesDictionary;
|
||||
goToFilteredList: (filter: DeviceSecurityVariation) => void;
|
||||
}
|
||||
|
||||
const SecurityRecommendations: React.FC<Props> = ({ devices }) => {
|
||||
const SecurityRecommendations: React.FC<Props> = ({
|
||||
devices,
|
||||
goToFilteredList,
|
||||
}) => {
|
||||
const devicesArray = Object.values<DeviceWithVerification>(devices);
|
||||
|
||||
const unverifiedDevicesCount = filterDevicesBySecurityRecommendation(
|
||||
|
@ -49,9 +53,6 @@ const SecurityRecommendations: React.FC<Props> = ({ devices }) => {
|
|||
|
||||
const inactiveAgeDays = INACTIVE_DEVICE_AGE_DAYS;
|
||||
|
||||
// TODO(kerrya) stubbed until PSG-640/652
|
||||
const noop = () => {};
|
||||
|
||||
return <SettingsSubsection
|
||||
heading={_t('Security recommendations')}
|
||||
description={_t('Improve your account security by following these recommendations')}
|
||||
|
@ -69,7 +70,8 @@ const SecurityRecommendations: React.FC<Props> = ({ devices }) => {
|
|||
>
|
||||
<AccessibleButton
|
||||
kind='link_inline'
|
||||
onClick={noop}
|
||||
onClick={() => goToFilteredList(DeviceSecurityVariation.Unverified)}
|
||||
data-testid='unverified-devices-cta'
|
||||
>
|
||||
{ _t('View all') + ` (${unverifiedDevicesCount})` }
|
||||
</AccessibleButton>
|
||||
|
@ -90,7 +92,8 @@ const SecurityRecommendations: React.FC<Props> = ({ devices }) => {
|
|||
>
|
||||
<AccessibleButton
|
||||
kind='link_inline'
|
||||
onClick={noop}
|
||||
onClick={() => goToFilteredList(DeviceSecurityVariation.Inactive)}
|
||||
data-testid='inactive-devices-cta'
|
||||
>
|
||||
{ _t('View all') + ` (${inactiveDevicesCount})` }
|
||||
</AccessibleButton>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue