diff --git a/flow/connectors/postgres/client.go b/flow/connectors/postgres/client.go index ad641cf01a..28923c2375 100644 --- a/flow/connectors/postgres/client.go +++ b/flow/connectors/postgres/client.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "regexp" + "slices" "strings" "github.com/PeerDB-io/peer-flow/connectors/utils" @@ -12,7 +13,6 @@ import ( "github.com/jackc/pgx/v5" log "github.com/sirupsen/logrus" "golang.org/x/exp/maps" - "golang.org/x/exp/slices" ) //nolint:stylecheck diff --git a/flow/go.mod b/flow/go.mod index 3edd51e431..b31c7efe2a 100644 --- a/flow/go.mod +++ b/flow/go.mod @@ -9,13 +9,13 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v1.0.2 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.1.1 - github.com/aws/aws-sdk-go v1.47.8 + github.com/aws/aws-sdk-go v1.47.9 github.com/cenkalti/backoff/v4 v4.2.1 github.com/google/uuid v1.4.0 github.com/grafana/pyroscope-go v1.0.4 github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 github.com/hashicorp/go-multierror v1.1.1 - github.com/jackc/pglogrepl v0.0.0-20230826184802-9ed16cb201f6 + github.com/jackc/pglogrepl v0.0.0-20231111135425-1627ab1b5780 github.com/jackc/pgx/v5 v5.5.0 github.com/jmoiron/sqlx v1.3.5 github.com/joho/godotenv v1.5.1 @@ -130,7 +130,7 @@ require ( github.com/zeebo/xxh3 v1.0.2 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/crypto v0.15.0 // indirect - golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.18.0 // indirect golang.org/x/oauth2 v0.14.0 // indirect diff --git a/flow/go.sum b/flow/go.sum index 48875e8d09..47c9799543 100644 --- a/flow/go.sum +++ b/flow/go.sum @@ -66,8 +66,8 @@ github.com/apache/arrow/go/v12 v12.0.1 h1:JsR2+hzYYjgSUkBSaahpqCetqZMr76djX80fF/ github.com/apache/arrow/go/v12 v12.0.1/go.mod h1:weuTY7JvTG/HDPtMQxEUp7pU73vkLWMLpY67QwZ/WWw= github.com/apache/thrift v0.19.0 h1:sOqkWPzMj7w6XaYbJQG7m4sGqVolaW/0D28Ln7yPzMk= github.com/apache/thrift v0.19.0/go.mod h1:SUALL216IiaOw2Oy+5Vs9lboJ/t9g40C+G07Dc0QC1I= -github.com/aws/aws-sdk-go v1.47.8 h1:VCFyO5UTREnhR0HRf9roqFfJeeRVin58zUy+pBMhwjY= -github.com/aws/aws-sdk-go v1.47.8/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.47.9 h1:rarTsos0mA16q+huicGx0e560aYRtOucV5z2Mw23JRY= +github.com/aws/aws-sdk-go v1.47.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.22.2 h1:lV0U8fnhAnPz8YcdmZVV60+tr6CakHzqA6P8T46ExJI= github.com/aws/aws-sdk-go-v2 v1.22.2/go.mod h1:Kd0OJtkW3Q0M0lUWGszapWjEvrXDzRW+D21JNsroB+c= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.0 h1:hHgLiIrTRtddC0AKcJr5s7i/hLgcpTt+q/FKxf1Zayk= @@ -255,8 +255,8 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pglogrepl v0.0.0-20230826184802-9ed16cb201f6 h1:qMz8L5hFgBNF3W72W7OwuUjB04qlic7YPzij+UiFle0= -github.com/jackc/pglogrepl v0.0.0-20230826184802-9ed16cb201f6/go.mod h1:Y1HIk+uK2wXiU8vuvQh0GaSzVh+MXFn2kfKBMpn6CZg= +github.com/jackc/pglogrepl v0.0.0-20231111135425-1627ab1b5780 h1:pNK2AKKIRC1MMMvpa6UiNtdtOebpiIloX7q2JZDkfsk= +github.com/jackc/pglogrepl v0.0.0-20231111135425-1627ab1b5780/go.mod h1:Y1HIk+uK2wXiU8vuvQh0GaSzVh+MXFn2kfKBMpn6CZg= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= @@ -462,8 +462,8 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w= -golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= diff --git a/nexus/Cargo.lock b/nexus/Cargo.lock index 286dc47542..dc7aeaa6e0 100644 --- a/nexus/Cargo.lock +++ b/nexus/Cargo.lock @@ -477,7 +477,7 @@ dependencies = [ "serde_json", "tar", "tempfile", - "toml 0.8.6", + "toml 0.8.8", "xz2", "zopfli", ] @@ -489,7 +489,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3f9629bc6c4388ea699781dc988c2b99766d7679b151c81990b4fa1208fafd3" dependencies = [ "serde", - "toml 0.8.6", + "toml 0.8.8", ] [[package]] @@ -521,9 +521,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" dependencies = [ "libc", ] @@ -561,9 +561,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -571,9 +571,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -877,9 +877,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -896,9 +896,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" dependencies = [ "libc", "windows-sys 0.48.0", @@ -1136,9 +1136,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -1214,9 +1214,9 @@ checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "hdrhistogram" -version = "7.5.2" +version = "7.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" +checksum = "a5b38e5c02b7c7be48c8dc5217c4f1634af2ea221caae2e024bffc7a7651c691" dependencies = [ "base64 0.13.1", "byteorder", @@ -1263,9 +1263,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "f95b9abcae896730d42b78e09c155ed4ddf82c07b4de772c64aee5b2d8b7c150" dependencies = [ "bytes", "fnv", @@ -1516,9 +1516,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" @@ -2864,9 +2864,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ "base64 0.21.5", ] @@ -2987,9 +2987,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.190" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] @@ -3005,9 +3005,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", @@ -3103,9 +3103,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", "rand_core", @@ -3170,9 +3170,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "snafu" @@ -3451,9 +3451,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -3481,9 +3481,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", @@ -3596,14 +3596,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff9e3abce27ee2c9a37f9ad37238c1bdd4e789c84ba37df76aa4d528f5072cc" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.7", + "toml_edit 0.21.0", ] [[package]] @@ -3630,9 +3630,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.7" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ "indexmap 2.1.0", "serde", diff --git a/ui/app/api/peers/route.ts b/ui/app/api/peers/route.ts index b1d1359e19..ff790da762 100644 --- a/ui/app/api/peers/route.ts +++ b/ui/app/api/peers/route.ts @@ -154,6 +154,6 @@ export const getTruePeer = (peer: CatalogPeer) => { // GET all the peers from the database export async function GET(request: Request) { const peers = await prisma.peers.findMany(); - const truePeers: Peer[] = peers.map((peer) => getTruePeer(peer)); + const truePeers: Peer[] = peers.map((peer: CatalogPeer) => getTruePeer(peer)); return new Response(JSON.stringify(truePeers)); } 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 && ( >, route: RouteCallback ) => { - if (!flowJobName) { - setMsg({ ok: false, msg: 'Mirror name is required' }); + const flowNameValid = flowNameSchema.safeParse(flowJobName); + if (!flowNameValid.success) { + const flowNameErr = flowNameValid.error.issues[0].message; + setMsg({ ok: false, msg: flowNameErr }); return; } + const isValid = validateCDCFields(rows, setMsg, config); if (!isValid) return; const tableNameMapping = reformattedTableMapping(rows); @@ -125,10 +133,13 @@ export const handleCreateQRep = async ( route: RouteCallback, xmin?: boolean ) => { - if (!flowJobName) { - setMsg({ ok: false, msg: 'Mirror name is required' }); + const flowNameValid = flowNameSchema.safeParse(flowJobName); + if (!flowNameValid.success) { + const flowNameErr = flowNameValid.error.issues[0].message; + setMsg({ ok: false, msg: flowNameErr }); return; } + if (xmin == true) { config.watermarkColumn = 'xmin'; config.query = `SELECT * FROM ${config.watermarkTable} WHERE xmin::text::bigint BETWEEN {{.start}} AND {{.end}}`; diff --git a/ui/app/mirrors/create/page.tsx b/ui/app/mirrors/create/page.tsx index afc94039be..d2027f1dd8 100644 --- a/ui/app/mirrors/create/page.tsx +++ b/ui/app/mirrors/create/page.tsx @@ -13,13 +13,13 @@ import { } from '@/lib/Layout'; import { Panel } from '@/lib/Panel'; import { RadioButton, RadioButtonGroup } from '@/lib/RadioButtonGroup'; -import { Select, SelectItem } from '@/lib/Select'; import { TextField } from '@/lib/TextField'; import { Divider } from '@tremor/react'; import Image from 'next/image'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; +import ReactSelect from 'react-select'; import { InfoPopover } from '../../../components/InfoPopover'; import { CDCConfig, TableMapRow } from '../../dto/MirrorsDTO'; import CDCConfigForm from './cdc'; @@ -30,6 +30,27 @@ import { qrepSettings } from './helpers/qrep'; import QRepConfigForm from './qrep'; import QRepQuery from './query'; +function getPeerValue(peer: Peer) { + return peer.name; +} + +function getPeerLabel(peer: Peer) { + return ( +
+
+ 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); @@ -159,8 +166,8 @@ export default function QRepConfigForm({ setting.label === 'Create Destination Table' ? mirrorConfig.setupWatermarkTableOnDestination : setting.label === 'Initial Copy Only' - ? mirrorConfig.initialCopyOnly - : mirrorConfig.dstTableFullResync + ? mirrorConfig.initialCopyOnly + : mirrorConfig.dstTableFullResync } onCheckedChange={(state: boolean) => handleChange(state, setting) @@ -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/[peerName]/helpers.tsx b/ui/app/peers/[peerName]/helpers.tsx index b219fe5c61..503455af7a 100644 --- a/ui/app/peers/[peerName]/helpers.tsx +++ b/ui/app/peers/[peerName]/helpers.tsx @@ -35,8 +35,8 @@ export const DurationDisplay = ({ duration }: { duration: number }) => { (duration % 3600) / 60 )} minutes` : duration >= 60 - ? `${Math.floor(duration / 60)} minute(s) ${Math.floor( - duration % 60 - )} seconds` - : `${duration.toFixed(2)} seconds`; + ? `${Math.floor(duration / 60)} minute(s) ${Math.floor( + duration % 60 + )} seconds` + : `${duration.toFixed(2)} seconds`; }; 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 { - - - - - - - - -