mirror of https://github.com/buster-so/buster.git
make add form a link
This commit is contained in:
parent
f49b4ef274
commit
4b4ed982a5
|
@ -79,6 +79,7 @@
|
|||
"ts-jest": "^29.2.6",
|
||||
"use-context-selector": "^2.0.0",
|
||||
"utility-types": "^3.11.0",
|
||||
"valibot": "^1.0.0",
|
||||
"virtua": "^0.40.3",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
|
@ -21322,6 +21323,20 @@
|
|||
"node": ">=10.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/valibot": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0.tgz",
|
||||
"integrity": "sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"typescript": ">=5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vfile": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
"ts-jest": "^29.2.6",
|
||||
"use-context-selector": "^2.0.0",
|
||||
"utility-types": "^3.11.0",
|
||||
"valibot": "^1.0.0",
|
||||
"virtua": "^0.40.3",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
import type { DataSource, DataSourceListItem } from '@/api/asset_interfaces/datasources';
|
||||
import type {
|
||||
BigQueryCredentials,
|
||||
DatabricksCredentials,
|
||||
DataSource,
|
||||
DataSourceListItem,
|
||||
MySQLCredentials,
|
||||
PostgresCredentials,
|
||||
SnowflakeCredentials,
|
||||
SQLServerCredentials
|
||||
} from '@/api/asset_interfaces/datasources';
|
||||
import mainApi from '../instances';
|
||||
import { DatasourceUpdateParams } from '@/api/request_interfaces/datasources';
|
||||
import {
|
||||
DatasourceUpdateParams,
|
||||
RedshiftCreateCredentials
|
||||
} from '@/api/request_interfaces/datasources';
|
||||
import { MySQLCreateParams } from './types';
|
||||
|
||||
export const listDatasources = async () => {
|
||||
return await mainApi.get<DataSourceListItem[]>('/data_sources').then((res) => res.data);
|
||||
|
@ -14,16 +27,7 @@ export const deleteDatasource = async (id: string) => {
|
|||
return await mainApi.delete(`/data_sources/${id}`).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const createPostgresDataSource = async (params: {
|
||||
name: string;
|
||||
type: 'postgres' | 'supabase';
|
||||
host: string;
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
default_database: string; //postgres
|
||||
default_schema: string; //public
|
||||
}) => {
|
||||
export const createPostgresDataSource = async (params: PostgresCredentials) => {
|
||||
return mainApi.post<DataSource>('/data_sources', params).then((res) => res.data);
|
||||
};
|
||||
|
||||
|
@ -34,15 +38,7 @@ export const updatePostgresDataSource = async ({
|
|||
return mainApi.put<DataSource>(`/data_sources/${id}`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const createMySQLDataSource = async (params: {
|
||||
name: string;
|
||||
type: 'mysql' | 'mariadb';
|
||||
host: string;
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
default_database: string;
|
||||
}) => {
|
||||
export const createMySQLDataSource = async (params: MySQLCredentials) => {
|
||||
return mainApi.post<DataSource>('/data_sources', params).then((res) => res.data);
|
||||
};
|
||||
|
||||
|
@ -53,16 +49,7 @@ export const updateMySQLDataSource = async ({
|
|||
return mainApi.put<DataSource>(`/data_sources/${id}`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const createRedshiftDataSource = async (params: {
|
||||
name: string;
|
||||
type: 'redshift';
|
||||
host: string;
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
default_database: string;
|
||||
default_schema: string;
|
||||
}) => {
|
||||
export const createRedshiftDataSource = async (params: RedshiftCreateCredentials) => {
|
||||
return mainApi.post<DataSource>('/data_sources', params).then((res) => res.data);
|
||||
};
|
||||
|
||||
|
@ -73,13 +60,7 @@ export const updateRedshiftDataSource = async ({
|
|||
return mainApi.put<DataSource>(`/data_sources/${id}`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const createBigQueryDataSource = async (params: {
|
||||
name: string;
|
||||
type: 'bigquery';
|
||||
service_role_key: string;
|
||||
default_project_id: string;
|
||||
default_dataset_id: string;
|
||||
}) => {
|
||||
export const createBigQueryDataSource = async (params: BigQueryCredentials) => {
|
||||
return mainApi.post<DataSource>('/data_sources', params).then((res) => res.data);
|
||||
};
|
||||
|
||||
|
@ -90,17 +71,7 @@ export const updateBigQueryDataSource = async ({
|
|||
return mainApi.put<DataSource>(`/data_sources/${id}`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const createSnowflakeDataSource = async (params: {
|
||||
name: string;
|
||||
type: 'snowflake';
|
||||
account_id: string;
|
||||
warehouse_id: string;
|
||||
username: string;
|
||||
password: string;
|
||||
role: string | null;
|
||||
default_database: string;
|
||||
default_schema: string;
|
||||
}) => {
|
||||
export const createSnowflakeDataSource = async (params: SnowflakeCredentials) => {
|
||||
return mainApi.post<DataSource>('/data_sources', params).then((res) => res.data);
|
||||
};
|
||||
|
||||
|
@ -111,15 +82,7 @@ export const updateSnowflakeDataSource = async ({
|
|||
return mainApi.put<DataSource>(`/data_sources/${id}`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const createDatabricksDataSource = async (params: {
|
||||
name: string;
|
||||
type: 'databricks';
|
||||
host: string;
|
||||
api_key: string;
|
||||
warehouse_id: string;
|
||||
default_catalog: string;
|
||||
default_schema: string;
|
||||
}) => {
|
||||
export const createDatabricksDataSource = async (params: DatabricksCredentials) => {
|
||||
return mainApi.post<DataSource>('/data_sources', params).then((res) => res.data);
|
||||
};
|
||||
|
||||
|
@ -130,16 +93,7 @@ export const updateDatabricksDataSource = async ({
|
|||
return mainApi.put<DataSource>(`/data_sources/${id}`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const createSQLServerDataSource = async (params: {
|
||||
name: string;
|
||||
type: 'sqlserver';
|
||||
host: string;
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
default_database: string;
|
||||
default_schema: string;
|
||||
}) => {
|
||||
export const createSQLServerDataSource = async (params: SQLServerCredentials) => {
|
||||
return mainApi.post<DataSource>('/data_sources', params).then((res) => res.data);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import type { DataSource, DataSourceTypes } from '@/api/asset_interfaces';
|
||||
import { DatabaseNames, type DataSource, type DataSourceTypes } from '@/api/asset_interfaces';
|
||||
import React from 'react';
|
||||
import { PostgresForm } from './PostgresForm';
|
||||
import { MySqlForm } from './MySqlForm';
|
||||
|
@ -9,6 +9,8 @@ import { SnowflakeForm } from './SnowflakeForm';
|
|||
import { RedshiftForm } from './RedshiftForm';
|
||||
import { DataBricksForm } from './DataBricksForm';
|
||||
import { SqlServerForm } from './SqlServerForm';
|
||||
import { AppDataSourceIcon } from '@/components/ui/icons/AppDataSourceIcons';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
|
||||
const FormRecord: Record<
|
||||
DataSourceTypes,
|
||||
|
@ -32,14 +34,19 @@ const FormRecord: Record<
|
|||
export const DataSourceFormContent: React.FC<{
|
||||
dataSource?: DataSource;
|
||||
type: DataSourceTypes;
|
||||
}> = ({ dataSource, type }) => {
|
||||
}> = React.memo(({ dataSource, type }) => {
|
||||
const SelectedForm = FormRecord[type];
|
||||
const DatabaseName = DatabaseNames[type];
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border">
|
||||
<div className="bg-item-hover flex items-center px-4 py-2.5">Datasource credentials</div>
|
||||
<div className="overflow-hidden rounded-lg border shadow">
|
||||
<div className="bg-item-hover flex items-center space-x-2 px-4 py-2.5">
|
||||
<Text>{`${DatabaseName} credentials`}</Text>
|
||||
</div>
|
||||
|
||||
<div className="p-4">{SelectedForm && <SelectedForm dataSource={dataSource} />}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
DataSourceFormContent.displayName = 'DataSourceFormContent';
|
||||
|
|
|
@ -30,7 +30,7 @@ export const SnowflakeForm: React.FC<{
|
|||
warehouse_id: credentials?.warehouse_id || '',
|
||||
username: credentials?.username || '',
|
||||
password: credentials?.password || '',
|
||||
role: credentials?.role || null,
|
||||
role: credentials?.role || '',
|
||||
default_database: credentials?.default_database || '',
|
||||
default_schema: credentials?.default_schema || '',
|
||||
type: 'snowflake' as const,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||
import { HeaderContainer } from '../../_HeaderContainer';
|
||||
import { useState } from 'react';
|
||||
|
@ -10,22 +10,44 @@ import { Title, Text } from '@/components/ui/typography';
|
|||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
import { AppDataSourceIcon } from '@/components/ui/icons/AppDataSourceIcons';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Page() {
|
||||
const [selectedDataSource, setSelectedDataSource] = useState<DataSourceTypes | null>(null);
|
||||
const { openInfoMessage } = useBusterNotifications();
|
||||
export default function Page({
|
||||
searchParams: { type }
|
||||
}: {
|
||||
searchParams: { type?: DataSourceTypes };
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [selectedDataSource, setSelectedDataSource] = useState<DataSourceTypes | null>(
|
||||
type || null
|
||||
);
|
||||
|
||||
const linkUrl = selectedDataSource
|
||||
? ''
|
||||
? createBusterRoute({
|
||||
route: BusterRoutes.SETTINGS_DATASOURCES_ADD
|
||||
})
|
||||
: createBusterRoute({
|
||||
route: BusterRoutes.SETTINGS_DATASOURCES
|
||||
});
|
||||
|
||||
const onClearSelectedDataSource = useMemoizedFn(() => {
|
||||
setSelectedDataSource(null);
|
||||
router.push(createBusterRoute({ route: BusterRoutes.SETTINGS_DATASOURCES_ADD }));
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (type) {
|
||||
setSelectedDataSource(type);
|
||||
}
|
||||
}, [type]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-5">
|
||||
<HeaderContainer
|
||||
buttonText={selectedDataSource ? 'Connect a datasource' : 'Datasources'}
|
||||
onClick={() => setSelectedDataSource(null)}
|
||||
onClick={onClearSelectedDataSource}
|
||||
linkUrl={linkUrl}
|
||||
/>
|
||||
|
||||
|
@ -34,15 +56,7 @@ export default function Page() {
|
|||
) : (
|
||||
<div className="flex flex-col space-y-6">
|
||||
<ConnectHeader />
|
||||
<DataSourceList
|
||||
onSelect={(v) => {
|
||||
if (SUPPORTED_DATASOURCES.includes(v)) {
|
||||
setSelectedDataSource(v);
|
||||
} else {
|
||||
openInfoMessage('This data source is not currently supported');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<DataSourceList />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -58,25 +72,27 @@ const ConnectHeader: React.FC<{}> = ({}) => {
|
|||
);
|
||||
};
|
||||
|
||||
const DataSourceList: React.FC<{
|
||||
onSelect: (dataSource: DataSourceTypes) => void;
|
||||
}> = ({ onSelect }) => {
|
||||
const DataSourceList: React.FC<{}> = ({}) => {
|
||||
return (
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
{Object.values(DataSourceTypes).map((dataSource) => {
|
||||
{SUPPORTED_DATASOURCES.map((dataSource) => {
|
||||
const name = DatabaseNames[dataSource];
|
||||
return (
|
||||
<div
|
||||
onClick={() => onSelect(dataSource)}
|
||||
<Link
|
||||
href={
|
||||
createBusterRoute({
|
||||
route: BusterRoutes.SETTINGS_DATASOURCES_ADD
|
||||
}) + `?type=${dataSource}`
|
||||
}
|
||||
key={dataSource}
|
||||
className={cn(
|
||||
'flex cursor-pointer items-center space-x-4 px-4 py-3 transition',
|
||||
'flex cursor-pointer items-center space-x-4 px-4 py-3 shadow transition',
|
||||
'bg-background hover:bg-item-hover',
|
||||
'border-border max-h-[48px] rounded border'
|
||||
)}>
|
||||
<AppDataSourceIcon size={28} type={dataSource} />
|
||||
<Text>{name}</Text>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue