diff --git a/flow/cmd/peer_data.go b/flow/cmd/peer_data.go index 6682e1aebb..7ec28329e2 100644 --- a/flow/cmd/peer_data.go +++ b/flow/cmd/peer_data.go @@ -92,8 +92,7 @@ func (h *FlowRequestHandler) GetTablesInSchema( CASE WHEN con.contype = 'p' OR t.relreplident = 'i' OR t.relreplident = 'f' THEN true ELSE false - END AS can_mirror, - pg_size_pretty(pg_total_relation_size(quote_ident(n.nspname) || '.' || quote_ident(t.relname))) :: text AS table_size + END AS can_mirror FROM pg_class t LEFT JOIN @@ -109,7 +108,6 @@ func (h *FlowRequestHandler) GetTablesInSchema( can_mirror DESC; `, req.SchemaName) if err != nil { - slog.Info("failed to fetch publications", slog.Any("error", err)) return &protos.SchemaTablesResponse{Tables: nil}, err } @@ -118,15 +116,10 @@ func (h *FlowRequestHandler) GetTablesInSchema( for rows.Next() { var table pgtype.Text var hasPkeyOrReplica pgtype.Bool - var tableSize pgtype.Text - err := rows.Scan(&table, &hasPkeyOrReplica, &tableSize) + err := rows.Scan(&table, &hasPkeyOrReplica) if err != nil { return &protos.SchemaTablesResponse{Tables: nil}, err } - var sizeOfTable string - if tableSize.Valid { - sizeOfTable = tableSize.String - } canMirror := false if hasPkeyOrReplica.Valid && hasPkeyOrReplica.Bool { canMirror = true @@ -135,14 +128,8 @@ func (h *FlowRequestHandler) GetTablesInSchema( tables = append(tables, &protos.TableResponse{ TableName: table.String, CanMirror: canMirror, - TableSize: sizeOfTable, }) } - - if err := rows.Err(); err != nil { - slog.Info("failed to fetch publications", slog.Any("error", err)) - return &protos.SchemaTablesResponse{Tables: nil}, err - } return &protos.SchemaTablesResponse{Tables: tables}, nil } @@ -338,26 +325,3 @@ func (h *FlowRequestHandler) GetStatInfo( StatData: statInfoRows, }, nil } - -func (h *FlowRequestHandler) GetPublications( - ctx context.Context, - req *protos.PostgresPeerActivityInfoRequest, -) (*protos.PeerPublicationsResponse, error) { - tunnel, peerConn, err := h.getConnForPGPeer(ctx, req.PeerName) - if err != nil { - return &protos.PeerPublicationsResponse{PublicationNames: nil}, err - } - defer tunnel.Close() - defer peerConn.Close(ctx) - - rows, err := peerConn.Query(ctx, "select pubname from pg_publication;") - if err != nil { - return &protos.PeerPublicationsResponse{PublicationNames: nil}, err - } - - publications, err := pgx.CollectRows[string](rows, pgx.RowTo) - if err != nil { - return &protos.PeerPublicationsResponse{PublicationNames: nil}, err - } - return &protos.PeerPublicationsResponse{PublicationNames: publications}, nil -} diff --git a/protos/route.proto b/protos/route.proto index 4d2c601fad..316459d78f 100644 --- a/protos/route.proto +++ b/protos/route.proto @@ -109,10 +109,6 @@ message PeerSchemasResponse { repeated string schemas = 1; } -message PeerPublicationsResponse { - repeated string publication_names = 1; -} - message SchemaTablesRequest { string peer_name = 1; string schema_name = 2; @@ -125,7 +121,6 @@ message SchemaTablesResponse { message TableResponse { string table_name = 1; bool can_mirror = 2; - string table_size = 3; } message AllTablesResponse { @@ -270,10 +265,6 @@ service FlowService { option (google.api.http) = { get: "/v1/peers/schemas" }; } - rpc GetPublications(PostgresPeerActivityInfoRequest) returns (PeerPublicationsResponse) { - option (google.api.http) = { get: "/v1/peers/publications" }; - } - rpc GetTablesInSchema(SchemaTablesRequest) returns (SchemaTablesResponse) { option (google.api.http) = { get: "/v1/peers/tables" }; } diff --git a/ui/app/api/peers/publications/route.ts b/ui/app/api/peers/publications/route.ts deleted file mode 100644 index 64dcd3dcf6..0000000000 --- a/ui/app/api/peers/publications/route.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { UPublicationsResponse } from '@/app/dto/PeersDTO'; -import { PeerPublicationsResponse } from '@/grpc_generated/route'; -import { GetFlowHttpAddressFromEnv } from '@/rpc/http'; - -export async function POST(request: Request) { - const body = await request.json(); - const { peerName } = body; - const flowServiceAddr = GetFlowHttpAddressFromEnv(); - try { - const publicationList: PeerPublicationsResponse = await fetch( - `${flowServiceAddr}/v1/peers/publications?peer_name=${peerName}` - ).then((res) => { - return res.json(); - }); - let response: UPublicationsResponse = { - publicationNames: publicationList.publicationNames, - }; - return new Response(JSON.stringify(response)); - } catch (e) { - console.log(e); - } -} diff --git a/ui/app/api/peers/schemas/route.ts b/ui/app/api/peers/schemas/route.ts index 9a1c10856e..0c701cb713 100644 --- a/ui/app/api/peers/schemas/route.ts +++ b/ui/app/api/peers/schemas/route.ts @@ -14,6 +14,11 @@ export async function POST(request: Request) { let response: USchemasResponse = { schemas: schemaList.schemas, }; + if (schemaList.message === 'no rows in result set') { + response = { + schemas: [], + }; + } return new Response(JSON.stringify(response)); } catch (e) { console.log(e); diff --git a/ui/app/dto/MirrorsDTO.ts b/ui/app/dto/MirrorsDTO.ts index 9b3724902a..33234a557d 100644 --- a/ui/app/dto/MirrorsDTO.ts +++ b/ui/app/dto/MirrorsDTO.ts @@ -26,7 +26,6 @@ export type TableMapRow = { exclude: Set; selected: boolean; canMirror: boolean; - tableSize: string; }; export type SyncStatusRow = { diff --git a/ui/app/dto/PeersDTO.ts b/ui/app/dto/PeersDTO.ts index 23b0243b4f..a015439d83 100644 --- a/ui/app/dto/PeersDTO.ts +++ b/ui/app/dto/PeersDTO.ts @@ -56,7 +56,3 @@ export type SlotLagPoint = { updatedAt: string; slotSize?: string; }; - -export type UPublicationsResponse = { - publicationNames: string[]; -}; diff --git a/ui/app/mirrors/[mirrorId]/edit/page.tsx b/ui/app/mirrors/[mirrorId]/edit/page.tsx index b4787f1b1c..4cff1b4538 100644 --- a/ui/app/mirrors/[mirrorId]/edit/page.tsx +++ b/ui/app/mirrors/[mirrorId]/edit/page.tsx @@ -11,7 +11,6 @@ import { Label } from '@/lib/Label'; import { RowWithTextField } from '@/lib/Layout'; import { ProgressCircle } from '@/lib/ProgressCircle'; import { TextField } from '@/lib/TextField'; -import { Callout } from '@tremor/react'; import { useRouter } from 'next/navigation'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { ToastContainer, toast } from 'react-toastify'; @@ -19,7 +18,6 @@ import 'react-toastify/dist/ReactToastify.css'; import TableMapping from '../../create/cdc/tablemapping'; import { reformattedTableMapping } from '../../create/handlers'; import { blankCDCSetting } from '../../create/helpers/common'; -import * as styles from '../../create/styles'; type EditMirrorProps = { params: { mirrorId: string }; }; @@ -122,6 +120,8 @@ const EditMirror = ({ params: { mirrorId } }: EditMirrorProps) => { return (
+ + {'Pull Batch Size'} } @@ -174,22 +174,6 @@ const EditMirror = ({ params: { mirrorId } }: EditMirrorProps) => { } /> - - {!isNotPaused && rows.some((row) => row.selected === true) && ( - - CDC will be put on hold until initial load for these added tables have - been completed. -

- The replication slot will grow during this period. -
- )} - { omitAdditionalTablesMapping={omitAdditionalTablesMapping} /> - {isNotPaused && ( - - Mirror can only be edited while paused. - + {isNotPaused ? ( + + ) : ( + )} - -
+
- +
diff --git a/ui/app/mirrors/create/cdc/cdc.tsx b/ui/app/mirrors/create/cdc/cdc.tsx index cb9ea4a381..25c15e58f4 100644 --- a/ui/app/mirrors/create/cdc/cdc.tsx +++ b/ui/app/mirrors/create/cdc/cdc.tsx @@ -2,9 +2,8 @@ import { DBType } from '@/grpc_generated/peers'; import { Button } from '@/lib/Button'; import { Icon } from '@/lib/Icon'; -import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react'; +import { Dispatch, SetStateAction, useMemo, useState } from 'react'; import { CDCConfig, MirrorSetter, TableMapRow } from '../../../dto/MirrorsDTO'; -import { fetchPublications } from '../handlers'; import { MirrorSetting } from '../helpers/common'; import CDCField from './fields'; import TableMapping from './tablemapping'; @@ -37,7 +36,6 @@ export default function CDCConfigForm({ rows, setRows, }: MirrorConfigProps) { - const [publications, setPublications] = useState(); const [show, setShow] = useState(false); const handleChange = (val: string | boolean, setting: MirrorSetting) => { let stateVal: string | boolean = val; @@ -66,26 +64,7 @@ export default function CDCConfigForm({ return true; }; - const optionsForField = (setting: MirrorSetting) => { - switch (setting.label) { - case 'Publication Name': - return publications; - default: - return []; - } - }; - - useEffect(() => { - fetchPublications(mirrorConfig.source?.name || '').then((pubs) => { - setPublications(pubs); - }); - }, [mirrorConfig.source?.name]); - - if ( - mirrorConfig.source != undefined && - mirrorConfig.destination != undefined && - publications != undefined - ) + if (mirrorConfig.source != undefined && mirrorConfig.destination != undefined) return ( <> {normalSettings.map((setting, id) => { @@ -95,7 +74,6 @@ export default function CDCConfigForm({ key={id} handleChange={handleChange} setting={setting} - options={optionsForField(setting)} /> ) ); @@ -123,10 +101,9 @@ export default function CDCConfigForm({ advancedSettings.map((setting, id) => { return ( ); })} diff --git a/ui/app/mirrors/create/cdc/fields.tsx b/ui/app/mirrors/create/cdc/fields.tsx index cf9f969d4d..acbb47764b 100644 --- a/ui/app/mirrors/create/cdc/fields.tsx +++ b/ui/app/mirrors/create/cdc/fields.tsx @@ -1,29 +1,21 @@ 'use client'; -import SelectTheme from '@/app/styles/select'; import { RequiredIndicator } from '@/components/RequiredIndicator'; import { Label } from '@/lib/Label'; -import { RowWithSelect, RowWithSwitch, RowWithTextField } from '@/lib/Layout'; +import { RowWithSwitch, RowWithTextField } from '@/lib/Layout'; import { Switch } from '@/lib/Switch'; import { TextField } from '@/lib/TextField'; -import ReactSelect from 'react-select'; import { InfoPopover } from '../../../../components/InfoPopover'; import { MirrorSetting } from '../helpers/common'; interface FieldProps { setting: MirrorSetting; handleChange: (val: string | boolean, setting: MirrorSetting) => void; - options?: string[]; } -const CDCField = ({ setting, handleChange, options }: FieldProps) => { +const CDCField = ({ setting, handleChange }: FieldProps) => { return setting.type === 'switch' ? ( - {setting.label} - {RequiredIndicator(setting.required)} - - } + label={} action={
{
} /> - ) : setting.type === 'select' ? ( - - {setting.label} - {RequiredIndicator(setting.required)} - - } - action={ -
-
- - val && handleChange(val.option, setting) - } - options={options?.map((option) => ({ option, label: option }))} - getOptionLabel={(option) => option.label} - getOptionValue={(option) => option.option} - theme={SelectTheme} - /> -
- {setting.tips && ( - - )} -
- } - /> ) : ( { const linkForDst = () => { - console.log(peerType); - switch (peerType.toUpperCase().replace(/%20/g, ' ')) { + switch (peerType) { case 'SNOWFLAKE': return 'https://docs.peerdb.io/connect/snowflake'; case 'BIGQUERY': return 'https://docs.peerdb.io/connect/bigquery'; - case 'RDS POSTGRESQL': - case 'POSTGRESQL': - return 'https://docs.peerdb.io/connect/rds_postgres'; - case 'AZURE FLEXIBLE POSTGRESQL': - return 'https://docs.peerdb.io/connect/azure_flexible_server_postgres'; - case 'GOOGLE CLOUD POSTGRESQL': - return 'https://docs.peerdb.io/connect/cloudsql_postgres'; default: - return ''; + return 'https://docs.peerdb.io/'; } }; - if (linkForDst() == '') { + if (peerType != 'SNOWFLAKE' && peerType != 'BIGQUERY') { return <>; } return ( diff --git a/ui/app/mirrors/create/cdc/schemabox.tsx b/ui/app/mirrors/create/cdc/schemabox.tsx index 4ec403f8ee..0c1d7e9a19 100644 --- a/ui/app/mirrors/create/cdc/schemabox.tsx +++ b/ui/app/mirrors/create/cdc/schemabox.tsx @@ -237,13 +237,6 @@ const SchemaBox = ({ > {row.source} - } action={ diff --git a/ui/app/mirrors/create/handlers.ts b/ui/app/mirrors/create/handlers.ts index 282fe70a34..beeb2aaf5d 100644 --- a/ui/app/mirrors/create/handlers.ts +++ b/ui/app/mirrors/create/handlers.ts @@ -1,7 +1,6 @@ import { UCreateMirrorResponse } from '@/app/dto/MirrorsDTO'; import { UColumnsResponse, - UPublicationsResponse, USchemasResponse, UTablesAllResponse, UTablesResponse, @@ -299,7 +298,6 @@ export const fetchTables = async ( exclude: new Set(), selected: false, canMirror: tableObject.canMirror, - tableSize: tableObject.tableSize, }); } } @@ -369,17 +367,3 @@ export const handleValidateCDC = async ( notify('CDC Mirror is valid', true); setLoading(false); }; - -export const fetchPublications = async (peerName: string) => { - const publicationsRes: UPublicationsResponse = await fetch( - '/api/peers/publications', - { - method: 'POST', - body: JSON.stringify({ - peerName, - }), - cache: 'no-store', - } - ).then((res) => res.json()); - return publicationsRes.publicationNames; -}; diff --git a/ui/app/mirrors/create/helpers/cdc.ts b/ui/app/mirrors/create/helpers/cdc.ts index fbf713d609..10ab07a951 100644 --- a/ui/app/mirrors/create/helpers/cdc.ts +++ b/ui/app/mirrors/create/helpers/cdc.ts @@ -11,7 +11,6 @@ export const cdcSettings: MirrorSetting[] = [ tips: 'Specify if you want initial load to happen for your tables.', type: 'switch', default: true, - required: true, }, { label: 'Pull Batch Size', @@ -36,7 +35,6 @@ export const cdcSettings: MirrorSetting[] = [ helpfulLink: 'https://docs.peerdb.io/metrics/important_cdc_configs', type: 'number', default: '60', - required: true, }, { label: 'Publication Name', @@ -45,11 +43,7 @@ export const cdcSettings: MirrorSetting[] = [ ...curr, publicationName: (value as string) || '', })), - type: 'select', - tips: 'PeerDB requires a publication associated with the tables you wish to sync.', - helpfulLink: - 'https://www.postgresql.org/docs/current/sql-createpublication.html', - required: true, + tips: 'If set, PeerDB will use this publication for the mirror.', }, { label: 'Replication Slot Name', @@ -65,36 +59,33 @@ export const cdcSettings: MirrorSetting[] = [ stateHandler: (value, setter) => setter((curr: CDCConfig) => ({ ...curr, - snapshotNumRowsPerPartition: parseInt(value as string, 10) || 1000000, + snapshotNumRowsPerPartition: parseInt(value as string, 10) || 500000, })), - tips: 'PeerDB splits up table data into partitions for increased performance. This setting controls the number of rows per partition. The default value is 1000000.', - default: '1000000', + tips: 'PeerDB splits up table data into partitions for increased performance. This setting controls the number of rows per partition. The default value is 500000.', + default: '500000', type: 'number', - advanced: true, }, { - label: 'Parallelism for Initial Load', + label: 'Snapshot Maximum Parallel Workers', stateHandler: (value, setter) => setter((curr: CDCConfig) => ({ ...curr, - snapshotMaxParallelWorkers: parseInt(value as string, 10) || 4, + snapshotMaxParallelWorkers: parseInt(value as string, 10) || 1, })), - tips: 'PeerDB spins up parallel threads for each partition in initial load. This setting controls the number of partitions to sync in parallel. The default value is 4.', - default: '4', + tips: 'PeerDB spins up parallel threads for each partition. This setting controls the number of partitions to sync in parallel. The default value is 1.', + default: '1', type: 'number', - required: true, }, { label: 'Snapshot Number of Tables In Parallel', stateHandler: (value, setter) => setter((curr: CDCConfig) => ({ ...curr, - snapshotNumTablesInParallel: parseInt(value as string, 10) || 1, + snapshotNumTablesInParallel: parseInt(value as string, 10) || 4, })), - tips: 'Specify the number of tables to sync perform initial load for, in parallel. The default value is 1.', - default: '1', + tips: 'Specify the number of tables to sync perform initial load for, in parallel. The default value is 4.', + default: '4', type: 'number', - advanced: true, }, { label: 'Snapshot Staging Path', @@ -104,7 +95,6 @@ export const cdcSettings: MirrorSetting[] = [ snapshotStagingPath: value as string | '', })), tips: 'You can specify staging path for Snapshot sync mode AVRO. For Snowflake as destination peer, this must be either empty or an S3 bucket URL. For BigQuery, this must be either empty or an existing GCS bucket name. In both cases, if empty, the local filesystem will be used.', - advanced: true, }, { label: 'CDC Staging Path', @@ -114,19 +104,17 @@ export const cdcSettings: MirrorSetting[] = [ cdcStagingPath: (value as string) || '', })), tips: 'You can specify staging path for CDC sync mode AVRO. For Snowflake as destination peer, this must be either empty or an S3 bucket URL. For BigQuery, this must be either empty or an existing GCS bucket name. In both cases, if empty, the local filesystem will be used.', - advanced: true, }, { label: 'Soft Delete', stateHandler: (value, setter) => setter((curr: CDCConfig) => ({ ...curr, - softDelete: (value as boolean) || true, + softDelete: (value as boolean) || false, })), tips: 'Allows you to mark some records as deleted without actual erasure from the database', - default: true, + default: false, type: 'switch', - required: true, }, { label: 'Initial Copy Only', diff --git a/ui/app/mirrors/create/helpers/common.ts b/ui/app/mirrors/create/helpers/common.ts index 0ed217e87b..5d1b8d9a93 100644 --- a/ui/app/mirrors/create/helpers/common.ts +++ b/ui/app/mirrors/create/helpers/common.ts @@ -23,12 +23,12 @@ export const blankCDCSetting: FlowConnectionConfigs = { maxBatchSize: 1000000, doInitialSnapshot: true, publicationName: '', - snapshotNumRowsPerPartition: 1000000, - snapshotMaxParallelWorkers: 4, - snapshotNumTablesInParallel: 1, + snapshotNumRowsPerPartition: 500000, + snapshotMaxParallelWorkers: 1, + snapshotNumTablesInParallel: 4, snapshotStagingPath: '', cdcStagingPath: '', - softDelete: true, + softDelete: false, replicationSlotName: '', resync: false, softDeleteColName: '', diff --git a/ui/app/mirrors/create/schema.ts b/ui/app/mirrors/create/schema.ts index dda55828a4..3ca4408315 100644 --- a/ui/app/mirrors/create/schema.ts +++ b/ui/app/mirrors/create/schema.ts @@ -58,15 +58,14 @@ export const cdcSchema = z.object({ publicationName: z .string({ invalid_type_error: 'Publication name must be a string', - required_error: 'Publication name must be selected.', }) - .min(1, 'Publication name must not be empty') - .max(255, 'Publication name must be less than 255 characters'), + .max(255, 'Publication name must be less than 255 characters') + .optional(), replicationSlotName: z .string({ - invalid_type_error: 'Replication slot name must be a string', + invalid_type_error: 'Publication name must be a string', }) - .max(255, 'Replication slot name must be less than 255 characters') + .max(255, 'Publication name must be less than 255 characters') .optional(), snapshotNumRowsPerPartition: z .number({ @@ -77,10 +76,10 @@ export const cdcSchema = z.object({ .optional(), snapshotMaxParallelWorkers: z .number({ - invalid_type_error: 'Initial load parallelism must be a number', + invalid_type_error: 'Snapshot max workers must be a number', }) .int() - .min(1, 'Initial load parallelism must be a positive integer') + .min(1, 'Snapshot max workers must be a positive integer') .optional(), snapshotNumTablesInParallel: z .number({ diff --git a/ui/app/peers/create/[peerType]/handlers.ts b/ui/app/peers/create/[peerType]/handlers.ts index 0964c80e35..e43164aa96 100644 --- a/ui/app/peers/create/[peerType]/handlers.ts +++ b/ui/app/peers/create/[peerType]/handlers.ts @@ -17,20 +17,20 @@ import { const validateFields = ( type: string, config: PeerConfig, - notify: (msg: string) => void, + setMessage: Dispatch>, name?: string ): boolean => { const peerNameValid = peerNameSchema.safeParse(name); if (!peerNameValid.success) { const peerNameErr = peerNameValid.error.issues[0].message; - notify(peerNameErr); + setMessage({ ok: false, msg: peerNameErr }); return false; } if (type === 'S3') { const s3Valid = S3Validation(config as S3Config); if (s3Valid.length > 0) { - notify(s3Valid); + setMessage({ ok: false, msg: s3Valid }); return false; } } @@ -61,9 +61,9 @@ const validateFields = ( validationErr = 'Unsupported peer type ' + type; } if (validationErr) { - notify(validationErr); + setMessage({ ok: false, msg: validationErr }); return false; - } + } else setMessage({ ok: true, msg: '' }); return true; }; @@ -71,11 +71,11 @@ const validateFields = ( export const handleValidate = async ( type: string, config: PeerConfig, - notify: (msg: string) => void, + setMessage: Dispatch>, setLoading: Dispatch>, name?: string ) => { - const isValid = validateFields(type, config, notify, name); + const isValid = validateFields(type, config, setMessage, name); if (!isValid) return; setLoading(true); const valid: UValidatePeerResponse = await fetch('/api/peers/', { @@ -89,11 +89,11 @@ export const handleValidate = async ( cache: 'no-store', }).then((res) => res.json()); if (!valid.valid) { - notify(valid.message); + setMessage({ ok: false, msg: valid.message }); setLoading(false); return; } - notify('Peer is valid'); + setMessage({ ok: true, msg: 'Peer is valid' }); setLoading(false); }; @@ -108,12 +108,12 @@ const S3Validation = (config: S3Config): string => { export const handleCreate = async ( type: string, config: PeerConfig, - notify: (msg: string) => void, + setMessage: Dispatch>, setLoading: Dispatch>, route: RouteCallback, name?: string ) => { - let isValid = validateFields(type, config, notify, name); + let isValid = validateFields(type, config, setMessage, name); if (!isValid) return; setLoading(true); const createdPeer: UCreatePeerResponse = await fetch('/api/peers/', { @@ -127,11 +127,11 @@ export const handleCreate = async ( cache: 'no-store', }).then((res) => res.json()); if (!createdPeer.created) { - notify(createdPeer.message); + setMessage({ ok: false, msg: createdPeer.message }); setLoading(false); return; } - + setMessage({ ok: true, msg: 'Peer created successfully' }); route(); setLoading(false); }; diff --git a/ui/app/peers/create/[peerType]/page.tsx b/ui/app/peers/create/[peerType]/page.tsx index 0f01d59279..b0693075b8 100644 --- a/ui/app/peers/create/[peerType]/page.tsx +++ b/ui/app/peers/create/[peerType]/page.tsx @@ -7,7 +7,6 @@ import PostgresForm from '@/components/PeerForms/PostgresForm'; import S3Form from '@/components/PeerForms/S3Form'; import SnowflakeForm from '@/components/PeerForms/SnowflakeForm'; -import TitleCase from '@/app/utils/titlecase'; import { Button } from '@/lib/Button'; import { ButtonGroup } from '@/lib/ButtonGroup'; import { Label } from '@/lib/Label'; @@ -18,8 +17,6 @@ import { Tooltip } from '@/lib/Tooltip'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { useState } from 'react'; -import { ToastContainer, toast } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.css'; import { handleCreate, handleValidate } from './handlers'; import { clickhouseSetting } from './helpers/ch'; import { getBlankSetting } from './helpers/common'; @@ -30,12 +27,6 @@ type CreateConfigProps = { params: { peerType: string }; }; -const notifyErr = (errMsg: string) => { - toast.error(errMsg, { - position: 'bottom-center', - }); -}; - export default function CreateConfig({ params: { peerType }, }: CreateConfigProps) { @@ -44,19 +35,15 @@ export default function CreateConfig({ const blankSetting = getBlankSetting(dbType); const [name, setName] = useState(''); const [config, setConfig] = useState(blankSetting); + const [formMessage, setFormMessage] = useState<{ ok: boolean; msg: string }>({ + ok: true, + msg: '', + }); const [loading, setLoading] = useState(false); const configComponentMap = (dbType: string) => { - if (dbType.includes('POSTGRESQL')) { - return ( - - ); - } - switch (dbType) { + case 'POSTGRES': + return ; case 'SNOWFLAKE': return ; case 'BIGQUERY': @@ -89,10 +76,11 @@ export default function CreateConfig({ > - + - handleValidate(dbType, config, notifyErr, setLoading, name) + handleValidate(dbType, config, setFormMessage, setLoading, name) } > Validate @@ -143,7 +131,7 @@ export default function CreateConfig({ handleCreate( dbType, config, - notifyErr, + setFormMessage, setLoading, listPeersRoute, name @@ -163,7 +151,15 @@ export default function CreateConfig({ Validating... )} - + {!loading && formMessage.msg.length > 0 && ( + + )}
diff --git a/ui/app/utils/titlecase.ts b/ui/app/utils/titlecase.ts deleted file mode 100644 index 31f262eed2..0000000000 --- a/ui/app/utils/titlecase.ts +++ /dev/null @@ -1,12 +0,0 @@ -function TitleCase(input: string): string { - return input - .toLowerCase() - .replace(/(?:^|\s)\S/g, function (char) { - return char.toUpperCase(); - }) - .replace(/Postgresql/g, 'PostgreSQL') - .replace(/Postgresql/g, 'PostgreSQL') - .replace(/Rds/g, 'RDS'); -} - -export default TitleCase; diff --git a/ui/components/PeerComponent.tsx b/ui/components/PeerComponent.tsx index 66851820ed..5b2f717cd2 100644 --- a/ui/components/PeerComponent.tsx +++ b/ui/components/PeerComponent.tsx @@ -8,12 +8,6 @@ import { useRouter } from 'next/navigation'; import { useState } from 'react'; export const DBTypeToImageMapping = (peerType: DBType | string) => { switch (peerType) { - case 'AZURE FLEXIBLE POSTGRESQL': - return '/svgs/azurepg.svg'; - case 'RDS POSTGRESQL': - return '/svgs/rds.svg'; - case 'GOOGLE CLOUD POSTGRESQL': - return '/svgs/gcp.svg'; case DBType.POSTGRES: case 'POSTGRES': return '/svgs/pg.svg'; diff --git a/ui/components/PeerForms/PostgresForm.tsx b/ui/components/PeerForms/PostgresForm.tsx index 98bef1aad2..0c7f5e808d 100644 --- a/ui/components/PeerForms/PostgresForm.tsx +++ b/ui/components/PeerForms/PostgresForm.tsx @@ -18,12 +18,12 @@ import { InfoPopover } from '../InfoPopover'; interface ConfigProps { settings: PeerSetting[]; setter: PeerSetter; - type: string; } -export default function PostgresForm({ settings, setter, type }: ConfigProps) { +export default function PostgresForm({ settings, setter }: ConfigProps) { const [showSSH, setShowSSH] = useState(false); const [sshConfig, setSSHConfig] = useState(blankSSHConfig); + const handleFile = ( file: File, setFile: (value: string, configSetter: sshSetter) => void diff --git a/ui/components/SelectSource.tsx b/ui/components/SelectSource.tsx index c445ceb21e..4aefe67082 100644 --- a/ui/components/SelectSource.tsx +++ b/ui/components/SelectSource.tsx @@ -1,6 +1,5 @@ 'use client'; import SelectTheme from '@/app/styles/select'; -import TitleCase from '@/app/utils/titlecase'; import { DBType } from '@/grpc_generated/peers'; import Image from 'next/image'; import { Dispatch, SetStateAction } from 'react'; @@ -12,12 +11,12 @@ interface SelectSourceProps { setPeerType: Dispatch>; } -function SourceLabel({ value, label }: { value: string; label: string }) { - const peerLogo = DBTypeToImageMapping(label); +function SourceLabel({ value }: { value: string }) { + const peerLogo = DBTypeToImageMapping(value); return (
peer -
{TitleCase(label)}
+
{value}
); } @@ -26,11 +25,11 @@ export default function SelectSource({ peerType, setPeerType, }: SelectSourceProps) { - let dbTypes = Object.values(DBType) + const dbTypes = Object.values(DBType) .filter( (value): value is string => typeof value === 'string' && - (value === 'POSTGRESQL' || + (value === 'POSTGRES' || value === 'SNOWFLAKE' || value === 'BIGQUERY' || value === 'S3' || @@ -38,19 +37,13 @@ export default function SelectSource({ ) .map((value) => ({ label: value, value })); - dbTypes.push( - { value: 'POSTGRESQL', label: 'POSTGRESQL' }, - { value: 'POSTGRESQL', label: 'RDS POSTGRESQL' }, - { value: 'POSTGRESQL', label: 'GOOGLE CLOUD POSTGRESQL' }, - { value: 'POSTGRESQL', label: 'AZURE FLEXIBLE POSTGRESQL' } - ); return ( opt.label === peerType)} - onChange={(val, _) => val && setPeerType(val.label)} + defaultValue={dbTypes.find((opt) => opt.value === peerType)} + onChange={(val, _) => val && setPeerType(val.value)} formatOptionLabel={SourceLabel} theme={SelectTheme} /> diff --git a/ui/public/svgs/azurepg.svg b/ui/public/svgs/azurepg.svg deleted file mode 100644 index 811a6c7397..0000000000 --- a/ui/public/svgs/azurepg.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ui/public/svgs/gcp.svg b/ui/public/svgs/gcp.svg deleted file mode 100644 index 81b7d24547..0000000000 --- a/ui/public/svgs/gcp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ui/public/svgs/rds.svg b/ui/public/svgs/rds.svg deleted file mode 100644 index f384cdad89..0000000000 --- a/ui/public/svgs/rds.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file