Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Device manager - spinners while devices are signing out #9433

Merged
merged 1 commit into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@ limitations under the License.

.mx_FilteredDeviceList_headerButton {
flex-shrink: 0;
// override inline button styling
display: flex !important;
flex-direction: row;
gap: $spacing-8;
}
2 changes: 2 additions & 0 deletions res/css/views/elements/_AccessibleButton.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ limitations under the License.
&.mx_AccessibleButton_kind_primary_sm,
&.mx_AccessibleButton_kind_link,
&.mx_AccessibleButton_kind_link_inline,
&.mx_AccessibleButton_kind_danger_inline,
&.mx_AccessibleButton_kind_content_inline,
&.mx_AccessibleButton_kind_link_sm {
opacity: 0.4;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
} from './types';
import { DevicesState } from './useOwnDevices';
import FilteredDeviceListHeader from './FilteredDeviceListHeader';
import Spinner from '../../elements/Spinner';

interface Props {
devices: DevicesDictionary;
Expand Down Expand Up @@ -183,6 +184,7 @@ const DeviceListItem: React.FC<{
onClick={onDeviceExpandToggle}
device={device}
>
{ isSigningOut && <Spinner w={16} h={16} /> }
<DeviceExpandDetailsButton
isExpanded={isExpanded}
onClick={onDeviceExpandToggle}
Expand Down Expand Up @@ -276,6 +278,8 @@ export const FilteredDeviceList =
}
};

const isSigningOut = !!signingOutDeviceIds.length;

return <div className='mx_FilteredDeviceList' ref={ref}>
<FilteredDeviceListHeader
selectedDeviceCount={selectedDeviceIds.length}
Expand All @@ -287,14 +291,17 @@ export const FilteredDeviceList =
<AccessibleButton
data-testid='sign-out-selection-cta'
kind='danger_inline'
disabled={isSigningOut}
onClick={() => onSignOutDevices(selectedDeviceIds)}
className='mx_FilteredDeviceList_headerButton'
>
{ isSigningOut && <Spinner w={16} h={16} /> }
{ _t('Sign out') }
</AccessibleButton>
<AccessibleButton
data-testid='cancel-selection-cta'
kind='content_inline'
disabled={isSigningOut}
onClick={() => setSelectedDeviceIds([])}
className='mx_FilteredDeviceList_headerButton'
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('<SessionManagerTab />', () => {
};

const alicesInactiveDevice = {
device_id: 'alices_older_mobile_device',
device_id: 'alices_older_inactive_mobile_device',
last_seen_ts: Date.now() - (INACTIVE_DEVICE_AGE_MS + 1000),
};

Expand Down Expand Up @@ -105,7 +105,7 @@ describe('<SessionManagerTab />', () => {
const toggleDeviceDetails = (
getByTestId: ReturnType<typeof render>['getByTestId'],
deviceId: ExtendedDevice['device_id'],
) => {
): void => {
// open device detail
const tile = getByTestId(`device-tile-${deviceId}`);
const toggle = tile.querySelector('[aria-label="Toggle device details"]') as Element;
Expand All @@ -115,11 +115,18 @@ describe('<SessionManagerTab />', () => {
const toggleDeviceSelection = (
getByTestId: ReturnType<typeof render>['getByTestId'],
deviceId: ExtendedDevice['device_id'],
) => {
): void => {
const checkbox = getByTestId(`device-tile-checkbox-${deviceId}`);
fireEvent.click(checkbox);
};

const getDeviceTile = (
getByTestId: ReturnType<typeof render>['getByTestId'],
deviceId: ExtendedDevice['device_id'],
): HTMLElement => {
return getByTestId(`device-tile-${deviceId}`);
};

const setFilter = async (
container: HTMLElement,
option: DeviceSecurityVariation | string,
Expand Down Expand Up @@ -749,6 +756,7 @@ describe('<SessionManagerTab />', () => {
it('deletes multiple devices', async () => {
mockClient.getDevices.mockResolvedValue({ devices: [
alicesDevice, alicesMobileDevice, alicesOlderMobileDevice,
alicesInactiveDevice,
] });
mockClient.deleteMultipleDevices.mockResolvedValue({});

Expand All @@ -763,6 +771,24 @@ describe('<SessionManagerTab />', () => {

fireEvent.click(getByTestId('sign-out-selection-cta'));

// buttons disabled in list header
expect(getByTestId('sign-out-selection-cta').getAttribute('aria-disabled')).toBeTruthy();
expect(getByTestId('cancel-selection-cta').getAttribute('aria-disabled')).toBeTruthy();
// spinner rendered in list header
expect(getByTestId('sign-out-selection-cta').querySelector('.mx_Spinner')).toBeTruthy();

// spinners on signing out devices
expect(getDeviceTile(
getByTestId, alicesMobileDevice.device_id,
).querySelector('.mx_Spinner')).toBeTruthy();
expect(getDeviceTile(
getByTestId, alicesOlderMobileDevice.device_id,
).querySelector('.mx_Spinner')).toBeTruthy();
// no spinner for device that is not signing out
expect(getDeviceTile(
getByTestId, alicesInactiveDevice.device_id,
).querySelector('.mx_Spinner')).toBeFalsy();

// delete called with both ids
expect(mockClient.deleteMultipleDevices).toHaveBeenCalledWith(
[
Expand Down