Skip to content

Commit

Permalink
feat(@leav/ui): manage display multi color attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
P0ppoff committed Dec 10, 2024
1 parent 9830ef9 commit 2a96aef
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 8 deletions.
1 change: 1 addition & 0 deletions libs/ui/src/components/Explorer/DataView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export const DataView: FunctionComponent<IDataViewProps> = ({
borderedRows
cellsBackgroundColor={theme.utilities.light}
backgroundColor={theme.colors.primary['50']}
showHeader={dataGroupedFilteredSorted.length > 0}
columns={columns}
scroll={{y: scrollHeight}}
dataSource={dataGroupedFilteredSorted}
Expand Down
53 changes: 50 additions & 3 deletions libs/ui/src/components/Explorer/Explorer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ const simpleColorMockAttribute = {
}
} satisfies gqlTypes.AttributePropertiesFragment;

const multivalColorMockAttribute = {
...simpleColorMockAttribute,
id: 'color_multival',
multiple_values: true,
label: {
fr: 'Mon attribut couleur multiple',
en: 'My color attribute multi-valued'
}
} satisfies gqlTypes.AttributePropertiesFragment;

describe('Explorer', () => {
const recordId1 = '613982168';
const enrichTextRecord1 = '<h1>This is a test enrich text<script>alert("XSS")</script></h1>';
Expand Down Expand Up @@ -196,6 +206,11 @@ describe('Explorer', () => {
}
]
},
{
attributeId: multivalColorMockAttribute.id,
attributeProperties: multivalColorMockAttribute,
values: [{valuePayload: '00FF00'}, {valuePayload: 'FF0000'}, {valuePayload: '0000FF'}]
},
{
attributeId: booleanMockAttribute.id,
attributeProperties: booleanMockAttribute,
Expand Down Expand Up @@ -277,6 +292,11 @@ describe('Explorer', () => {
}
]
},
{
attributeId: multivalColorMockAttribute.id,
attributeProperties: multivalColorMockAttribute,
values: []
},
{
attributeId: booleanMockAttribute.id,
attributeProperties: booleanMockAttribute,
Expand All @@ -291,6 +311,16 @@ describe('Explorer', () => {
}
] satisfies gqlTypes.ExplorerQuery['records']['list'];

const mockEmptyExplorerQueryResult: Mockify<typeof gqlTypes.useExplorerQuery> = {
loading: false,
called: true,
data: {
records: {
list: []
}
}
};

const mockExplorerQueryResult: Mockify<typeof gqlTypes.useExplorerQuery> = {
loading: false,
called: true,
Expand Down Expand Up @@ -334,10 +364,12 @@ describe('Explorer', () => {
];
const [customPrimaryAction1, customPrimaryAction2] = customPrimaryActions;

let spyUseExplorerQuery: jest.SpyInstance;

beforeAll(() => {
jest.spyOn(gqlTypes, 'useExplorerQuery').mockImplementation(
() => mockExplorerQueryResult as gqlTypes.ExplorerQueryResult
);
spyUseExplorerQuery = jest
.spyOn(gqlTypes, 'useExplorerQuery')
.mockImplementation(() => mockExplorerQueryResult as gqlTypes.ExplorerQueryResult);

jest.spyOn(gqlTypes, 'useExplorerLibraryDataQuery').mockImplementation(
() => mockLibraryDataQueryResult as gqlTypes.ExplorerLibraryDataQueryResult
Expand Down Expand Up @@ -374,6 +406,15 @@ describe('Explorer', () => {
expect(screen.getByText(record2.whoAmI.label)).toBeInTheDocument();
});

test('Should hide table header when no data provided', async () => {
spyUseExplorerQuery.mockReturnValueOnce(mockEmptyExplorerQueryResult);
render(<Explorer library="campaigns" />);

expect(screen.getByRole('table')).toBeVisible();
expect(screen.getByRole('row')).toBeVisible();
expect(within(screen.getByRole('row')).getByText('Aucune donnée')).toBeVisible();
});

test('Should display the list of records in a table with attributes values', async () => {
render(
<Explorer
Expand All @@ -385,6 +426,7 @@ describe('Explorer', () => {
multivalLinkMockAttribute.id,
simpleRichTextMockAttribute.id,
simpleColorMockAttribute.id,
multivalColorMockAttribute.id,
booleanMockAttribute.id,
multivalBooleanMockAttribute.id
]
Expand All @@ -404,6 +446,7 @@ describe('Explorer', () => {
multivalLinkCell,
simpleRichTextCell,
simpleColorCell,
multivalColorCell,
boolCell,
multivalBoolCell
] = within(firstRecordRow).getAllByRole('cell');
Expand All @@ -426,6 +469,10 @@ describe('Explorer', () => {

expect(simpleColorCell).toHaveTextContent(`#${colorRecord1}`);

expect(within(multivalColorCell).getByText('#00FF00')).toBeVisible();
expect(within(multivalColorCell).getByText('#FF0000')).toBeVisible();
expect(within(multivalColorCell).getByText('#0000FF')).toBeVisible();

expect(within(boolCell).getByText(/yes/)).toBeVisible();

expect(within(multivalBoolCell).getByText(/yes/)).toBeVisible();
Expand Down
22 changes: 17 additions & 5 deletions libs/ui/src/components/Explorer/TableCell.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright LEAV Solutions 2017 until 2023/11/05, Copyright Aristid from 2023/11/06
// This file is released under LGPL V3
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt
import {FunctionComponent, ReactNode} from 'react';
import {
AttributeFormat,
AttributePropertiesFragment,
Expand All @@ -11,14 +12,13 @@ import {
PropertyValueValueFragment
} from '_ui/_gqlTypes';
import {useSharedTranslation} from '_ui/hooks/useSharedTranslation';
import {FaListAlt} from 'react-icons/fa';
import DOMPurify from 'dompurify';
import {KitAvatar, KitTag, KitTypography} from 'aristid-ds';
import {FunctionComponent, ReactNode} from 'react';
import {IKitTag, IKitTagConfig} from 'aristid-ds/dist/Kit/DataDisplay/Tag/types';
import styled from 'styled-components';
import {IdCard} from './IdCard';
import {IKitTag, IKitTagConfig} from 'aristid-ds/dist/Kit/DataDisplay/Tag/types';
import {TableTagGroup} from './TableTagGroup';
import {FaListAlt} from 'react-icons/fa';
import DOMPurify from 'dompurify';
import {multiColorTagAvatarClassName, TableTagGroup} from './TableTagGroup';

const isStandardValue = (
v: PropertyValueFragment,
Expand Down Expand Up @@ -80,6 +80,18 @@ export const TableCell: FunctionComponent<ITableCellProps> = ({values, attribute
},
type: value.valuePayload ? 'primary' : ('neutral' as IKitTag['type'])
};
case AttributeFormat.color:
const colorHexa = `#${value.valuePayload}`;
return {
idCardProps: {
description: colorHexa,
avatarProps: {
color: colorHexa,
shape: 'square',
className: multiColorTagAvatarClassName
}
}
};
default:
const valueContent =
attributeProperties.format === AttributeFormat.encrypted
Expand Down
9 changes: 9 additions & 0 deletions libs/ui/src/components/Explorer/TableTagGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {IKitTag} from 'aristid-ds/dist/Kit/DataDisplay/Tag/types';
import {FunctionComponent} from 'react';
import styled from 'styled-components';

export const multiColorTagAvatarClassName = 'multi-color-tag-avatar';

Check warning on line 9 in libs/ui/src/components/Explorer/TableTagGroup.tsx

View workflow job for this annotation

GitHub Actions / lint

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components

const StyledTagsGroupDiv = styled.div`
display: flex;
column-gap: calc(var(--general-spacing-xxs) * 1px);
Expand All @@ -15,6 +17,13 @@ const StyledTagsGroupDiv = styled.div`
& > span {
margin-right: var(--general-spacing-none);
}
// TODO: wait DS to allow better customization on avatar
&&& .${multiColorTagAvatarClassName} {
height: calc(var(--general-spacing-s) * 1px);
width: calc(var(--general-spacing-s) * 1px);
border-radius: calc(var(--general-border-radius-xs) * 1px);
}
`;

export const TableTagGroup: FunctionComponent<{
Expand Down

0 comments on commit 2a96aef

Please sign in to comment.