💄(app-desk) highlight team selected

Highlight the selected team in the team list.
This commit is contained in:
Anthony LC
2024-02-20 15:52:06 +01:00
committed by Anthony LC
parent 45d05873e2
commit 5113eb013b
6 changed files with 110 additions and 35 deletions

View File

@@ -8,6 +8,13 @@ import { PanelTeams } from '../components/PanelTeams';
window.HTMLElement.prototype.scroll = function () {}; window.HTMLElement.prototype.scroll = function () {};
jest.mock('next/router', () => ({
...jest.requireActual('next/router'),
useRouter: () => ({
query: {},
}),
}));
describe('PanelTeams', () => { describe('PanelTeams', () => {
afterEach(() => { afterEach(() => {
fetchMock.restore(); fetchMock.restore();

View File

@@ -1,3 +1,4 @@
import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -15,9 +16,13 @@ interface TeamProps {
export const PanelTeam = ({ team }: TeamProps) => { export const PanelTeam = ({ team }: TeamProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme(); const { colorsTokens } = useCunninghamTheme();
const {
query: { id },
} = useRouter();
// There is at least 1 owner in the team // There is at least 1 owner in the team
const hasMembers = team.accesses.length > 1; const hasMembers = team.accesses.length > 1;
const isActive = team.id === id;
const commonProps = { const commonProps = {
className: 'p-t', className: 'p-t',
@@ -25,12 +30,40 @@ export const PanelTeam = ({ team }: TeamProps) => {
style: { style: {
borderRadius: '10px', borderRadius: '10px',
flexShrink: 0, flexShrink: 0,
background: '#fff',
}, },
}; };
const activeStyle = `
border-right: 4px solid ${colorsTokens()['primary-600']};
background: ${colorsTokens()['primary-400']};
span{
color: ${colorsTokens()['primary-text']};
}
`;
const hoverStyle = `
&:hover{
border-right: 4px solid ${colorsTokens()['primary-400']};
background: ${colorsTokens()['primary-300']};
span{
color: ${colorsTokens()['primary-text']};
}
}
`;
return ( return (
<Box as="li"> <Box
<StyledLink href={`/teams/${team.id}`}> className="m-0"
as="li"
$css={`
transition: all 0.2s ease-in;
border-right: 4px solid transparent;
${isActive ? activeStyle : hoverStyle}
`}
>
<StyledLink className="p-s pt-t pb-t" href={`/teams/${team.id}`}>
<Box $align="center" $direction="row" $gap="0.5rem"> <Box $align="center" $direction="row" $gap="0.5rem">
{hasMembers ? ( {hasMembers ? (
<IconGroup <IconGroup
@@ -53,7 +86,12 @@ export const PanelTeam = ({ team }: TeamProps) => {
}} }}
/> />
)} )}
<Text $weight="bold">{team.name}</Text> <Text
$weight="bold"
$color={!hasMembers ? colorsTokens()['greyscale-600'] : undefined}
>
{team.name}
</Text>
</Box> </Box>
</StyledLink> </StyledLink>
</Box> </Box>

View File

@@ -44,7 +44,7 @@ const PanelTeamsState = ({
if (!teams?.length) { if (!teams?.length) {
return ( return (
<Box $justify="center"> <Box $justify="center" className="m-s">
<Text as="p" className="mb-0 mt-0" $theme="greyscale" $variation="500"> <Text as="p" className="mb-0 mt-0" $theme="greyscale" $variation="500">
{t('0 group to display.')} {t('0 group to display.')}
</Text> </Text>
@@ -88,9 +88,8 @@ export const PanelTeams = () => {
void fetchNextPage(); void fetchNextPage();
}} }}
scrollContainer={containerRef.current} scrollContainer={containerRef.current}
$gap="1rem"
as="ul" as="ul"
className="p-s mt-t" className="p-0 mt-0"
role="listbox" role="listbox"
> >
<PanelTeamsState <PanelTeamsState

View File

@@ -1,9 +1,35 @@
import { expect, test } from '@playwright/test'; import { Page, expect, test } from '@playwright/test';
import { waitForElementCount } from '../helpers'; import { waitForElementCount } from '../helpers';
import { keyCloakSignIn } from './common'; import { keyCloakSignIn } from './common';
const createTeam = async (
page: Page,
teamName: string,
browserName: string,
length: number,
) => {
const panel = page.getByLabel('Teams panel').first();
const buttonCreate = page.getByRole('button', { name: 'Create the team' });
const randomTeams = Array.from({ length }, (_el, index) => {
return `${teamName}-${browserName}-${Math.floor(Math.random() * 10000)}-${index}`;
});
for (let i = 0; i < randomTeams.length; i++) {
await panel.getByRole('button', { name: 'Add a team' }).click();
await page.getByText('Team name').fill(randomTeams[i]);
await expect(buttonCreate).toBeEnabled();
await buttonCreate.click();
await expect(
panel.locator('li').nth(0).getByText(randomTeams[i]),
).toBeVisible();
}
return randomTeams;
};
test.beforeEach(async ({ page, browserName }) => { test.beforeEach(async ({ page, browserName }) => {
await page.goto('/'); await page.goto('/');
await keyCloakSignIn(page, browserName); await keyCloakSignIn(page, browserName);
@@ -31,21 +57,7 @@ test.describe('Teams Panel', () => {
test('002 - checks the sort button', async ({ page, browserName }) => { test('002 - checks the sort button', async ({ page, browserName }) => {
const panel = page.getByLabel('Teams panel').first(); const panel = page.getByLabel('Teams panel').first();
const randomTeams = await createTeam(page, 'team-sort', browserName, 3);
const buttonCreate = page.getByRole('button', { name: 'Create the team' });
const randomTeams = Array.from({ length: 3 }, (_el, index) => {
return `team-sort-${browserName}-${Math.floor(Math.random() * 1000)}-${index}`;
});
for (let i = 0; i < randomTeams.length; i++) {
await panel.getByRole('button', { name: 'Add a team' }).click();
await page.getByText('Team name').fill(randomTeams[i]);
await expect(buttonCreate).toBeEnabled();
await buttonCreate.click();
await expect(
panel.locator('li').nth(0).getByText(randomTeams[i]),
).toBeVisible();
}
await panel await panel
.getByRole('button', { .getByRole('button', {
@@ -66,17 +78,12 @@ test.describe('Teams Panel', () => {
test.setTimeout(90000); test.setTimeout(90000);
const panel = page.getByLabel('Teams panel').first(); const panel = page.getByLabel('Teams panel').first();
const buttonCreate = page.getByRole('button', { name: 'Create the team' }); const randomTeams = await createTeam(
const randomTeams = Array.from({ length: 40 }, (_el, index) => { page,
return `team-infinite-${browserName}-${Math.floor(Math.random() * 10000)}-${index}`; 'team-infinite',
}); browserName,
for (let i = 0; i < randomTeams.length; i++) { 40,
await panel.getByRole('button', { name: 'Add a team' }).click(); );
await page.getByText('Team name').fill(randomTeams[i]);
await expect(buttonCreate).toBeEnabled();
await buttonCreate.click();
await expect(panel.locator('li').getByText(randomTeams[i])).toBeVisible();
}
await expect(panel.locator('li')).toHaveCount(20); await expect(panel.locator('li')).toHaveCount(20);
await panel.getByText(randomTeams[24]).click(); await panel.getByText(randomTeams[24]).click();
@@ -84,4 +91,22 @@ test.describe('Teams Panel', () => {
await waitForElementCount(panel.locator('li'), 21, 10000); await waitForElementCount(panel.locator('li'), 21, 10000);
expect(await panel.locator('li').count()).toBeGreaterThan(20); expect(await panel.locator('li').count()).toBeGreaterThan(20);
}); });
test('004 - checks the hover and selected state', async ({
page,
browserName,
}) => {
const panel = page.getByLabel('Teams panel').first();
await createTeam(page, 'team-hover', browserName, 2);
const selectedTeam = panel.locator('li').nth(0);
await expect(selectedTeam).toHaveCSS(
'background-color',
'rgb(202, 202, 251)',
);
const hoverTeam = panel.locator('li').nth(1);
await hoverTeam.hover();
await expect(hoverTeam).toHaveCSS('background-color', 'rgb(227, 227, 253)');
});
}); });

View File

@@ -43,6 +43,7 @@ module.exports = {
'jest/expect-expect': 'error', 'jest/expect-expect': 'error',
'@typescript-eslint/unbound-method': 'off', '@typescript-eslint/unbound-method': 'off',
'jest/unbound-method': 'error', 'jest/unbound-method': 'error',
'react/react-in-jsx-scope': 'off',
}, },
}, },
], ],

View File

@@ -2,7 +2,6 @@ const common = require('./common');
module.exports = { module.exports = {
extends: [ extends: [
'people/jest',
'next', 'next',
'plugin:prettier/recommended', 'plugin:prettier/recommended',
'plugin:@tanstack/eslint-plugin-query/recommended', 'plugin:@tanstack/eslint-plugin-query/recommended',
@@ -30,6 +29,12 @@ module.exports = {
'react-hooks/rules-of-hooks': 'error', 'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error', 'react-hooks/exhaustive-deps': 'error',
}, },
overrides: common.eslintTS, overrides: [
...common.eslintTS,
{
files: ['*.spec.*', '*.test.*', '**/__mock__/**/*'],
extends: ['people/jest'],
},
],
ignorePatterns: ['node_modules'], ignorePatterns: ['node_modules'],
}; };