From 83789ccc9bc761fdcbaa1e208f6250a91101594b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Mon, 13 Nov 2023 13:33:51 +0000 Subject: [PATCH 1/3] Replace @radix-ui/react-select with react-select (#647) app/peers/edit was placeholder code, so deleted it instead Fixes #646 Effort began in #645 but fixes need to be merged quickly, so no time to split out this PR & have a clean switch from one select component to the other --- ui/app/mirrors/create/cdc.tsx | 34 +-- ui/app/mirrors/create/page.tsx | 99 ++++---- ui/app/mirrors/create/qrep.tsx | 77 +++--- ui/app/mirrors/create/tablemapping.tsx | 6 +- ui/app/peers/edit/[connectorId]/page.tsx | 291 ----------------------- ui/components/BigqueryConfig.tsx | 4 +- ui/components/SelectSource.tsx | 50 ++-- ui/lib/Layout/RowWithSelect.stories.tsx | 15 +- ui/lib/Select/Select.stories.tsx | 36 --- ui/lib/Select/Select.styles.ts | 50 ---- ui/lib/Select/Select.tsx | 34 --- ui/lib/Select/SelectItem.stories.tsx | 36 --- ui/lib/Select/SelectItem.styles.ts | 32 --- ui/lib/Select/SelectItem.tsx | 17 -- ui/lib/Select/SelectMenu.stories.tsx | 28 --- ui/lib/Select/SelectMenu.styles.ts | 12 - ui/lib/Select/SelectMenu.tsx | 13 - ui/lib/Select/index.ts | 2 - ui/lib/Table/Table.stories.tsx | 19 -- ui/lib/Table/TableCell.stories.tsx | 7 +- ui/lib/Table/TableRow.stories.tsx | 5 +- ui/package-lock.json | 45 +--- ui/package.json | 1 - 23 files changed, 139 insertions(+), 774 deletions(-) delete mode 100644 ui/app/peers/edit/[connectorId]/page.tsx delete mode 100644 ui/lib/Select/Select.stories.tsx delete mode 100644 ui/lib/Select/Select.styles.ts delete mode 100644 ui/lib/Select/Select.tsx delete mode 100644 ui/lib/Select/SelectItem.stories.tsx delete mode 100644 ui/lib/Select/SelectItem.styles.ts delete mode 100644 ui/lib/Select/SelectItem.tsx delete mode 100644 ui/lib/Select/SelectMenu.stories.tsx delete mode 100644 ui/lib/Select/SelectMenu.styles.ts delete mode 100644 ui/lib/Select/SelectMenu.tsx delete mode 100644 ui/lib/Select/index.ts diff --git a/ui/app/mirrors/create/cdc.tsx b/ui/app/mirrors/create/cdc.tsx index fba743a15e..ce7b6b931a 100644 --- a/ui/app/mirrors/create/cdc.tsx +++ b/ui/app/mirrors/create/cdc.tsx @@ -4,10 +4,10 @@ import { QRepSyncMode } from '@/grpc_generated/flow'; import { DBType } from '@/grpc_generated/peers'; import { Label } from '@/lib/Label'; import { RowWithSelect, RowWithSwitch, RowWithTextField } from '@/lib/Layout'; -import { Select, SelectItem } from '@/lib/Select'; import { Switch } from '@/lib/Switch'; import { TextField } from '@/lib/TextField'; import { Dispatch, SetStateAction } from 'react'; +import ReactSelect from 'react-select'; import { InfoPopover } from '../../../components/InfoPopover'; import { CDCConfig, MirrorSetter, TableMapRow } from '../../dto/MirrorsDTO'; import { MirrorSetting } from './helpers/common'; @@ -23,6 +23,11 @@ interface MirrorConfigProps { setSchema: Dispatch>; } +const SyncModeOptions = ['AVRO', 'Copy with Binary'].map((value) => ({ + label: value, + value, +})); + export const defaultSyncMode = (dtype: DBType | undefined) => { switch (dtype) { case DBType.POSTGRES: @@ -133,24 +138,23 @@ export default function CDCConfigForm({ alignItems: 'center', }} > - + options={SyncModeOptions} + /> {setting.tips && ( +
+ me +
+
{peer.name}
+ + ); +} + export default function CreateMirrors() { const router = useRouter(); const [mirrorName, setMirrorName] = useState(''); @@ -73,10 +94,10 @@ export default function CreateMirrors() { router.push('/mirrors'); }; - const handlePeer = (val: string, peerEnd: 'src' | 'dst') => { - const stateVal = peers.find((peer) => peer.name === val)!; + const handlePeer = (peer: Peer | null, peerEnd: 'src' | 'dst') => { + if (!peer) return; if (peerEnd === 'dst') { - if (stateVal.type === DBType.POSTGRES) { + if (peer.type === DBType.POSTGRES) { setConfig((curr) => { return { ...curr, @@ -86,8 +107,8 @@ export default function CreateMirrors() { }; }); } else if ( - stateVal.type === DBType.SNOWFLAKE || - stateVal.type === DBType.BIGQUERY + peer.type === DBType.SNOWFLAKE || + peer.type === DBType.BIGQUERY ) { setConfig((curr) => { return { @@ -100,14 +121,14 @@ export default function CreateMirrors() { } setConfig((curr) => ({ ...curr, - destination: stateVal, - destinationPeer: stateVal, + destination: peer, + destinationPeer: peer, })); } else { setConfig((curr) => ({ ...curr, - source: stateVal, - sourcePeer: stateVal, + source: peer, + sourcePeer: peer, })); } }; @@ -287,31 +308,15 @@ export default function CreateMirrors() { alignItems: 'center', }} > - + } + getOptionValue={getPeerValue} + formatOptionLabel={getPeerLabel} + /> - + onChange={(val, action) => handlePeer(val, 'dst')} + options={peers ?? []} + getOptionValue={getPeerValue} + formatOptionLabel={getPeerLabel} + /> ({ + label: value, + value, +})); +const WriteModes = ['Append', 'Upsert', 'Overwrite'].map((value) => ({ + label: value, + value, +})); + export default function QRepConfigForm({ settings, mirrorConfig, @@ -114,10 +122,9 @@ export default function QRepConfigForm({ const handleSourceChange = ( val: string | undefined, - action: string, setting: MirrorSetting ) => { - if (action == 'select-option' && val) { + if (val) { if (setting.label === 'Table') { setter((curr) => ({ ...curr, destinationTableIdentifier: val })); loadColumnOptions(val); @@ -192,33 +199,33 @@ export default function QRepConfigForm({ alignItems: 'center', }} > - {setting.label.includes('Sync') || - setting.label.includes('Write') ? ( - - ) : ( -
+
+ {setting.label.includes('Sync') || + setting.label.includes('Write') ? ( + + val && handleChange(val.value, setting) + } + isDisabled={setToDefault(setting)} + defaultValue={ + setToDefault(setting) + ? ((mode) => + SyncModes.find((opt) => opt.value === mode) || + WriteModes.find((opt) => opt.value === mode))( + defaultSyncMode( + mirrorConfig.destinationPeer?.type + ) + ) + : undefined + } + options={ + setting.label.includes('Sync') + ? SyncModes + : WriteModes + } + /> + ) : ( - handleSourceChange( - val?.value, - action.action, - setting - ) + handleSourceChange(val?.value, setting) } isLoading={loading} options={ @@ -239,8 +242,8 @@ export default function QRepConfigForm({ : sourceTables } /> -
- )} + )} +
{setting.tips && ( { - if (action.action == 'select-option') { - setSchema(val?.value || ''); - getTablesOfSchema(val?.value || ''); + if (val) { + setSchema(val.value || ''); + getTablesOfSchema(val.value || ''); } }} defaultInputValue={schema.length > 0 ? schema : 'Loading...'} diff --git a/ui/app/peers/edit/[connectorId]/page.tsx b/ui/app/peers/edit/[connectorId]/page.tsx deleted file mode 100644 index f7021b8c04..0000000000 --- a/ui/app/peers/edit/[connectorId]/page.tsx +++ /dev/null @@ -1,291 +0,0 @@ -'use client'; - -import { Badge } from '@/lib/Badge'; -import { Button } from '@/lib/Button'; -import { ButtonGroup } from '@/lib/ButtonGroup'; -import { TrackerChart } from '@/lib/Chart'; -import { Checkbox } from '@/lib/Checkbox'; -import { Header } from '@/lib/Header'; -import { Icon } from '@/lib/Icon'; -import { Label } from '@/lib/Label'; -import { - LayoutMain, - LayoutRightSidebar, - Row, - RowWithToggleGroup, -} from '@/lib/Layout'; -import { Panel } from '@/lib/Panel'; -import { SearchField } from '@/lib/SearchField'; -import { Select } from '@/lib/Select'; -import { Table, TableCell, TableRow } from '@/lib/Table'; -import { ToggleGroup, ToggleGroupItem } from '@/lib/Toggle'; -import { Color } from '@tremor/react'; -import { useState } from 'react'; - -const weekdays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']; - -interface Tracker { - color: Color; - tooltip: string; -} - -const weekData = weekdays.map((weekDay) => ({ - tooltip: weekDay, - color: Math.random() > 0.5 ? 'blue' : 'gray', -})); - -const Badges = [ - - - Active - , - - - Paused - , - - - Broken - , - - - Incomplete - , -]; - -const ExampleTable = ({ title }: { title: string }) => ( - {title}} - toolbar={{ - left: ( - <> - - - - - - - ), - right: , - }} - header={ - - - - - - - - - - - - - - - - - - } - > - {Array(8) - .fill(null) - .map((_, index) => ( - - - - - - - - - - - - - - - - - - - - {Badges[index % Badges.length]} - - - - - ))} -
-); - -type EditMirrorProps = { - params: { peerId: string }; -}; -export default function EditPeer({ params: { peerId } }: EditMirrorProps) { - const [logsOpen, setLogsOpen] = useState(false); - return ( - <> - - -
- - - - - - } - > - {peerId} -
- -
- -
- - - - -
-
- - - - -
- Sync history} - action={ - - Month - Week - Day - - } - /> - } - /> -
- - - -
- - -
{ - setLogsOpen(false); - }} - > - - - } - > - Logs -
- - -
- - - - - - - - - -
- - ); -} diff --git a/ui/components/BigqueryConfig.tsx b/ui/components/BigqueryConfig.tsx index d58def1d16..9da7c9601d 100644 --- a/ui/components/BigqueryConfig.tsx +++ b/ui/components/BigqueryConfig.tsx @@ -58,7 +58,7 @@ export default function BQConfig(props: BQProps) { @@ -122,7 +122,7 @@ export default function BQConfig(props: BQProps) { /> } diff --git a/ui/components/SelectSource.tsx b/ui/components/SelectSource.tsx index 49fde97c73..695174a2fe 100644 --- a/ui/components/SelectSource.tsx +++ b/ui/components/SelectSource.tsx @@ -1,8 +1,8 @@ 'use client'; import { DBType } from '@/grpc_generated/peers'; -import { Select, SelectItem } from '@/lib/Select'; import Image from 'next/image'; import { Dispatch, SetStateAction } from 'react'; +import ReactSelect from 'react-select'; import { DBTypeToImageMapping } from './PeerComponent'; interface SelectSourceProps { @@ -10,31 +10,35 @@ interface SelectSourceProps { setPeerType: Dispatch>; } -export default function SelectSource({ setPeerType }: SelectSourceProps) { - const dbTypes: string[] = Object.values(DBType).filter( - (value): value is string => - typeof value === 'string' && - (value === 'POSTGRES' || value === 'SNOWFLAKE' || value === 'BIGQUERY') +function SourceLabel({ value }: { value: string }) { + const peerLogo = DBTypeToImageMapping(value); + return ( +
+ peer +
{value}
+
); +} + +export default function SelectSource({ + peerType, + setPeerType, +}: SelectSourceProps) { + const dbTypes = Object.values(DBType) + .filter( + (value): value is string => + typeof value === 'string' && + (value === 'POSTGRES' || value === 'SNOWFLAKE' || value === 'BIGQUERY') + ) + .map((value) => ({ label: value, value })); return ( - + options={dbTypes} + defaultValue={dbTypes.find((opt) => opt.value === peerType)} + onChange={(val, action) => val && setPeerType(val.value)} + formatOptionLabel={SourceLabel} + /> ); } diff --git a/ui/lib/Layout/RowWithSelect.stories.tsx b/ui/lib/Layout/RowWithSelect.stories.tsx index a79c41990e..3af3dfaafa 100644 --- a/ui/lib/Layout/RowWithSelect.stories.tsx +++ b/ui/lib/Layout/RowWithSelect.stories.tsx @@ -1,6 +1,5 @@ import { Meta, StoryObj } from '@storybook/react'; import { Label } from '../Label'; -import { Select, SelectItem } from '../Select'; import { RowWithSelect } from './Layout'; export default { @@ -12,19 +11,7 @@ export default { Label ), - action: ( - - ), + action:
select
, description: , }, } satisfies Meta; diff --git a/ui/lib/Select/Select.stories.tsx b/ui/lib/Select/Select.stories.tsx deleted file mode 100644 index 9a30caf43b..0000000000 --- a/ui/lib/Select/Select.stories.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; -import { Separator } from '../Separator'; -import { Select } from './Select'; -import { SelectItem } from './SelectItem'; - -export default { - title: 'Components / Input / Select', - component: Select, - tags: ['autodocs'], -} satisfies Meta; - -type Story = StoryObj; -export const Default: Story = { - render: () => ( - - ), -}; - -export const Disabled: Story = { - render: () => ( - - ), -}; diff --git a/ui/lib/Select/Select.styles.ts b/ui/lib/Select/Select.styles.ts deleted file mode 100644 index 7f7b60c22a..0000000000 --- a/ui/lib/Select/Select.styles.ts +++ /dev/null @@ -1,50 +0,0 @@ -import * as RadixSelect from '@radix-ui/react-select'; -import styled, { css } from 'styled-components'; - -export const StyledSelectIcon = styled(RadixSelect.Icon)` - color: ${({ theme }) => theme.colors.base.text.lowContrast}; -`; - -export const StyledSelectTrigger = styled(RadixSelect.Trigger)` - all: unset; - - min-width: 128px; - width: 100%; - margin: ${({ theme }) => theme.spacing.xxSmall} 0px; - padding: ${({ theme }) => `${theme.spacing.xxSmall} ${theme.spacing.medium}`}; - - display: flex; - flex-flow: row nowrap; - - border-radius: ${({ theme }) => theme.radius.medium}; - color: ${({ theme }) => theme.colors.base.text.highContrast}; - ${({ theme }) => css(theme.text.regular.body)} - - &[data-state='open'], - &:focus-visible, - &:hover:not([data-disabled]) { - justify-content: space-between; - - > i { - color: ${({ theme }) => theme.colors.base.text.highContrast}; - } - } - - &[data-state='open'], - &:hover:not([data-disabled]) { - background-color: ${({ theme }) => theme.colors.base.surface.hovered}; - } - - &:focus { - outline: none; - } - - &:focus-visible { - outline: 2px solid ${({ theme }) => theme.colors.accent.border.normal}; - outline-offset: -2px; - } - - &[data-disabled] { - opacity: 0.3; - } -`; diff --git a/ui/lib/Select/Select.tsx b/ui/lib/Select/Select.tsx deleted file mode 100644 index 13f733e3c5..0000000000 --- a/ui/lib/Select/Select.tsx +++ /dev/null @@ -1,34 +0,0 @@ -'use client'; -// your-select.jsx -import * as RadixSelect from '@radix-ui/react-select'; -import { PropsWithChildren } from 'react'; -import { Icon } from '../Icon'; -import { StyledSelectIcon, StyledSelectTrigger } from './Select.styles'; -import { SelectMenu } from './SelectMenu'; - -type SelectProps = PropsWithChildren & { - placeholder?: string; - id?: string; - className?: string; -}; -export function Select({ - placeholder, - children, - id, - className, - ...selectRootProps -}: SelectProps) { - return ( - - - - - - - - - {children} - - - ); -} diff --git a/ui/lib/Select/SelectItem.stories.tsx b/ui/lib/Select/SelectItem.stories.tsx deleted file mode 100644 index e9e01e7603..0000000000 --- a/ui/lib/Select/SelectItem.stories.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as RadixSelect from '@radix-ui/react-select'; -import { Meta, StoryObj } from '@storybook/react'; -import { SelectItem } from './SelectItem'; - -export default { - title: 'Components / Input / Select / SelectItem', - component: SelectItem, - tags: ['autodocs'], - args: { - value: 'label', - }, -} satisfies Meta; - -type Story = StoryObj; -export const Default: Story = { - render: (props) => ( - - - Label - - - ), -}; - -export const Disabled: Story = { - args: { - disabled: true, - }, - render: (props) => ( - - - Label - - - ), -}; diff --git a/ui/lib/Select/SelectItem.styles.ts b/ui/lib/Select/SelectItem.styles.ts deleted file mode 100644 index 32c489ad6d..0000000000 --- a/ui/lib/Select/SelectItem.styles.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as RadixSelect from '@radix-ui/react-select'; -import styled, { css } from 'styled-components'; - -export const StyledItem = styled(RadixSelect.Item)` - position: relative; - display: flex; - justify-content: flex-start; - - padding: 0; - padding-left: ${({ theme }) => theme.spacing['4xLarge']}; - padding-right: ${({ theme }) => theme.spacing.medium}; - - border-radius: ${({ theme }) => theme.radius.small}; - - color: ${({ theme }) => theme.colors.base.text.highContrast}; - ${({ theme }) => css(theme.text.regular.body)} - - &[data-state="checked"], - &[data-highlighted] { - background-color: ${({ theme }) => theme.colors.base.surface.hovered}; - outline: none; - } - - &[data-disabled] { - opacity: 0.3; - } -`; - -export const StyledIndicator = styled(RadixSelect.ItemIndicator)` - position: absolute; - left: ${({ theme }) => theme.spacing.medium}; -`; diff --git a/ui/lib/Select/SelectItem.tsx b/ui/lib/Select/SelectItem.tsx deleted file mode 100644 index b0ff603e52..0000000000 --- a/ui/lib/Select/SelectItem.tsx +++ /dev/null @@ -1,17 +0,0 @@ -'use client'; -import * as RadixSelect from '@radix-ui/react-select'; -import type { PropsWithChildren } from 'react'; -import { Icon } from '../Icon'; -import { StyledIndicator, StyledItem } from './SelectItem.styles'; - -type SelectItemProps = PropsWithChildren; -export function SelectItem({ children, ...selectItemProps }: SelectItemProps) { - return ( - - - - - {children} - - ); -} diff --git a/ui/lib/Select/SelectMenu.stories.tsx b/ui/lib/Select/SelectMenu.stories.tsx deleted file mode 100644 index 36cb6f0727..0000000000 --- a/ui/lib/Select/SelectMenu.stories.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as RadixSelect from '@radix-ui/react-select'; -import { Meta, StoryObj } from '@storybook/react'; -import { SelectItem } from './SelectItem'; -import { SelectMenu } from './SelectMenu'; - -export default { - title: 'Components / Input / Select / SelectMenu', - component: SelectMenu, - tags: ['autodocs'], -} satisfies Meta; - -type Story = StoryObj; -export const Default: Story = { - render: (props) => ( -
- - - Item one - Item two - Item three - Item four - Item five - Item six - - -
- ), -}; diff --git a/ui/lib/Select/SelectMenu.styles.ts b/ui/lib/Select/SelectMenu.styles.ts deleted file mode 100644 index 82c22b3017..0000000000 --- a/ui/lib/Select/SelectMenu.styles.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as RadixSelect from '@radix-ui/react-select'; -import styled, { css } from 'styled-components'; - -export const SelectContent = styled(RadixSelect.SelectContent)` - padding: ${({ theme }) => theme.spacing.medium}; - border: 1px solid ${({ theme }) => theme.colors.base.border.subtle}; - border-radius: ${({ theme }) => theme.radius.medium}; - background-color: ${({ theme }) => theme.colors.base.background.normal}; - ${({ theme }) => css(theme.dropShadow.large)}; - - width: var(--radix-popper-anchor-width, 'auto'); -`; diff --git a/ui/lib/Select/SelectMenu.tsx b/ui/lib/Select/SelectMenu.tsx deleted file mode 100644 index 34aa128a37..0000000000 --- a/ui/lib/Select/SelectMenu.tsx +++ /dev/null @@ -1,13 +0,0 @@ -'use client'; -import * as RadixSelect from '@radix-ui/react-select'; -import { PropsWithChildren } from 'react'; -import { SelectContent } from './SelectMenu.styles'; - -type SelectMenuProps = PropsWithChildren; -export function SelectMenu({ children, ...contentProps }: SelectMenuProps) { - return ( - - {children} - - ); -} diff --git a/ui/lib/Select/index.ts b/ui/lib/Select/index.ts deleted file mode 100644 index 7669724a89..0000000000 --- a/ui/lib/Select/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './Select'; -export * from './SelectItem'; diff --git a/ui/lib/Table/Table.stories.tsx b/ui/lib/Table/Table.stories.tsx index 27c41ec3db..9bf333d213 100644 --- a/ui/lib/Table/Table.stories.tsx +++ b/ui/lib/Table/Table.stories.tsx @@ -5,7 +5,6 @@ import { Checkbox } from '../Checkbox'; import { Icon } from '../Icon'; import { Label } from '../Label'; import { SearchField } from '../SearchField'; -import { Select } from '../Select'; import { Table } from './Table'; import { TableCell } from './TableCell'; import { TableRow } from './TableRow'; @@ -50,24 +49,6 @@ export default { - - - - - - - - -