diff --git a/packages/core/content-type-builder/admin/src/components/AttributeOptions/AttributeOption/index.js b/packages/core/content-type-builder/admin/src/components/AttributeOptions/AttributeOption/index.js index ab767fe443..c5a8f64f31 100644 --- a/packages/core/content-type-builder/admin/src/components/AttributeOptions/AttributeOption/index.js +++ b/packages/core/content-type-builder/admin/src/components/AttributeOptions/AttributeOption/index.js @@ -42,7 +42,10 @@ const AttributeOption = ({ type }) => { - {formatMessage({ id: getTrad(`attribute.${type}.description`) })} + {formatMessage({ + id: getTrad(`attribute.${type}.description`), + defaultMessage: 'A type for modeling data', + })} diff --git a/packages/core/content-type-builder/admin/src/components/AttributeOptions/index.js b/packages/core/content-type-builder/admin/src/components/AttributeOptions/index.js index db130b6eb0..37030fd8d0 100644 --- a/packages/core/content-type-builder/admin/src/components/AttributeOptions/index.js +++ b/packages/core/content-type-builder/admin/src/components/AttributeOptions/index.js @@ -12,58 +12,82 @@ import { Divider } from '@strapi/design-system/Divider'; import { Grid, GridItem } from '@strapi/design-system/Grid'; import { KeyboardNavigable } from '@strapi/design-system/KeyboardNavigable'; import { ModalBody } from '@strapi/design-system/ModalLayout'; -import { Flex } from '@strapi/design-system/Flex'; import { Stack } from '@strapi/design-system/Stack'; +import { Flex } from '@strapi/design-system/Flex'; import { Typography } from '@strapi/design-system/Typography'; +import { Tabs, Tab, TabGroup, TabPanels, TabPanel } from '@strapi/design-system/Tabs'; import { getTrad } from '../../utils'; import AttributeOption from './AttributeOption'; const AttributeOptions = ({ attributes, forTarget, kind }) => { const { formatMessage } = useIntl(); + const defaultTabId = getTrad('modalForm.tabs.default'); + const customTabId = getTrad('modalForm.tabs.custom'); + const titleIdSuffix = forTarget.includes('component') ? 'component' : kind; const titleId = getTrad(`modalForm.sub-header.chooseAttribute.${titleIdSuffix}`); return ( - - - - {formatMessage({ id: titleId, defaultMessage: 'Select a field' })} - - - - - - - {attributes.map((attributeRow, index) => { - const key = index; + + + + + {formatMessage({ id: titleId, defaultMessage: 'Select a field' })} + + + {formatMessage({ id: defaultTabId, defaultMessage: 'Default' })} + {formatMessage({ id: customTabId, defaultMessage: 'Custom' })} + + + + + + + + + + {attributes.map((attributeRow, index) => { + const key = index; - return ( - - {attributeRow.map((attribute, index) => { - const isOdd = index % 2 === 1; - const paddingLeft = isOdd ? 2 : 0; - const paddingRight = isOdd ? 0 : 2; + return ( + + {attributeRow.map((attribute, index) => { + const isOdd = index % 2 === 1; + const paddingLeft = isOdd ? 2 : 0; + const paddingRight = isOdd ? 0 : 2; - return ( - - - - - - ); - })} - - ); - })} - - - + return ( + + + + + + ); + })} + + ); + })} + + + + + Coming soon + + + ); }; diff --git a/packages/core/content-type-builder/admin/src/components/AttributeOptions/tests/__snapshots__/index.test.js.snap b/packages/core/content-type-builder/admin/src/components/AttributeOptions/tests/__snapshots__/index.test.js.snap new file mode 100644 index 0000000000..a1fe23434d --- /dev/null +++ b/packages/core/content-type-builder/admin/src/components/AttributeOptions/tests/__snapshots__/index.test.js.snap @@ -0,0 +1,1264 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders and matches the snapshot 1`] = ` +.c26 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +.c10 { + padding-bottom: 24px; +} + +.c17 { + padding-right: 8px; + padding-bottom: 4px; + padding-left: 0px; +} + +.c18 { + padding: 16px; + border-radius: 4px; +} + +.c22 { + padding-left: 16px; +} + +.c25 { + padding-right: 0px; + padding-bottom: 4px; + padding-left: 8px; +} + +.c2 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + +.c20 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; +} + +.c13 { + -webkit-align-items: stretch; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +.c14 > * { + margin-top: 0; + margin-bottom: 0; +} + +.c14 > * + * { + margin-top: 40px; +} + +.c3 { + color: #32324d; + font-weight: 600; + font-size: 1.125rem; + line-height: 1.22; +} + +.c23 { + font-weight: 600; + color: #32324d; + font-size: 0.875rem; + line-height: 1.43; +} + +.c24 { + color: #666687; + font-size: 0.75rem; + line-height: 1.33; +} + +.c11 { + background: #eaeaef; +} + +.c12 { + height: 1px; + border: none; + margin: 0; +} + +.c15 { + display: grid; + grid-template-columns: repeat(12,1fr); + gap: 0px; +} + +.c16 { + grid-column: span 6; + max-width: 100%; +} + +.c0 { + padding: 24px; +} + +.c1 { + overflow: auto; + max-height: 60vh; +} + +.c7 { + color: #4945ff; + font-weight: 600; + font-size: 0.6875rem; + line-height: 1.45; + text-transform: uppercase; +} + +.c9 { + color: #666687; + font-weight: 600; + font-size: 0.6875rem; + line-height: 1.45; + text-transform: uppercase; +} + +.c5 { + padding: 16px; +} + +.c6 { + border-bottom: 2px solid #4945ff; +} + +.c8 { + border-bottom: 2px solid transparent; +} + +.c4[aria-disabled='true'] { + cursor: not-allowed; +} + +.c21 { + width: 2rem; + height: 1.5rem; + box-sizing: content-box; +} + +.c19 { + width: 100%; + height: 100%; + border: 1px solid #dcdce4; + text-align: left; +} + +.c19:hover { + background: #f0f0ff; + border: 1px solid #d9d8ff; +} + +@media (max-width:68.75rem) { + .c16 { + grid-column: span; + } +} + +@media (max-width:34.375rem) { + .c16 { + grid-column: span; + } +} + +
+
+
+
+

+ Select a field +

+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

+

+

+
+`; diff --git a/packages/core/content-type-builder/admin/src/components/AttributeOptions/tests/index.test.js b/packages/core/content-type-builder/admin/src/components/AttributeOptions/tests/index.test.js new file mode 100644 index 0000000000..8b927ce234 --- /dev/null +++ b/packages/core/content-type-builder/admin/src/components/AttributeOptions/tests/index.test.js @@ -0,0 +1,77 @@ +import React from 'react'; +import { render, screen, getByText, fireEvent } from '@testing-library/react'; +import { lightTheme, ThemeProvider } from '@strapi/design-system'; +import { IntlProvider } from 'react-intl'; +import FormModalNavigationProvider from '../../FormModalNavigationProvider'; +import AttributeOptions from '../index'; + +const mockAttributes = [ + [ + 'text', + 'email', + 'richtext', + 'password', + 'number', + 'enumeration', + 'date', + 'media', + 'boolean', + 'json', + 'relation', + 'uid', + ], + ['component', 'dynamiczone'], +]; + +const App = ( + + + + + + + +); + +describe('', () => { + it('renders and matches the snapshot', () => { + const { container } = render(App); + + expect(container).toMatchSnapshot(); + }); + + it('shows the simple tabs', () => { + render(App); + + const defaultTab = screen.getByRole('tab', { selected: true }); + const customTab = screen.getByRole('tab', { selected: false }); + + expect(defaultTab).toBeVisible(); + expect(customTab).toBeVisible(); + }); + + it('defaults to the default tab', () => { + render(App); + + const comingSoonText = screen.queryByText('Coming soon'); + + expect(comingSoonText).toEqual(null); + }); + + it('switches to the custom tab', () => { + render(App); + + const customTab = screen.getByRole('tab', { selected: false }); + fireEvent.click(customTab); + const customTabSelected = screen.getByRole('tab', { selected: true }); + const customTabText = getByText(customTabSelected, 'Custom'); + const comingSoonText = screen.getByText('Coming soon'); + + expect(customTabText).not.toBe(null); + expect(comingSoonText).toBeVisible(); + }); +}); diff --git a/packages/core/content-type-builder/admin/src/translations/en.json b/packages/core/content-type-builder/admin/src/translations/en.json index 77d02a63f2..bd855aa955 100644 --- a/packages/core/content-type-builder/admin/src/translations/en.json +++ b/packages/core/content-type-builder/admin/src/translations/en.json @@ -155,6 +155,9 @@ "modalForm.sub-header.chooseAttribute.collectionType": "Select a field for your collection type", "modalForm.sub-header.chooseAttribute.component": "Select a field for your component", "modalForm.sub-header.chooseAttribute.singleType": "Select a field for your single type", + "modalForm.tabs.custom": "Custom", + "modalForm.tabs.default": "Default", + "modalForm.tabs.label": "Default and Custom types tabs", "modelPage.attribute.relation-polymorphic": "Relation (polymorphic)", "modelPage.attribute.relationWith": "Relation with", "notification.error.dynamiczone-min.validation": "At least one component is required in a dynamic zone to be able to save a content type",