Skip to content

Commit

Permalink
Athena: Pre-select first catalog and database (#3949)
Browse files Browse the repository at this point in the history
  • Loading branch information
fiskus authored Apr 18, 2024
1 parent 147abcd commit ad9db41
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 37 deletions.
61 changes: 39 additions & 22 deletions catalog/app/containers/Bucket/Queries/Athena/Athena.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ import Results from './Results'
import History from './History'
import Workgroups from './Workgroups'

interface QuerySelectSkeletonProps {
className?: string
}

function QuerySelectSkeleton({ className }: QuerySelectSkeletonProps) {
return (
<div className={className}>
<Skeleton height={24} width={128} animate />
<Skeleton height={48} mt={1} animate />
</div>
)
}

const useAthenaQueriesStyles = M.makeStyles((t) => ({
form: {
margin: t.spacing(3, 0, 0),
Expand Down Expand Up @@ -77,12 +90,7 @@ function QueryConstructor({
</Section>
),
Err: makeAsyncDataErrorHandler('Select query'),
_: () => (
<>
<Skeleton height={24} width={128} animate />
<Skeleton height={48} mt={1} animate />
</>
),
_: () => <QuerySelectSkeleton />,
})}
<QueryEditor.Form
bucket={bucket}
Expand All @@ -95,6 +103,16 @@ function QueryConstructor({
)
}

function QueryConstructorSkeleton() {
const classes = useStyles()
return (
<>
<QuerySelectSkeleton className={classes.section} />
<QueryEditor.Skeleton className={classes.section} />
</>
)
}

interface HistoryContainerProps {
bucket: string
className: string
Expand Down Expand Up @@ -326,15 +344,22 @@ interface AthenaMainProps {

function AthenaMain({ bucket, workgroup }: AthenaMainProps) {
const classes = useStyles()
const data = requests.athena.useDefaultQueryExecution()
return (
<div className={classes.content}>
<QueryConstructor
bucket={bucket}
className={classes.section}
key={workgroup}
workgroup={workgroup}
/>

{data.case({
Ok: (queryExecution) => (
<QueryConstructor
bucket={bucket}
className={classes.section}
key={workgroup}
workgroup={workgroup}
initialValue={queryExecution}
/>
),
Err: makeAsyncDataErrorHandler('Default catalog and database'),
_: () => <QueryConstructorSkeleton />,
})}
<HistoryContainer
bucket={bucket}
className={classes.section}
Expand Down Expand Up @@ -364,15 +389,7 @@ function AthenaExecution({ bucket, workgroup, queryExecutionId }: AthenaExecutio
workgroup={workgroup}
/>
),
_: () => (
<>
<div className={classes.section}>
<Skeleton height={24} width={128} animate />
<Skeleton height={48} mt={1} animate mb={3} />
</div>
<QueryEditor.Skeleton className={classes.section} />
</>
),
_: () => <QueryConstructorSkeleton />,
})}

{results.data.case({
Expand Down
41 changes: 27 additions & 14 deletions catalog/app/containers/Bucket/Queries/Athena/Database.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ interface SelectProps {
label: string
onChange: (value: string) => void
onLoadMore: (prev: Response) => void
value: string | null
}

function Select({ data, label, onChange, onLoadMore }: SelectProps) {
function Select({ data, label, onChange, onLoadMore, value }: SelectProps) {
const classes = useSelectStyles()
const handleChange = React.useCallback(
(event) => {
const { value } = event.target
if (value === LOAD_MORE) {
if (event.target.value === LOAD_MORE) {
onLoadMore(data)
} else {
onChange(value)
onChange(event.target.value)
}
},
[data, onLoadMore, onChange],
Expand All @@ -61,10 +61,10 @@ function Select({ data, label, onChange, onLoadMore }: SelectProps) {
return (
<M.FormControl className={classes.root}>
<M.InputLabel>{label}</M.InputLabel>
<M.Select onChange={handleChange}>
{data.list.map((value) => (
<M.MenuItem key={value} value={value}>
{value}
<M.Select onChange={handleChange} value={value?.toLowerCase()}>
{data.list.map((item) => (
<M.MenuItem key={item} value={item.toLowerCase()}>
{item}
</M.MenuItem>
))}
{data.next && <M.MenuItem value={LOAD_MORE}>Load more</M.MenuItem>}
Expand All @@ -74,10 +74,11 @@ function Select({ data, label, onChange, onLoadMore }: SelectProps) {
}

interface SelectCatalogNameProps {
onChange: (catalogName: string) => void
value: requests.athena.CatalogName | null
onChange: (catalogName: requests.athena.CatalogName) => void
}

function SelectCatalogName({ onChange }: SelectCatalogNameProps) {
function SelectCatalogName({ value, onChange }: SelectCatalogNameProps) {
const [prev, setPrev] = React.useState<requests.athena.CatalogNamesResponse | null>(
null,
)
Expand All @@ -89,6 +90,7 @@ function SelectCatalogName({ onChange }: SelectCatalogNameProps) {
label="Data catalog"
onChange={onChange}
onLoadMore={setPrev}
value={value}
/>
),
Err: (error) => <SelectError error={error} />,
Expand All @@ -99,14 +101,21 @@ function SelectCatalogName({ onChange }: SelectCatalogNameProps) {
interface SelectDatabaseProps {
catalogName: requests.athena.CatalogName | null
onChange: (database: requests.athena.Database) => void
value: requests.athena.Database | null
}

function SelectDatabase({ catalogName, onChange }: SelectDatabaseProps) {
function SelectDatabase({ catalogName, onChange, value }: SelectDatabaseProps) {
const [prev, setPrev] = React.useState<requests.athena.DatabasesResponse | null>(null)
const data = requests.athena.useDatabases(catalogName, prev)
return data.case({
Ok: (response) => (
<Select data={response} label="Database" onChange={onChange} onLoadMore={setPrev} />
<Select
data={response}
label="Database"
onChange={onChange}
onLoadMore={setPrev}
value={value}
/>
),
Err: (error) => <SelectError error={error} />,
_: () => <SelectSkeleton />,
Expand Down Expand Up @@ -146,11 +155,15 @@ function Dialog({ initialValue, open, onChange, onClose }: DialogProps) {
<M.DialogTitle>Select data catalog and database</M.DialogTitle>
<M.DialogContent>
<div className={classes.select}>
<SelectCatalogName onChange={setCatalogName} />
<SelectCatalogName onChange={setCatalogName} value={catalogName} />
</div>
{catalogName && (
<div className={classes.select}>
<SelectDatabase catalogName={catalogName} onChange={setDatabase} />
<SelectDatabase
catalogName={catalogName}
onChange={setDatabase}
value={database}
/>
</div>
)}
</M.DialogContent>
Expand Down
29 changes: 28 additions & 1 deletion catalog/app/containers/Bucket/Queries/requests/athena.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ export interface DatabasesResponse {
interface DatabasesArgs {
athena: Athena
catalogName: CatalogName
prev: DatabasesResponse
prev?: DatabasesResponse
}

async function fetchDatabases({
Expand Down Expand Up @@ -495,6 +495,33 @@ export function useDatabases(
)
}

interface DefaultDatabaseArgs {
athena: Athena
}

async function fetchDefaultQueryExecution({
athena,
}: DefaultDatabaseArgs): Promise<QueryExecution | null> {
const catalogNames = await fetchCatalogNames({ athena })
if (!catalogNames.list.length) {
return null
}
const catalogName = catalogNames.list[0]
const databases = await fetchDatabases({ athena, catalogName })
if (!databases.list.length) {
return null
}
return {
catalog: catalogName,
db: databases.list[0],
}
}

export function useDefaultQueryExecution(): AsyncData<QueryExecution> {
const athena = AWS.Athena.use()
return useData(fetchDefaultQueryExecution, { athena })
}

export interface ExecutionContext {
catalogName: CatalogName
database: Database
Expand Down
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Entries inside each section should be ordered by type:

## Catalog, Lambdas
* [Added] Sign URL in undocumented `compressedIndexURL` IGV property ([#3947](https://github.com/quiltdata/quilt/pull/3947))
* [Changed] Pre-select first catalog and database for Athena ([#3949](https://github.com/quiltdata/quilt/pull/3949))

# 6.0.0a2 - 2024-04-15
## Python API
Expand Down

0 comments on commit ad9db41

Please sign in to comment.