From 79c5bb9788dd351affedbcd95aeda4da695a97db Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Tue, 4 Jun 2024 17:02:47 +0800 Subject: [PATCH] [Dashboard] Data API on/off switch (#26796) * init layouts in project settings * Update general.tsx * update gap * Update Scaffold.tsx * Update PostgrestConfig.tsx * Update PostgrestConfig.tsx * spacing issues * now added a enabled switch * Revert "now added a enabled switch" This reverts commit f22050302aa339c23b59cf008ee9b4fdc0e3c2b7. * Update PostgrestConfig.tsx * Update PostgrestConfig.tsx * revert * Update project-postgrest-config-update-mutation.ts * add bottom padding * Update PostgrestConfig.tsx * Update PostgrestConfig.tsx * fix * Update PostgrestConfig.tsx * Update PostgrestConfig.tsx * Update PostgrestConfig.tsx * Update PostgrestConfig.tsx * Update PostgrestConfig.tsx * add collapible * update FormPanel component to be more composable * Update PostgrestConfig.tsx * Update PostgrestConfig.tsx * update callout to warning variant * Update FormLayout.tsx * Update PostgrestConfig.tsx * Small copy changes --------- Co-authored-by: Joshen Lim --- .../SQLEditor/OngoingQueriesPanel.tsx | 9 +- .../Settings/API/PostgrestConfig.tsx | 546 +++++++++++------- apps/studio/components/ui/Forms/FormPanel.tsx | 70 ++- packages/config/tailwind.config.js | 10 + packages/ui-patterns/admonition.tsx | 22 +- .../ui-patterns/form/Layout/FormLayout.tsx | 2 +- .../ui-patterns/multi-select/multi-select.tsx | 11 +- 7 files changed, 436 insertions(+), 234 deletions(-) diff --git a/apps/studio/components/interfaces/SQLEditor/OngoingQueriesPanel.tsx b/apps/studio/components/interfaces/SQLEditor/OngoingQueriesPanel.tsx index 34eba6240e1..898b5679f3b 100644 --- a/apps/studio/components/interfaces/SQLEditor/OngoingQueriesPanel.tsx +++ b/apps/studio/components/interfaces/SQLEditor/OngoingQueriesPanel.tsx @@ -100,7 +100,14 @@ export const OngoingQueriesPanel = ({ visible, onClose }: OngoingQueriesPanel) = )} {queries.length === 0 && (
- No ongoing queries running on database + + No queries are currently running on the{' '} + {database?.identifier !== project?.ref + ? `read replica ${database?.identifier}` + : (databases ?? []).length > 1 + ? 'primary database' + : 'database'} + + + )} + + } + /> + )} + + + )} + /> + + ( + + + + + + + + )} + /> + + ( + + + + + + + + )} + /> + + ( + + + + + field.onChange( + e.target.value === '' ? null : Number(e.target.value) + ) + } + value={field.value === null ? '' : field.value} + /> + + + + )} + /> + + + + )} + { : undefined } /> -
- } - > - {isError ? ( - - ) : ( - <> - ( - - - {isLoadingSchemas ? ( -
- -
- ) : ( - - - - - - - {schema.map((x, i) => ( - - {x.name} - - ))} - - - - )} - - {!field.value.includes('public') && ( - - <> -

- You will not be able to query tables and views in the{' '} - public schema via supabase-js or HTTP clients. -

- {isGraphqlExtensionEnabled && ( - <> -

- Tables in the public schema are - still exposed over our GraphQL endpoints. -

- - - )} - -
- )} -
-
- )} - /> - - ( - - - - - - - - )} - /> - - ( - - - - - - - - )} - /> - - ( - - - - - field.onChange(e.target.value === '' ? null : Number(e.target.value)) - } - value={field.value === null ? '' : field.value} - /> - - - - )} - /> - - )} - + + + ) diff --git a/apps/studio/components/ui/Forms/FormPanel.tsx b/apps/studio/components/ui/Forms/FormPanel.tsx index a2a58fe81d0..d16420c94b8 100644 --- a/apps/studio/components/ui/Forms/FormPanel.tsx +++ b/apps/studio/components/ui/Forms/FormPanel.tsx @@ -1,3 +1,6 @@ +import { HTMLAttributes, forwardRef } from 'react' +import { cn } from 'ui' + interface Props { children: React.ReactNode header?: React.ReactNode @@ -9,22 +12,55 @@ interface Props { } const FormPanel = ({ children, header, footer }: Props) => ( -
- {header &&
{header}
} -
{children}
- {footer && ( - <> -
- {footer} - - )} -
+ + {header && {header}} + {children} + {footer && {footer}} + ) -export { FormPanel } +const FormPanelContainer = forwardRef>( + ({ children, ...props }, ref) => ( +
+ {children} +
+ ) +) + +FormPanelContainer.displayName = FormPanelContainer.displayName + +const FormPanelHeader = forwardRef>( + ({ children, ...props }, ref) => ( +
+ {children} +
+ ) +) + +FormPanelHeader.displayName = FormPanelHeader.displayName + +const FormPanelContent = forwardRef>( + ({ children, ...props }, ref) => ( +
+ {children} +
+ ) +) + +FormPanelContent.displayName = FormPanelContent.displayName + +const FormPanelFooter = forwardRef>( + ({ children, ...props }, ref) => ( +
+ {children} +
+ ) +) + +FormPanelFooter.displayName = FormPanelFooter.displayName + +export { FormPanel, FormPanelContainer, FormPanelContent, FormPanelHeader, FormPanelFooter } diff --git a/packages/config/tailwind.config.js b/packages/config/tailwind.config.js index 50803243ff0..7e5f9a0fa0e 100644 --- a/packages/config/tailwind.config.js +++ b/packages/config/tailwind.config.js @@ -380,12 +380,22 @@ const uiConfig = ui({ from: { height: 'var(--radix-accordion-content-height)' }, to: { height: 0 }, }, + 'collapsible-down': { + from: { height: 0 }, + to: { height: 'var(--radix-collapsible-content-height)' }, + }, + 'collapsible-up': { + from: { height: 'var(--radix-collapsible-content-height)' }, + to: { height: 0 }, + }, }, animation: { 'flash-code': 'flash-code 1s forwards', 'flash-code-slow': 'flash-code 2s forwards', 'accordion-down': 'accordion-down 0.15s ease-out', 'accordion-up': 'accordion-up 0.15s ease-out', + 'collapsible-down': 'collapsible-down 0.10s ease-out', + 'collapsible-up': 'collapsible-up 0.10s ease-out', }, borderRadius: { // lg: `var(--radius)`, diff --git a/packages/ui-patterns/admonition.tsx b/packages/ui-patterns/admonition.tsx index 225e414a45b..38f5f067434 100644 --- a/packages/ui-patterns/admonition.tsx +++ b/packages/ui-patterns/admonition.tsx @@ -17,6 +17,10 @@ export interface AdmonitionProps { title?: string description?: string | React.ReactNode showIcon?: boolean + childProps?: { + title?: React.ComponentProps + description?: React.ComponentProps + } } const admonitionToAlertMapping: Record< @@ -113,17 +117,29 @@ export const Admonition = forwardRef< {label || title ? ( <> {label || title} - {description && {description}} + {description && ( + + {description} + + )} {/* // children is to handle Docs and MDX issues with children and

elements */} {children && ( - + {children} )} diff --git a/packages/ui-patterns/form/Layout/FormLayout.tsx b/packages/ui-patterns/form/Layout/FormLayout.tsx index cd0f95b2f06..713ab2a026e 100644 --- a/packages/ui-patterns/form/Layout/FormLayout.tsx +++ b/packages/ui-patterns/form/Layout/FormLayout.tsx @@ -26,7 +26,7 @@ type Props = { name?: string } -const ContainerVariants = cva('grid gap-2', { +const ContainerVariants = cva('relative grid gap-2', { variants: { size: { tiny: 'text-xs', diff --git a/packages/ui-patterns/multi-select/multi-select.tsx b/packages/ui-patterns/multi-select/multi-select.tsx index a993f9a9e37..9c99c467001 100644 --- a/packages/ui-patterns/multi-select/multi-select.tsx +++ b/packages/ui-patterns/multi-select/multi-select.tsx @@ -43,6 +43,7 @@ type MultiSelectorProps = { values: string[] onValuesChange: (value: string[]) => void loop?: boolean + disabled?: boolean } & React.ComponentPropsWithoutRef & VariantProps @@ -56,6 +57,7 @@ interface MultiSelectContextProps { activeIndex: number setActiveIndex: React.Dispatch> size: MultiSelectorProps['size'] + disabled?: boolean } const MultiSelectContext = createContext(null) @@ -76,6 +78,7 @@ const MultiSelector = ({ children, dir, size = 'small', + disabled, ...props }: MultiSelectorProps) => { const [inputValue, setInputValue] = useState('') @@ -154,6 +157,7 @@ const MultiSelector = ({ activeIndex, setActiveIndex, size: size || 'small', + disabled, }} > ( ({ className, children, ...props }, ref) => { - const { value, onValueChange, activeIndex, size } = useMultiSelect() + const { value, onValueChange, activeIndex, size, disabled } = useMultiSelect() const mousePreventDefault = useCallback((e: React.MouseEvent) => { e.preventDefault() @@ -214,6 +218,7 @@ const MultiSelectorTrigger = forwardRef( ref={ref} className={cn( 'flex flex-wrap gap-1 border border-control bg-foreground/[.026] rounded-lg px-1', + disabled && 'cursor-not-allowed opacity-50', className )} {...props} @@ -264,7 +269,8 @@ const MultiSelectorInput = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => { - const { setOpen, inputValue, setInputValue, activeIndex, setActiveIndex, size } = useMultiSelect() + const { setOpen, inputValue, setInputValue, activeIndex, setActiveIndex, size, disabled } = + useMultiSelect() return ( setOpen(false)} onFocus={() => setOpen(true)} onClick={() => setActiveIndex(-1)} + disabled={disabled} className={cn( MultiSelectorInputVariants({ size }), 'text-sm bg-transparent border-none outline-none placeholder:text-foreground-muted flex-1',