diff --git a/studio/.prettierignore b/studio/.prettierignore new file mode 100644 index 00000000000..b74a8bc8f9f --- /dev/null +++ b/studio/.prettierignore @@ -0,0 +1,6 @@ +.expo +.next +node_modules +package-lock.json +docker* +apps/**/out diff --git a/studio/.prettierrc b/studio/.prettierrc new file mode 100644 index 00000000000..76c3f65353b --- /dev/null +++ b/studio/.prettierrc @@ -0,0 +1,8 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 100, + "endOfLine": "lf" +} diff --git a/studio/components/grid/components/common/BlockKeys.tsx b/studio/components/grid/components/common/BlockKeys.tsx index a78eefb17d6..4a8007326c8 100644 --- a/studio/components/grid/components/common/BlockKeys.tsx +++ b/studio/components/grid/components/common/BlockKeys.tsx @@ -1,45 +1,40 @@ -import * as React from 'react'; +import * as React from 'react' type BlockKeysProps = { - onEscape?: (value: string | null) => void; - onEnter?: (value: string | null) => void; - value: string | null; -}; + onEscape?: (value: string | null) => void + onEnter?: (value: string | null) => void + value: string | null +} /** * Blocks key events from propagating * We use this with cell editor to allow editor component to handle keys. * Example: press enter to add newline on textEditor */ -export const BlockKeys: React.FC = ({ - onEscape, - onEnter, - value, - children, -}) => { +export const BlockKeys: React.FC = ({ onEscape, onEnter, value, children }) => { const handleKeyDown = React.useCallback( (ev: React.KeyboardEvent) => { switch (ev.key) { case 'Escape': - ev.stopPropagation(); - if (onEscape) onEscape(value); - break; + ev.stopPropagation() + if (onEscape) onEscape(value) + break case 'Enter': - ev.stopPropagation(); - if (onEnter) onEnter(value); - break; + ev.stopPropagation() + if (onEnter) onEnter(value) + break } }, [value] - ); + ) function onBlur() { - if (onEscape) onEscape(value); + if (onEscape) onEscape(value) } return (
{children}
- ); -}; + ) +} diff --git a/studio/components/grid/components/common/DropdownControl.tsx b/studio/components/grid/components/common/DropdownControl.tsx index 0a00a4d2436..c37b2c9dd84 100644 --- a/studio/components/grid/components/common/DropdownControl.tsx +++ b/studio/components/grid/components/common/DropdownControl.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import { Dropdown, Typography } from '@supabase/ui'; +import * as React from 'react' +import { Dropdown, Typography } from '@supabase/ui' type DropdownControlProps = { options: { - value: string | number; - label: string; - postLabel?: string; - preLabel?: string; - }[]; - onSelect: (value: string | number) => void; - className?: string; - side?: 'bottom' | 'left' | 'top' | 'right' | undefined; - align?: 'start' | 'center' | 'end' | undefined; - isNested?: boolean; -}; + value: string | number + label: string + postLabel?: string + preLabel?: string + }[] + onSelect: (value: string | number) => void + className?: string + side?: 'bottom' | 'left' | 'top' | 'right' | undefined + align?: 'start' | 'center' | 'end' | undefined + isNested?: boolean +} export const DropdownControl: React.FC = (p) => { - const { className, children, side, align, isNested } = p; + const { className, children, side, align, isNested } = p return ( = (p) => { > {children} - ); -}; + ) +} -const DropdownItems: React.FC = ({ - options, - onSelect, -}) => { +const DropdownItems: React.FC = ({ options, onSelect }) => { return (
{options.length == 0 && ( - - No more items - + No more items )} {options.map((x) => { return ( onSelect(x.value)}>
- {x.preLabel && ( - - {x.preLabel} - - )} + {x.preLabel && {x.preLabel}} {x.label} - {x.postLabel && ( - {x.postLabel} - )} + {x.postLabel && {x.postLabel}}
- ); + ) })}
- ); -}; + ) +} diff --git a/studio/components/grid/components/common/EmptyValue.tsx b/studio/components/grid/components/common/EmptyValue.tsx index 1a32e29aaf5..d5f7b7d13c7 100644 --- a/studio/components/grid/components/common/EmptyValue.tsx +++ b/studio/components/grid/components/common/EmptyValue.tsx @@ -1,11 +1,11 @@ -import * as React from 'react'; +import * as React from 'react' -type EmptyValueProps = {}; +type EmptyValueProps = {} export const EmptyValue: React.FC = ({}) => { return ( EMPTY - ); -}; + ) +} diff --git a/studio/components/grid/components/common/ForeignTableModal/RowItem.tsx b/studio/components/grid/components/common/ForeignTableModal/RowItem.tsx index 81e65eb660f..8a0296bc6ab 100644 --- a/studio/components/grid/components/common/ForeignTableModal/RowItem.tsx +++ b/studio/components/grid/components/common/ForeignTableModal/RowItem.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import { Menu, Typography } from '@supabase/ui'; -import { Dictionary } from '../../../types'; +import * as React from 'react' +import { Menu, Typography } from '@supabase/ui' +import { Dictionary } from '../../../types' interface RowItemProps { - item: Dictionary; - onSelect: (item: Dictionary) => void; - columnNames: string[], + item: Dictionary + onSelect: (item: Dictionary) => void + columnNames: string[] } export const RowItem: React.FC = ({ item, onSelect, columnNames }) => { return (
- onSelect(item)} style={{minWidth: 'min-content'}}> + onSelect(item)} style={{ minWidth: 'min-content' }}>
{columnNames.map((key, j) => { // @@ -19,13 +19,10 @@ export const RowItem: React.FC = ({ item, onSelect, columnNames }) // // this could be improved so the user could pick which attributes to display // @mildtomato - if (j > 5) return null; + if (j > 5) return null return ( -
+
= ({ item, onSelect, columnNames }) {key} - {item[key] ? (typeof item[key] === 'object') ? JSON.stringify(item[key]) : item[key] : '[null]'} + {item[key] + ? typeof item[key] === 'object' + ? JSON.stringify(item[key]) + : item[key] + : '[null]'}
- ); + ) })}
- ); -}; + ) +} diff --git a/studio/components/grid/components/common/Hooks.tsx b/studio/components/grid/components/common/Hooks.tsx index 2efd87710be..b1d6ef0f778 100644 --- a/studio/components/grid/components/common/Hooks.tsx +++ b/studio/components/grid/components/common/Hooks.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; +import * as React from 'react' function includes(array: string[], element: string) { - return array.indexOf(element) >= 0; + return array.indexOf(element) >= 0 } /** @@ -19,7 +19,7 @@ export function useKeyboardShortcuts( whitelistNodes: string[] = [], whitelistClasses: string[] = [] ) { - const [lastKeydown, setLastKeydown] = React.useState(); + const [lastKeydown, setLastKeydown] = React.useState() const handleKeydown = (event: any) => { if ( @@ -27,10 +27,10 @@ export function useKeyboardShortcuts( includes(whitelistNodes, event.target.nodeName) || includes(whitelistClasses, event.target.className) ) { - return; + return } - let keyPressed = getKeyPresses(event); + let keyPressed = getKeyPresses(event) if (keyMap[keyPressed]) { /** @@ -38,25 +38,25 @@ export function useKeyboardShortcuts( * while single keymap will trigger action on KeyUp event */ if (keyPressed.includes('+')) { - event.preventDefault(); - keyMap[keyPressed](event); - setLastKeydown(null); + event.preventDefault() + keyMap[keyPressed](event) + setLastKeydown(null) } else { - setLastKeydown(event.key); - event.preventDefault(); + setLastKeydown(event.key) + event.preventDefault() } } - }; + } const handleKeyup = (event: any) => { - if (!keyMap) return; + if (!keyMap) return if (keyMap[event.key] && lastKeydown === event.key) { - event.preventDefault(); - keyMap[event.key](event); - setLastKeydown(null); + event.preventDefault() + keyMap[event.key](event) + setLastKeydown(null) } - }; + } function getKeyPresses(event: KeyboardEvent) { return event.metaKey && event.shiftKey @@ -67,15 +67,15 @@ export function useKeyboardShortcuts( ? `Shift+${event.key}` : event.ctrlKey && event.key ? `Control+${event.key}` - : event.key; + : event.key } React.useEffect(() => { - window.addEventListener('keydown', handleKeydown); - window.addEventListener('keyup', handleKeyup); + window.addEventListener('keydown', handleKeydown) + window.addEventListener('keyup', handleKeyup) return () => { - window.removeEventListener('keydown', handleKeydown); - window.removeEventListener('keyup', handleKeyup); - }; - }); + window.removeEventListener('keydown', handleKeydown) + window.removeEventListener('keyup', handleKeyup) + } + }) } diff --git a/studio/components/grid/components/common/MonacoEditor.tsx b/studio/components/grid/components/common/MonacoEditor.tsx index 8ec385d0ce7..f1cf3b61b8f 100644 --- a/studio/components/grid/components/common/MonacoEditor.tsx +++ b/studio/components/grid/components/common/MonacoEditor.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import Editor from '@monaco-editor/react'; +import * as React from 'react' +import Editor from '@monaco-editor/react' type MonacoEditorProps = { - width?: string | number | undefined; - height?: string | number | undefined; - value?: string | undefined; - language?: string | undefined; - onChange: (value: string | undefined) => void; - onMount?: (editor: any) => void; -}; + width?: string | number | undefined + height?: string | number | undefined + value?: string | undefined + language?: string | undefined + onChange: (value: string | undefined) => void + onMount?: (editor: any) => void +} export const MonacoEditor: React.FC = ({ width, @@ -25,20 +25,20 @@ export const MonacoEditor: React.FC = ({ afterLineNumber: 0, heightInPx: 4, domNode: document.createElement('div'), - }); - }); + }) + }) // move cursor to the end of document - const model = editor.getModel(); - const position = model.getPositionAt(value?.length); - editor.setPosition(position); + const model = editor.getModel() + const position = model.getPositionAt(value?.length) + editor.setPosition(position) // auto focus on mount setTimeout(() => { - editor?.focus(); - }, 0); + editor?.focus() + }, 0) - if (onMount) onMount(editor); + if (onMount) onMount(editor) } return ( @@ -68,5 +68,5 @@ export const MonacoEditor: React.FC = ({ wordWrap: 'on', }} /> - ); -}; + ) +} diff --git a/studio/components/grid/components/common/NullValue.tsx b/studio/components/grid/components/common/NullValue.tsx index aea4d62ccda..342c1ac1365 100644 --- a/studio/components/grid/components/common/NullValue.tsx +++ b/studio/components/grid/components/common/NullValue.tsx @@ -1,11 +1,11 @@ -import * as React from 'react'; +import * as React from 'react' -type NullValueProps = {}; +type NullValueProps = {} export const NullValue: React.FC = ({}) => { return ( NULL - ); -}; + ) +} diff --git a/studio/components/grid/components/common/Shortcuts.tsx b/studio/components/grid/components/common/Shortcuts.tsx index 3e7f3af6ffc..8926c9bf057 100644 --- a/studio/components/grid/components/common/Shortcuts.tsx +++ b/studio/components/grid/components/common/Shortcuts.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import { useTrackedState } from '../../store'; -import { useKeyboardShortcuts } from './Hooks'; -import { DataGridHandle } from '@supabase/react-data-grid'; -import { formatClipboardValue, copyToClipboard } from '../../utils'; +import * as React from 'react' +import { useTrackedState } from '../../store' +import { useKeyboardShortcuts } from './Hooks' +import { DataGridHandle } from '@supabase/react-data-grid' +import { formatClipboardValue, copyToClipboard } from '../../utils' type ShortcutsProps = { - gridRef: React.RefObject; -}; + gridRef: React.RefObject +} export function Shortcuts({ gridRef }: ShortcutsProps) { - const state = useTrackedState(); - const { rows, gridColumns, selectedCellPosition } = state; - const [metaKey, setMetaKey] = React.useState('Command'); + const state = useTrackedState() + const { rows, gridColumns, selectedCellPosition } = state + const [metaKey, setMetaKey] = React.useState('Command') React.useEffect(() => { function getClientOS() { @@ -19,69 +19,69 @@ export function Shortcuts({ gridRef }: ShortcutsProps) { ? 'windows' : navigator?.appVersion.indexOf('Mac') !== -1 ? 'macos' - : 'unknown'; + : 'unknown' } - const metakey = getClientOS() === 'windows' ? 'Control' : 'Command'; - setMetaKey(metakey); - }, []); + const metakey = getClientOS() === 'windows' ? 'Control' : 'Command' + setMetaKey(metakey) + }, []) useKeyboardShortcuts( { - [`${metaKey}+ArrowUp`]: event => { - event.stopPropagation(); + [`${metaKey}+ArrowUp`]: (event) => { + event.stopPropagation() if (selectedCellPosition) { const position = { idx: selectedCellPosition?.idx ?? 0, rowIdx: 0, - }; - gridRef.current!.selectCell(position); + } + gridRef.current!.selectCell(position) } else { - gridRef.current!.scrollToRow(Number(0)); + gridRef.current!.scrollToRow(Number(0)) } }, - [`${metaKey}+ArrowDown`]: event => { - event.stopPropagation(); + [`${metaKey}+ArrowDown`]: (event) => { + event.stopPropagation() if (selectedCellPosition) { const position = { idx: selectedCellPosition?.idx ?? 0, rowIdx: rows.length > 1 ? rows.length - 1 : 0, - }; - gridRef.current!.selectCell(position); + } + gridRef.current!.selectCell(position) } else { - gridRef.current!.scrollToRow(Number(rows.length)); + gridRef.current!.scrollToRow(Number(rows.length)) } }, - [`${metaKey}+ArrowLeft`]: event => { - event.stopPropagation(); - const fronzenColumns = gridColumns.filter(x => x.frozen); + [`${metaKey}+ArrowLeft`]: (event) => { + event.stopPropagation() + const fronzenColumns = gridColumns.filter((x) => x.frozen) const position = { idx: fronzenColumns.length, rowIdx: selectedCellPosition?.rowIdx ?? 0, - }; - gridRef.current!.selectCell(position); + } + gridRef.current!.selectCell(position) }, - [`${metaKey}+ArrowRight`]: event => { - event.stopPropagation(); + [`${metaKey}+ArrowRight`]: (event) => { + event.stopPropagation() gridRef.current?.selectCell({ idx: gridColumns.length - 1, rowIdx: selectedCellPosition?.rowIdx ?? 0, - }); + }) }, - [`${metaKey}+c`]: event => { - event.stopPropagation(); + [`${metaKey}+c`]: (event) => { + event.stopPropagation() if (selectedCellPosition) { - const { idx, rowIdx } = selectedCellPosition; + const { idx, rowIdx } = selectedCellPosition if (idx > 0) { - const colKey = gridColumns[idx].key; - const cellValue = rows[rowIdx]?.[colKey] ?? ''; - const value = formatClipboardValue(cellValue); - copyToClipboard(value); + const colKey = gridColumns[idx].key + const cellValue = rows[rowIdx]?.[colKey] ?? '' + const value = formatClipboardValue(cellValue) + copyToClipboard(value) } } }, }, ['INPUT', 'TEXTAREA', 'SELECT'] - ); + ) - return null; + return null } diff --git a/studio/components/grid/components/editor/BooleanEditor.tsx b/studio/components/grid/components/editor/BooleanEditor.tsx index 114188539c8..8505b5a5901 100644 --- a/studio/components/grid/components/editor/BooleanEditor.tsx +++ b/studio/components/grid/components/editor/BooleanEditor.tsx @@ -1,5 +1,5 @@ -import * as React from 'react'; -import { EditorProps } from '@supabase/react-data-grid'; +import * as React from 'react' +import { EditorProps } from '@supabase/react-data-grid' export function BooleanEditor({ row, @@ -8,11 +8,11 @@ export function BooleanEditor({ onClose, }: EditorProps) { function onChange(event: React.ChangeEvent) { - onRowChange({ ...row, [column.key]: event.target.checked }); + onRowChange({ ...row, [column.key]: event.target.checked }) } function onBlur() { - onClose(true); + onClose(true) } return ( @@ -26,5 +26,5 @@ export function BooleanEditor({ style={{ margin: 'auto' }} />
- ); + ) } diff --git a/studio/components/grid/components/editor/DateEditor.tsx b/studio/components/grid/components/editor/DateEditor.tsx index 3c2bb6c2b1b..fdcfcca018c 100644 --- a/studio/components/grid/components/editor/DateEditor.tsx +++ b/studio/components/grid/components/editor/DateEditor.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; -import { EditorProps } from '@supabase/react-data-grid'; +import * as React from 'react' +import { EditorProps } from '@supabase/react-data-grid' function autoFocusAndSelect(input: HTMLInputElement | null) { - input?.focus(); - input?.select(); + input?.focus() + input?.select() } export function DateEditor({ @@ -12,12 +12,12 @@ export function DateEditor({ onRowChange, onClose, }: EditorProps) { - const value = (row[column.key as keyof TRow] as unknown) as string; + const value = row[column.key as keyof TRow] as unknown as string function onChange(event: React.ChangeEvent) { - let _value = event.target.value; - if (_value == '') onRowChange({ ...row, [column.key]: null }); - else onRowChange({ ...row, [column.key]: _value }); + let _value = event.target.value + if (_value == '') onRowChange({ ...row, [column.key]: null }) + else onRowChange({ ...row, [column.key]: _value }) } return ( @@ -29,5 +29,5 @@ export function DateEditor({ onBlur={() => onClose(true)} type="date" /> - ); + ) } diff --git a/studio/components/grid/components/editor/NullableBooleanEditor.tsx b/studio/components/grid/components/editor/NullableBooleanEditor.tsx index 72e90865163..cac18ed8e4c 100644 --- a/studio/components/grid/components/editor/NullableBooleanEditor.tsx +++ b/studio/components/grid/components/editor/NullableBooleanEditor.tsx @@ -1,6 +1,6 @@ -import React, { useEffect } from 'react'; -import { EditorProps } from '@supabase/react-data-grid'; -import { Button, IconX } from '@supabase/ui'; +import React, { useEffect } from 'react' +import { EditorProps } from '@supabase/react-data-grid' +import { Button, IconX } from '@supabase/ui' export function NullableBooleanEditor({ row, @@ -8,25 +8,25 @@ export function NullableBooleanEditor({ onRowChange, onClose, }: EditorProps) { - const value = row[column.key as keyof TRow] as unknown as boolean | null; + const value = row[column.key as keyof TRow] as unknown as boolean | null useEffect(() => { // if value is null, set it to false on initial render if (value === null) { - onRowChange({ ...row, [column.key]: false }); + onRowChange({ ...row, [column.key]: false }) } - }, []); + }, []) function onChange(event: React.ChangeEvent) { - onRowChange({ ...row, [column.key]: event.target.checked }); + onRowChange({ ...row, [column.key]: event.target.checked }) } function onBlur() { - onClose(true); + onClose(true) } function onClear() { - onRowChange({ ...row, [column.key]: null }, true); + onRowChange({ ...row, [column.key]: null }, true) } return ( @@ -47,5 +47,5 @@ export function NullableBooleanEditor({ style={{ padding: '3px', margin: 'auto 5px auto auto' }} /> - ); + ) } diff --git a/studio/components/grid/components/editor/NumberEditor.tsx b/studio/components/grid/components/editor/NumberEditor.tsx index d8e020da217..2ff9c67e310 100644 --- a/studio/components/grid/components/editor/NumberEditor.tsx +++ b/studio/components/grid/components/editor/NumberEditor.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; -import { EditorProps } from '@supabase/react-data-grid'; +import * as React from 'react' +import { EditorProps } from '@supabase/react-data-grid' function autoFocusAndSelect(input: HTMLInputElement | null) { - input?.focus(); - input?.select(); + input?.focus() + input?.select() } export function NumberEditor({ @@ -12,16 +12,16 @@ export function NumberEditor({ onRowChange, onClose, }: EditorProps) { - const value = (row[column.key as keyof TRow] as unknown) as string; + const value = row[column.key as keyof TRow] as unknown as string function onChange(event: React.ChangeEvent) { - const _value = event.target.value; - if (_value == '') onRowChange({ ...row, [column.key]: null }); - else onRowChange({ ...row, [column.key]: _value }); + const _value = event.target.value + if (_value == '') onRowChange({ ...row, [column.key]: null }) + else onRowChange({ ...row, [column.key]: _value }) } function onBlur() { - onClose(true); + onClose(true) } return ( @@ -33,5 +33,5 @@ export function NumberEditor({ onBlur={onBlur} type="number" /> - ); + ) } diff --git a/studio/components/grid/components/editor/TimeEditor.tsx b/studio/components/grid/components/editor/TimeEditor.tsx index 72004b72a99..bfcc54b3b0a 100644 --- a/studio/components/grid/components/editor/TimeEditor.tsx +++ b/studio/components/grid/components/editor/TimeEditor.tsx @@ -1,25 +1,24 @@ -import * as React from 'react'; -import { EditorProps } from '@supabase/react-data-grid'; -import dayjs from 'dayjs'; -import customParseFormat from 'dayjs/plugin/customParseFormat'; +import * as React from 'react' +import { EditorProps } from '@supabase/react-data-grid' +import dayjs from 'dayjs' +import customParseFormat from 'dayjs/plugin/customParseFormat' -dayjs.extend(customParseFormat); +dayjs.extend(customParseFormat) function autoFocusAndSelect(input: HTMLInputElement | null) { - input?.focus(); - input?.select(); + input?.focus() + input?.select() } -interface TimeEditorProps - extends EditorProps { - format: string; +interface TimeEditorProps extends EditorProps { + format: string } /** * original input time format 'HH:mm' * when step=1, it becomes 'HH:mm:ss' */ -const INPUT_TIME_FORMAT = 'HH:mm:ss'; +const INPUT_TIME_FORMAT = 'HH:mm:ss' function BaseEditor({ row, @@ -28,18 +27,16 @@ function BaseEditor({ onRowChange, onClose, }: TimeEditorProps) { - const value = row[column.key as keyof TRow] as unknown as string; - const timeValue = value - ? dayjs(value, format).format(INPUT_TIME_FORMAT) - : value; + const value = row[column.key as keyof TRow] as unknown as string + const timeValue = value ? dayjs(value, format).format(INPUT_TIME_FORMAT) : value function onChange(event: React.ChangeEvent) { - const _value = event.target.value; + const _value = event.target.value if (_value == '') { - onRowChange({ ...row, [column.key]: null }); + onRowChange({ ...row, [column.key]: null }) } else { - const _timeValue = dayjs(_value, INPUT_TIME_FORMAT).format(format); - onRowChange({ ...row, [column.key]: _timeValue }); + const _timeValue = dayjs(_value, INPUT_TIME_FORMAT).format(format) + onRowChange({ ...row, [column.key]: _timeValue }) } } @@ -53,17 +50,15 @@ function BaseEditor({ type="time" step="1" /> - ); + ) } -export function TimeEditor( - props: EditorProps -) { - return ; +export function TimeEditor(props: EditorProps) { + return } export function TimeWithTimezoneEditor( props: EditorProps ) { - return ; + return } diff --git a/studio/components/grid/components/editor/index.ts b/studio/components/grid/components/editor/index.ts index 56379b8f45a..af37e035773 100644 --- a/studio/components/grid/components/editor/index.ts +++ b/studio/components/grid/components/editor/index.ts @@ -1,9 +1,9 @@ -export * from './BooleanEditor'; -export * from './DateEditor'; -export * from './DateTimeEditor'; -export * from './JsonEditor'; -export * from './NullableBooleanEditor'; -export * from './NumberEditor'; -export * from './SelectEditor'; -export * from './TextEditor'; -export * from './TimeEditor'; +export * from './BooleanEditor' +export * from './DateEditor' +export * from './DateTimeEditor' +export * from './JsonEditor' +export * from './NullableBooleanEditor' +export * from './NumberEditor' +export * from './SelectEditor' +export * from './TextEditor' +export * from './TimeEditor' diff --git a/studio/components/grid/components/footer/Footer.tsx b/studio/components/grid/components/footer/Footer.tsx index 86f6248d068..f950319460b 100644 --- a/studio/components/grid/components/footer/Footer.tsx +++ b/studio/components/grid/components/footer/Footer.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; -import Pagination from './pagination'; +import * as React from 'react' +import Pagination from './pagination' -type FooterProps = {}; +type FooterProps = {} const Footer: React.FC = () => { return ( @@ -10,6 +10,6 @@ const Footer: React.FC = () => { - ); -}; -export default Footer; + ) +} +export default Footer diff --git a/studio/components/grid/components/footer/index.ts b/studio/components/grid/components/footer/index.ts index ced11e5251b..9c7e8318339 100644 --- a/studio/components/grid/components/footer/index.ts +++ b/studio/components/grid/components/footer/index.ts @@ -1,3 +1,3 @@ -import Footer from './Footer'; +import Footer from './Footer' -export default Footer; +export default Footer diff --git a/studio/components/grid/components/footer/pagination/index.ts b/studio/components/grid/components/footer/pagination/index.ts index 9ed530b1f60..1466412190c 100644 --- a/studio/components/grid/components/footer/pagination/index.ts +++ b/studio/components/grid/components/footer/pagination/index.ts @@ -1,3 +1,3 @@ -import Pagination from './Pagination'; +import Pagination from './Pagination' -export default Pagination; +export default Pagination diff --git a/studio/components/grid/components/formatter/BooleanFormatter.tsx b/studio/components/grid/components/formatter/BooleanFormatter.tsx index 34fa3bd2cc7..a038fdda957 100644 --- a/studio/components/grid/components/formatter/BooleanFormatter.tsx +++ b/studio/components/grid/components/formatter/BooleanFormatter.tsx @@ -1,12 +1,10 @@ -import * as React from 'react'; -import { FormatterProps } from '@supabase/react-data-grid'; -import { SupaRow } from '../../types'; -import { NullValue } from '../common'; +import * as React from 'react' +import { FormatterProps } from '@supabase/react-data-grid' +import { SupaRow } from '../../types' +import { NullValue } from '../common' -export const BooleanFormatter = ( - p: React.PropsWithChildren> -) => { - const value = p.row[p.column.key] as boolean | null; - if (value === null) return ; - return <>{value ? 'true' : 'false'}; -}; +export const BooleanFormatter = (p: React.PropsWithChildren>) => { + const value = p.row[p.column.key] as boolean | null + if (value === null) return + return <>{value ? 'true' : 'false'} +} diff --git a/studio/components/grid/components/formatter/DefaultFormatter.tsx b/studio/components/grid/components/formatter/DefaultFormatter.tsx index 4ce80783aa4..65df936137b 100644 --- a/studio/components/grid/components/formatter/DefaultFormatter.tsx +++ b/studio/components/grid/components/formatter/DefaultFormatter.tsx @@ -1,17 +1,15 @@ -import * as React from 'react'; -import { FormatterProps } from '@supabase/react-data-grid'; -import { SupaRow } from '../../types'; -import { NullValue } from '../common'; -import { EmptyValue } from '../common/EmptyValue'; +import * as React from 'react' +import { FormatterProps } from '@supabase/react-data-grid' +import { SupaRow } from '../../types' +import { NullValue } from '../common' +import { EmptyValue } from '../common/EmptyValue' -export const DefaultFormatter = ( - p: React.PropsWithChildren> -) => { - let value = p.row[p.column.key]; - if (value === null) return ; - if(value === '') return ; +export const DefaultFormatter = (p: React.PropsWithChildren>) => { + let value = p.row[p.column.key] + if (value === null) return + if (value === '') return if (typeof value == 'object' || Array.isArray(value)) { - value = JSON.stringify(value); + value = JSON.stringify(value) } - return <>{value}; -}; + return <>{value} +} diff --git a/studio/components/grid/components/formatter/index.ts b/studio/components/grid/components/formatter/index.ts index a8becfed3df..3a1f31f3b94 100644 --- a/studio/components/grid/components/formatter/index.ts +++ b/studio/components/grid/components/formatter/index.ts @@ -1,3 +1,3 @@ -export * from './BooleanFormatter'; -export * from './DefaultFormatter'; -export * from './ForeignKeyFormatter'; +export * from './BooleanFormatter' +export * from './DefaultFormatter' +export * from './ForeignKeyFormatter' diff --git a/studio/components/grid/components/grid/RowRenderer.tsx b/studio/components/grid/components/grid/RowRenderer.tsx index da7fec46a2a..9520648f7f8 100644 --- a/studio/components/grid/components/grid/RowRenderer.tsx +++ b/studio/components/grid/components/grid/RowRenderer.tsx @@ -1,19 +1,19 @@ -import * as React from 'react'; -import { TriggerEvent, useContextMenu } from 'react-contexify'; -import { Row, RowRendererProps } from '@supabase/react-data-grid'; -import { MENU_IDS } from '../menu'; -import { SupaRow } from '../../types'; +import * as React from 'react' +import { TriggerEvent, useContextMenu } from 'react-contexify' +import { Row, RowRendererProps } from '@supabase/react-data-grid' +import { MENU_IDS } from '../menu' +import { SupaRow } from '../../types' export default function RowRenderer(props: RowRendererProps) { - const { show: showContextMenu } = useContextMenu(); + const { show: showContextMenu } = useContextMenu() function displayMenu(e: TriggerEvent) { - const menuId = MENU_IDS.ROW_CONTEXT_MENU_ID; + const menuId = MENU_IDS.ROW_CONTEXT_MENU_ID showContextMenu(e, { id: menuId, props: { rowIdx: props.rowIdx }, - }); + }) } - return ; + return } diff --git a/studio/components/grid/components/grid/index.ts b/studio/components/grid/components/grid/index.ts index 4d5f13be998..5513c7ef8d2 100644 --- a/studio/components/grid/components/grid/index.ts +++ b/studio/components/grid/components/grid/index.ts @@ -1,4 +1,4 @@ -export * from './ColumnHeader'; -export * from './Grid'; -export * from './SelectColumn'; -export * from './AddColumn'; +export * from './ColumnHeader' +export * from './Grid' +export * from './SelectColumn' +export * from './AddColumn' diff --git a/studio/components/grid/components/header/StatusLabel.tsx b/studio/components/grid/components/header/StatusLabel.tsx index d08ec33361d..b36b6ac680b 100644 --- a/studio/components/grid/components/header/StatusLabel.tsx +++ b/studio/components/grid/components/header/StatusLabel.tsx @@ -1,33 +1,33 @@ -import * as React from 'react'; -import { SupabaseGridQueue } from '../../constants'; -import { Typography } from '@supabase/ui'; +import * as React from 'react' +import { SupabaseGridQueue } from '../../constants' +import { Typography } from '@supabase/ui' -type StatusLabelProps = {}; +type StatusLabelProps = {} const StatusLabel: React.FC = ({}) => { - const [msg, setMsg] = React.useState(undefined); + const [msg, setMsg] = React.useState(undefined) React.useEffect(() => { - let isMounted = true; - let timer: number | null; + let isMounted = true + let timer: number | null SupabaseGridQueue.on('active', () => { - if (timer) clearTimeout(timer); + if (timer) clearTimeout(timer) - if (isMounted) setMsg('Saving...'); - }); + if (isMounted) setMsg('Saving...') + }) SupabaseGridQueue.on('idle', () => { - if (timer) clearTimeout(timer); - timer = window.setTimeout(() => setMsg(undefined), 2000); + if (timer) clearTimeout(timer) + timer = window.setTimeout(() => setMsg(undefined), 2000) - if (isMounted) setMsg('All changes saved'); - }); + if (isMounted) setMsg('All changes saved') + }) return () => { - isMounted = false; - if (timer) clearTimeout(timer); - }; - }, []); + isMounted = false + if (timer) clearTimeout(timer) + } + }, []) return (
@@ -38,6 +38,6 @@ const StatusLabel: React.FC = ({}) => {
)} - ); -}; -export default StatusLabel; + ) +} +export default StatusLabel diff --git a/studio/components/grid/components/header/filter/index.ts b/studio/components/grid/components/header/filter/index.ts index c2649a3b187..077fcde392d 100644 --- a/studio/components/grid/components/header/filter/index.ts +++ b/studio/components/grid/components/header/filter/index.ts @@ -1,4 +1,4 @@ -import FilterPopover from './FilterPopover'; +import FilterPopover from './FilterPopover' -export * from './Filter.constants'; -export default FilterPopover; +export * from './Filter.constants' +export default FilterPopover diff --git a/studio/components/grid/components/header/index.ts b/studio/components/grid/components/header/index.ts index a9ce1058c39..7cd29d7abd0 100644 --- a/studio/components/grid/components/header/index.ts +++ b/studio/components/grid/components/header/index.ts @@ -1,3 +1,3 @@ -import Header from './Header'; +import Header from './Header' -export default Header; +export default Header diff --git a/studio/components/grid/components/header/sort/index.ts b/studio/components/grid/components/header/sort/index.ts index cd4307ac38c..f3f0e9d2821 100644 --- a/studio/components/grid/components/header/sort/index.ts +++ b/studio/components/grid/components/header/sort/index.ts @@ -1,3 +1,3 @@ -import SortPopover from './SortPopover'; +import SortPopover from './SortPopover' -export default SortPopover; +export default SortPopover diff --git a/studio/components/grid/constants.ts b/studio/components/grid/constants.ts index 8706a6bd394..1f4b8caf92e 100644 --- a/studio/components/grid/constants.ts +++ b/studio/components/grid/constants.ts @@ -1,17 +1,17 @@ -import PQueue from 'p-queue'; +import PQueue from 'p-queue' -export const SupabaseGridQueue = new PQueue({ concurrency: 1 }); +export const SupabaseGridQueue = new PQueue({ concurrency: 1 }) -export const COLUMN_MIN_WIDTH = 100; +export const COLUMN_MIN_WIDTH = 100 -export const STORAGE_KEY_PREFIX = 'supabase_grid'; +export const STORAGE_KEY_PREFIX = 'supabase_grid' -export const REFRESH_PAGE_IMMEDIATELY = -1; -export const TOTAL_ROWS_INITIAL = -1; -export const TOTAL_ROWS_RESET = -2; +export const REFRESH_PAGE_IMMEDIATELY = -1 +export const TOTAL_ROWS_INITIAL = -1 +export const TOTAL_ROWS_RESET = -2 -export const SELECT_COLUMN_KEY = 'supabase-grid-select-row'; -export const ADD_COLUMN_KEY = 'supabase-grid-add-column'; +export const SELECT_COLUMN_KEY = 'supabase-grid-select-row' +export const ADD_COLUMN_KEY = 'supabase-grid-add-column' export const ERROR_PRIMARY_KEY_NOTFOUND = - 'Please add a primary key column to your table to update or delete rows'; + 'Please add a primary key column to your table to update or delete rows' diff --git a/studio/components/grid/index.ts b/studio/components/grid/index.ts index 9914484540a..c6ed6766a7b 100644 --- a/studio/components/grid/index.ts +++ b/studio/components/grid/index.ts @@ -1,7 +1,7 @@ -export * from './SupabaseGrid'; -export { parseSupaTable } from './SupabaseGrid.utils'; -export * from './types'; +export * from './SupabaseGrid' +export { parseSupaTable } from './SupabaseGrid.utils' +export * from './types' -import Query from './query'; +import Query from './query' -export { Query }; +export { Query } diff --git a/studio/components/grid/query/Query.ts b/studio/components/grid/query/Query.ts index ef5fe1e7ea3..1139a23a0f8 100644 --- a/studio/components/grid/query/Query.ts +++ b/studio/components/grid/query/Query.ts @@ -1,7 +1,7 @@ -import { IQueryAction, QueryAction } from './QueryAction'; +import { IQueryAction, QueryAction } from './QueryAction' interface IQuery { - from: (table: string, schema?: string) => IQueryAction; + from: (table: string, schema?: string) => IQueryAction } export class Query implements IQuery { @@ -13,6 +13,6 @@ export class Query implements IQuery { return new QueryAction({ name, schema: schema ?? 'public', - }); + }) } } diff --git a/studio/components/grid/query/index.ts b/studio/components/grid/query/index.ts index 27ced1506de..7a974c2c7ed 100644 --- a/studio/components/grid/query/index.ts +++ b/studio/components/grid/query/index.ts @@ -1,3 +1,3 @@ -import { Query } from './Query'; +import { Query } from './Query' -export default Query; +export default Query diff --git a/studio/components/grid/services/meta/SqlMetaService.sqls.ts b/studio/components/grid/services/meta/SqlMetaService.sqls.ts index a8ccea92cc3..16bbec771db 100644 --- a/studio/components/grid/services/meta/SqlMetaService.sqls.ts +++ b/studio/components/grid/services/meta/SqlMetaService.sqls.ts @@ -1,7 +1,7 @@ -import { format } from '@scaleleap/pg-format'; +import { format } from '@scaleleap/pg-format' export function getColumnsSql(filter_schema: string, filter_name: string) { - return format(columnsSql, filter_schema, filter_name); + return format(columnsSql, filter_schema, filter_name) } const columnsSql = ` SELECT @@ -101,10 +101,10 @@ WHERE 'SELECT, INSERT, UPDATE, REFERENCES' ) ) -`; +` export function getPrimaryKeysSql(filter_schema: string, filter_name: string) { - return format(primaryKeysSql, filter_schema, filter_name); + return format(primaryKeysSql, filter_schema, filter_name) } const primaryKeysSql = ` SELECT @@ -125,13 +125,10 @@ WHERE AND a.attrelid = c.oid AND a.attnum = ANY (i.indkey) AND i.indisprimary -`; +` -export function getRelationshipsSql( - filter_schema: string, - filter_name: string -) { - return format(relationshipsSql, filter_schema, filter_name); +export function getRelationshipsSql(filter_schema: string, filter_name: string) { + return format(relationshipsSql, filter_schema, filter_name) } const relationshipsSql = ` SELECT @@ -161,10 +158,10 @@ WHERE c.contype = 'f' AND nsa.nspname = %L AND csa.relname = %L; -`; +` export function getTableSql(filter_schema: string, filter_name: string) { - return format(tableSql, filter_schema, filter_name); + return format(tableSql, filter_schema, filter_name) } const tableSql = ` SELECT @@ -189,4 +186,4 @@ WHERE ) OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') ) -`; +` diff --git a/studio/components/grid/services/meta/SqlMetaService.ts b/studio/components/grid/services/meta/SqlMetaService.ts index 9d5da5ca165..7e91ca00105 100644 --- a/studio/components/grid/services/meta/SqlMetaService.ts +++ b/studio/components/grid/services/meta/SqlMetaService.ts @@ -1,56 +1,52 @@ -import { IMetaService } from '.'; +import { IMetaService } from '.' import { getColumnsSql, getPrimaryKeysSql, getRelationshipsSql, getTableSql, -} from './SqlMetaService.sqls'; +} from './SqlMetaService.sqls' export class SqlMetaService implements IMetaService { - constructor( - protected onSqlQuery: ( - query: string - ) => Promise<{ data?: any; error?: any }> - ) {} + constructor(protected onSqlQuery: (query: string) => Promise<{ data?: any; error?: any }>) {} async fetchInfo(name: string, schema?: string | undefined) { - const sql = getTableSql(schema ?? 'public', name); - const { data, error } = await this.onSqlQuery(sql); + const sql = getTableSql(schema ?? 'public', name) + const { data, error } = await this.onSqlQuery(sql) if (error) { - return { error }; + return { error } } else { if (data?.length == 1) { - return { data: data[0] }; + return { data: data[0] } } else { - return { error: { message: 'fetch table info failed' } }; + return { error: { message: 'fetch table info failed' } } } } } async fetchColumns(name: string, schema?: string | undefined) { - const sql = getColumnsSql(schema ?? 'public', name); - const { data, error } = await this.onSqlQuery(sql); + const sql = getColumnsSql(schema ?? 'public', name) + const { data, error } = await this.onSqlQuery(sql) if (error) { - return { error }; + return { error } } else { - return { data }; + return { data } } } async fetchPrimaryKeys(name: string, schema?: string | undefined) { - const sql = getPrimaryKeysSql(schema ?? 'public', name); - const { data, error } = await this.onSqlQuery(sql); + const sql = getPrimaryKeysSql(schema ?? 'public', name) + const { data, error } = await this.onSqlQuery(sql) if (error) { - return { error }; + return { error } } else { - return { data }; + return { data } } } async fetchRelationships(name: string, schema?: string | undefined) { - const sql = getRelationshipsSql(schema ?? 'public', name); - const { data, error } = await this.onSqlQuery(sql); + const sql = getRelationshipsSql(schema ?? 'public', name) + const { data, error } = await this.onSqlQuery(sql) if (error) { - return { error }; + return { error } } else { - return { data }; + return { data } } } } diff --git a/studio/components/grid/services/meta/index.ts b/studio/components/grid/services/meta/index.ts index 48caf4dfe99..5b328984c04 100644 --- a/studio/components/grid/services/meta/index.ts +++ b/studio/components/grid/services/meta/index.ts @@ -1,22 +1,22 @@ -import { Dictionary, ServiceError } from '../../types'; +import { Dictionary, ServiceError } from '../../types' export interface IMetaService { fetchInfo: ( name: string, schema?: string - ) => Promise<{ data?: Dictionary; error?: ServiceError }>; + ) => Promise<{ data?: Dictionary; error?: ServiceError }> fetchColumns: ( name: string, schema?: string - ) => Promise<{ data?: Dictionary[]; error?: ServiceError }>; + ) => Promise<{ data?: Dictionary[]; error?: ServiceError }> fetchPrimaryKeys: ( name: string, schema?: string - ) => Promise<{ data?: Dictionary[]; error?: ServiceError }>; + ) => Promise<{ data?: Dictionary[]; error?: ServiceError }> fetchRelationships: ( name: string, schema?: string - ) => Promise<{ data?: Dictionary[]; error?: ServiceError }>; + ) => Promise<{ data?: Dictionary[]; error?: ServiceError }> } -export * from './SqlMetaService'; +export * from './SqlMetaService' diff --git a/studio/components/grid/store/index.ts b/studio/components/grid/store/index.ts index 47e0805c13b..678248c00d7 100644 --- a/studio/components/grid/store/index.ts +++ b/studio/components/grid/store/index.ts @@ -1 +1 @@ -export * from './Store'; +export * from './Store' diff --git a/studio/components/grid/store/reducers/callback.ts b/studio/components/grid/store/reducers/callback.ts index edb6060008d..30d7b4bb735 100644 --- a/studio/components/grid/store/reducers/callback.ts +++ b/studio/components/grid/store/reducers/callback.ts @@ -1,13 +1,13 @@ -import { SupaRow } from '../../types'; +import { SupaRow } from '../../types' export interface CallbackInitialState { - onAddColumn: (() => void) | null; - onAddRow: (() => void) | null; - onError: ((error: any) => void) | null; - onEditRow: ((row: SupaRow) => void) | null; - onEditColumn: ((columnName: string) => void) | null; - onDeleteColumn: ((columnName: string) => void) | null; - onSqlQuery: ((query: string) => Promise<{ data?: any; error?: any }>) | null; + onAddColumn: (() => void) | null + onAddRow: (() => void) | null + onError: ((error: any) => void) | null + onEditRow: ((row: SupaRow) => void) | null + onEditColumn: ((columnName: string) => void) | null + onDeleteColumn: ((columnName: string) => void) | null + onSqlQuery: ((query: string) => Promise<{ data?: any; error?: any }>) | null } export const callbackInitialState: CallbackInitialState = { @@ -18,27 +18,22 @@ export const callbackInitialState: CallbackInitialState = { onEditColumn: null, onDeleteColumn: null, onSqlQuery: null, -}; +} type CALLBACK_ACTIONTYPE = { - type: 'INIT_CALLBACK'; + type: 'INIT_CALLBACK' payload: { - onAddColumn: (() => void) | null; - onAddRow: (() => void) | null; - onError: ((error: any) => void) | null; - onEditRow: ((row: SupaRow) => void) | null; - onEditColumn: ((columnName: string) => void) | null; - onDeleteColumn: ((columnName: string) => void) | null; - onSqlQuery: - | ((query: string) => Promise<{ data?: any; error?: any }>) - | null; - }; -}; + onAddColumn: (() => void) | null + onAddRow: (() => void) | null + onError: ((error: any) => void) | null + onEditRow: ((row: SupaRow) => void) | null + onEditColumn: ((columnName: string) => void) | null + onDeleteColumn: ((columnName: string) => void) | null + onSqlQuery: ((query: string) => Promise<{ data?: any; error?: any }>) | null + } +} -const CallbackReducer = ( - state: CallbackInitialState, - action: CALLBACK_ACTIONTYPE -) => { +const CallbackReducer = (state: CallbackInitialState, action: CALLBACK_ACTIONTYPE) => { switch (action.type) { case 'INIT_CALLBACK': { return { @@ -50,12 +45,12 @@ const CallbackReducer = ( onEditColumn: action.payload.onEditColumn, onDeleteColumn: action.payload.onDeleteColumn, onSqlQuery: action.payload.onSqlQuery, - }; + } } default: - return state; + return state } -}; +} -export default CallbackReducer; +export default CallbackReducer diff --git a/studio/components/grid/store/reducers/column.ts b/studio/components/grid/store/reducers/column.ts index b63afe14ce7..8f1d4f9674b 100644 --- a/studio/components/grid/store/reducers/column.ts +++ b/studio/components/grid/store/reducers/column.ts @@ -1,61 +1,51 @@ -import update from 'immutability-helper'; -import { CalculatedColumn } from '@supabase/react-data-grid'; -import { cloneColumn, getInitialGridColumns } from '../../utils'; -import { INIT_ACTIONTYPE } from './base'; +import update from 'immutability-helper' +import { CalculatedColumn } from '@supabase/react-data-grid' +import { cloneColumn, getInitialGridColumns } from '../../utils' +import { INIT_ACTIONTYPE } from './base' export interface ColumnInitialState { - gridColumns: CalculatedColumn []; + gridColumns: CalculatedColumn[] } export const columnInitialState: ColumnInitialState = { gridColumns: [], -}; +} type COLUMN_ACTIONTYPE = | INIT_ACTIONTYPE | { - type: 'MOVE_COLUMN'; - payload: { fromKey: string; toKey: string }; + type: 'MOVE_COLUMN' + payload: { fromKey: string; toKey: string } } | { - type: 'UPDATE_COLUMN_SIZE'; - payload: { index: number; width: number }; + type: 'UPDATE_COLUMN_SIZE' + payload: { index: number; width: number } } | { - type: 'FREEZE_COLUMN'; - payload: { columnKey: string }; + type: 'FREEZE_COLUMN' + payload: { columnKey: string } } | { - type: 'UNFREEZE_COLUMN'; - payload: { columnKey: string }; + type: 'UNFREEZE_COLUMN' + payload: { columnKey: string } } | { - type: 'UPDATE_COLUMN_IDX'; - payload: { columnKey: string; columnIdx: number }; - }; + type: 'UPDATE_COLUMN_IDX' + payload: { columnKey: string; columnIdx: number } + } -const ColumnReducer = ( - state: ColumnInitialState, - action: COLUMN_ACTIONTYPE -) => { +const ColumnReducer = (state: ColumnInitialState, action: COLUMN_ACTIONTYPE) => { switch (action.type) { case 'INIT_TABLE': { return { ...state, - gridColumns: getInitialGridColumns( - action.payload.gridColumns, - action.payload.savedState - ), - }; + gridColumns: getInitialGridColumns(action.payload.gridColumns, action.payload.savedState), + } } case 'MOVE_COLUMN': { - const fromIdx = state.gridColumns.findIndex( - x => x.key === action.payload.fromKey - ); - const toIdx = state.gridColumns.findIndex( - x => x.key === action.payload.toKey - ); - const moveItem = state.gridColumns[fromIdx]; + const fromIdx = state.gridColumns.findIndex((x) => x.key === action.payload.fromKey) + const toIdx = state.gridColumns.findIndex((x) => x.key === action.payload.toKey) + const moveItem = state.gridColumns[fromIdx] return { ...state, gridColumns: update(state.gridColumns, { @@ -64,61 +54,54 @@ const ColumnReducer = ( [toIdx, 0, moveItem], ], }), - }; + } } case 'UPDATE_COLUMN_SIZE': { - const updated = cloneColumn(state.gridColumns[action.payload.index]); - updated.width = action.payload.width; + const updated = cloneColumn(state.gridColumns[action.payload.index]) + updated.width = action.payload.width return { ...state, gridColumns: update(state.gridColumns, { [action.payload.index]: { $set: updated }, }), - }; + } } case 'FREEZE_COLUMN': { - const columnIdx = state.gridColumns.findIndex( - x => x.key === action.payload.columnKey - ); - const updated = cloneColumn(state.gridColumns[columnIdx]); - updated.frozen = true; + const columnIdx = state.gridColumns.findIndex((x) => x.key === action.payload.columnKey) + const updated = cloneColumn(state.gridColumns[columnIdx]) + updated.frozen = true return { ...state, gridColumns: update(state.gridColumns, { [columnIdx]: { $set: updated }, }), - }; + } } case 'UNFREEZE_COLUMN': { - const columnIdx = state.gridColumns.findIndex( - x => x.key === action.payload.columnKey - ); - const updated = cloneColumn(state.gridColumns[columnIdx]); - updated.frozen = false; + const columnIdx = state.gridColumns.findIndex((x) => x.key === action.payload.columnKey) + const updated = cloneColumn(state.gridColumns[columnIdx]) + updated.frozen = false return { ...state, gridColumns: update(state.gridColumns, { [columnIdx]: { $set: updated }, }), - }; + } } case 'UPDATE_COLUMN_IDX': { - const index = state.gridColumns.findIndex( - x => x.key === action.payload.columnKey - ); - const updated = cloneColumn(state.gridColumns[index]); - updated.idx = action.payload.columnIdx; + const index = state.gridColumns.findIndex((x) => x.key === action.payload.columnKey) + const updated = cloneColumn(state.gridColumns[index]) + updated.idx = action.payload.columnIdx return { ...state, gridColumns: update(state.gridColumns, { [index]: { $set: updated }, - }) - .sort((a, b) => a.idx - b.idx), - }; + }).sort((a, b) => a.idx - b.idx), + } } default: - return state; + return state } -}; +} -export default ColumnReducer; +export default ColumnReducer diff --git a/studio/components/grid/types/grid.ts b/studio/components/grid/types/grid.ts index 92581029b05..e05352cfdfc 100644 --- a/studio/components/grid/types/grid.ts +++ b/studio/components/grid/types/grid.ts @@ -1,74 +1,74 @@ -import React from 'react'; -import { Dictionary } from './base'; -import { SupaRow, SupaTable } from './table'; +import React from 'react' +import { Dictionary } from './base' +import { SupaRow, SupaTable } from './table' export interface GridProps { - width?: string | number; - height?: string | number; - defaultColumnWidth?: string | number; - containerClass?: string; - gridClass?: string; - rowClass?: ((row: SupaRow) => string | undefined) | undefined; + width?: string | number + height?: string | number + defaultColumnWidth?: string | number + containerClass?: string + gridClass?: string + rowClass?: ((row: SupaRow) => string | undefined) | undefined } export interface SupabaseGridProps { /** * database table swagger or table name */ - table: SupaTable | string; + table: SupaTable | string /** * run sql query */ - onSqlQuery: (query: string) => Promise<{ data?: any; error?: any }>; + onSqlQuery: (query: string) => Promise<{ data?: any; error?: any }> /** * Optional react node to display in grid header */ - headerActions?: React.ReactNode; + headerActions?: React.ReactNode /** * enable table editor */ - editable?: boolean; + editable?: boolean /** * props to config grid view */ - gridProps?: GridProps; + gridProps?: GridProps /** * table schema. Default set to 'public' if not provided */ - schema?: string; + schema?: string /** * storageRef is used to save state on localstorage */ - storageRef?: string; + storageRef?: string /** * Optional grid theme */ - theme?: 'dark' | 'light'; + theme?: 'dark' | 'light' /** * show create new column button if available */ - onAddColumn?: () => void; + onAddColumn?: () => void /** * show add row button if available */ - onAddRow?: () => void; + onAddRow?: () => void /** * show delete column menu if available */ - onDeleteColumn?: (columnName: string) => void; + onDeleteColumn?: (columnName: string) => void /** * show edit column menu if available */ - onEditColumn?: (columnName: string) => void; + onEditColumn?: (columnName: string) => void /** * show edit row button if available */ - onEditRow?: (row: SupaRow) => void; + onEditRow?: (row: SupaRow) => void /** * error handler */ - onError?: (error: any) => void; + onError?: (error: any) => void } export interface SupabaseGridRef { @@ -77,12 +77,12 @@ export interface SupabaseGridRef { * * @param row newly added row data */ - rowAdded(row: Dictionary): void; + rowAdded(row: Dictionary): void /** * callback when a row is edited * * @param row edited row data * @param idx edited row index */ - rowEdited(row: Dictionary, idx: number): void; + rowEdited(row: Dictionary, idx: number): void } diff --git a/studio/components/grid/types/index.ts b/studio/components/grid/types/index.ts index 6918ebeeb63..03c9ecf309f 100644 --- a/studio/components/grid/types/index.ts +++ b/studio/components/grid/types/index.ts @@ -1,5 +1,5 @@ -export * from './base'; -export * from './grid'; -export * from './query'; -export * from './service'; -export * from './table'; +export * from './base' +export * from './grid' +export * from './query' +export * from './service' +export * from './table' diff --git a/studio/components/grid/types/query.ts b/studio/components/grid/types/query.ts index 72219b8bb04..2d688965e49 100644 --- a/studio/components/grid/types/query.ts +++ b/studio/components/grid/types/query.ts @@ -1,9 +1,9 @@ export interface QueryTable { - name: string; - schema: string; + name: string + schema: string } export interface QueryPagination { - limit: number; - offset: number; + limit: number + offset: number } diff --git a/studio/components/grid/types/service.ts b/studio/components/grid/types/service.ts index 6f109f6a712..0f2ed39a82c 100644 --- a/studio/components/grid/types/service.ts +++ b/studio/components/grid/types/service.ts @@ -1,3 +1,3 @@ export interface ServiceError { - message: string; + message: string } diff --git a/studio/components/grid/types/table.ts b/studio/components/grid/types/table.ts index 48ecf6f44b8..e3a5c91838b 100644 --- a/studio/components/grid/types/table.ts +++ b/studio/components/grid/types/table.ts @@ -1,30 +1,30 @@ -import { Dictionary } from './base'; +import { Dictionary } from './base' export interface SupaColumn { - readonly dataType: string; - readonly format: string; - readonly name: string; - readonly comment?: string | null; - readonly defaultValue?: string | null; - readonly enum?: string[] | null; - readonly isPrimaryKey?: boolean; - readonly isIdentity?: boolean; - readonly isGeneratable?: boolean; - readonly isNullable?: boolean; - readonly isUpdatable?: boolean; - readonly targetTableSchema?: string | null; - readonly targetTableName?: string | null; - readonly targetColumnName?: string | null; - position: number; + readonly dataType: string + readonly format: string + readonly name: string + readonly comment?: string | null + readonly defaultValue?: string | null + readonly enum?: string[] | null + readonly isPrimaryKey?: boolean + readonly isIdentity?: boolean + readonly isGeneratable?: boolean + readonly isNullable?: boolean + readonly isUpdatable?: boolean + readonly targetTableSchema?: string | null + readonly targetTableName?: string | null + readonly targetColumnName?: string | null + position: number } export interface SupaTable { - readonly columns: SupaColumn[]; - readonly name: string; - readonly schema?: string | null; - readonly comment?: string | null; + readonly columns: SupaColumn[] + readonly name: string + readonly schema?: string | null + readonly comment?: string | null } export interface SupaRow extends Dictionary { - readonly idx: number; + readonly idx: number } diff --git a/studio/components/grid/utils/column.ts b/studio/components/grid/utils/column.ts index aecc6bd7299..0f8575d02a0 100644 --- a/studio/components/grid/utils/column.ts +++ b/studio/components/grid/utils/column.ts @@ -1,57 +1,54 @@ -import { CalculatedColumn } from '@supabase/react-data-grid'; -import { ADD_COLUMN_KEY, SELECT_COLUMN_KEY } from '../constants'; -import { SavedState } from '../types'; -import { deepClone } from './common'; +import { CalculatedColumn } from '@supabase/react-data-grid' +import { ADD_COLUMN_KEY, SELECT_COLUMN_KEY } from '../constants' +import { SavedState } from '../types' +import { deepClone } from './common' export function cloneColumn(column: CalculatedColumn) { - const cloned = deepClone(column); + const cloned = deepClone(column) // these properties can't be cloned. Need to manual re-set again - cloned.editor = column.editor; - cloned.headerRenderer = column.headerRenderer; - cloned.formatter = column.formatter; - return cloned; + cloned.editor = column.editor + cloned.headerRenderer = column.headerRenderer + cloned.formatter = column.formatter + return cloned } export function getInitialGridColumns( gridColumns: CalculatedColumn[], savedState?: SavedState ) { - let result = gridColumns; + let result = gridColumns if (savedState?.gridColumns) { - result = []; + result = [] // filter utility columns select, add-column - const stateColumnsFiltered = savedState.gridColumns.filter( - (x) => x?.name !== '' - ); + const stateColumnsFiltered = savedState.gridColumns.filter((x) => x?.name !== '') for (let i = 0; i < stateColumnsFiltered.length; i++) { - const state = stateColumnsFiltered[i]; - const found = gridColumns.find((y) => y.key === state.key); + const state = stateColumnsFiltered[i] + const found = gridColumns.find((y) => y.key === state.key) // merge with savedState item props: width - if (found) - result.push({ ...found, width: state.width, frozen: state.frozen }); + if (found) result.push({ ...found, width: state.width, frozen: state.frozen }) } // check for newly created columns const newGridColumns = gridColumns.filter((x) => { // no existed in stateColumnsFiltered and not utility column - const found = stateColumnsFiltered.find((state) => state.key === x.key); - return !found && x.name !== ''; - }); - result = result.concat(newGridColumns); + const found = stateColumnsFiltered.find((state) => state.key === x.key) + return !found && x.name !== '' + }) + result = result.concat(newGridColumns) // process utility columns - const selectColumn = gridColumns.find((x) => x.key === SELECT_COLUMN_KEY); + const selectColumn = gridColumns.find((x) => x.key === SELECT_COLUMN_KEY) if (selectColumn) { - result = [selectColumn, ...result]; + result = [selectColumn, ...result] } - const addColumn = gridColumns.find((x) => x.key === ADD_COLUMN_KEY); + const addColumn = gridColumns.find((x) => x.key === ADD_COLUMN_KEY) if (addColumn) { - result.push(addColumn); + result.push(addColumn) } } - return result; + return result } diff --git a/studio/components/grid/utils/common.ts b/studio/components/grid/utils/common.ts index 83fdec70d23..2bb720a1e6e 100644 --- a/studio/components/grid/utils/common.ts +++ b/studio/components/grid/utils/common.ts @@ -1,57 +1,53 @@ -import { SupaColumn, SupaRow } from '../types'; +import { SupaColumn, SupaRow } from '../types' export function deepClone(obj: unknown) { try { - return JSON.parse(JSON.stringify(obj)); + return JSON.parse(JSON.stringify(obj)) } catch (e) { - throw e; + throw e } } -export function exportRowsToCsv( - columns: SupaColumn[], - rows: SupaRow[], - separator: string = ',' -) { - const keys = columns.map(x => x.name) || []; +export function exportRowsToCsv(columns: SupaColumn[], rows: SupaRow[], separator: string = ',') { + const keys = columns.map((x) => x.name) || [] const csv = keys.join(separator) + '\n' + rows - .map(row => { + .map((row) => { return keys - .map(k => { - let cell = row[k] === null || row[k] === undefined ? '' : row[k]; + .map((k) => { + let cell = row[k] === null || row[k] === undefined ? '' : row[k] cell = cell instanceof Date ? cell.toLocaleString() : typeof cell == 'object' || Array.isArray(cell) ? JSON.stringify(cell).replace(/"/g, '""') - : cell.toString().replace(/"/g, '""'); + : cell.toString().replace(/"/g, '""') if (cell.search(/("|,|\n)/g) >= 0) { - cell = `"${cell}"`; + cell = `"${cell}"` } - return cell; + return cell }) - .join(separator); + .join(separator) }) - .join('\n'); - return csv; + .join('\n') + return csv } export function formatClipboardValue(value: any) { - if (value === null) return ''; + if (value === null) return '' if (typeof value == 'object' || Array.isArray(value)) { - return JSON.stringify(value); + return JSON.stringify(value) } - return value; + return value } export const copyToClipboard = (str: string, callback = () => {}) => { - const focused = window.document.hasFocus(); + const focused = window.document.hasFocus() if (focused) { - window.navigator?.clipboard?.writeText(str).then(callback); + window.navigator?.clipboard?.writeText(str).then(callback) } else { - console.warn('Unable to copy to clipboard'); + console.warn('Unable to copy to clipboard') } -}; +} diff --git a/studio/components/grid/utils/gridColumns.tsx b/studio/components/grid/utils/gridColumns.tsx index 200a92eb397..978d4c3ca08 100644 --- a/studio/components/grid/utils/gridColumns.tsx +++ b/studio/components/grid/utils/gridColumns.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; -import { CalculatedColumn } from '@supabase/react-data-grid'; -import { ColumnType, SupaColumn, SupaRow, SupaTable } from '../types'; +import * as React from 'react' +import { CalculatedColumn } from '@supabase/react-data-grid' +import { ColumnType, SupaColumn, SupaRow, SupaTable } from '../types' import { isArrayColumn, isBoolColumn, @@ -12,7 +12,7 @@ import { isNumericalColumn, isTextColumn, isTimeColumn, -} from './types'; +} from './types' import { BooleanEditor, DateEditor, @@ -25,25 +25,21 @@ import { TextEditor, TimeEditor, TimeWithTimezoneEditor, -} from '../components/editor'; -import { AddColumn, ColumnHeader, SelectColumn } from '../components/grid'; -import { COLUMN_MIN_WIDTH } from '../constants'; -import { - BooleanFormatter, - DefaultFormatter, - ForeignKeyFormatter, -} from '../components/formatter'; +} from '../components/editor' +import { AddColumn, ColumnHeader, SelectColumn } from '../components/grid' +import { COLUMN_MIN_WIDTH } from '../constants' +import { BooleanFormatter, DefaultFormatter, ForeignKeyFormatter } from '../components/formatter' export function getGridColumns( table: SupaTable, options?: { - editable?: boolean; - defaultWidth?: string | number; - onAddColumn?: () => void; + editable?: boolean + defaultWidth?: string | number + onAddColumn?: () => void } ): any[] { const columns = table.columns.map((x, idx) => { - const columnType = getColumnType(x); + const columnType = getColumnType(x) const columnDefinition: CalculatedColumn = { key: x.name, name: x.name, @@ -65,61 +61,55 @@ export function getGridColumns( ), editor: options?.editable ? getColumnEditor(x, columnType) : undefined, formatter: getColumnFormatter(x, columnType), - }; + } - return columnDefinition; - }); + return columnDefinition + }) - const gridColumns = [SelectColumn, ...columns]; + const gridColumns = [SelectColumn, ...columns] if (options?.onAddColumn) { - gridColumns.push(AddColumn); + gridColumns.push(AddColumn) } - return gridColumns; + return gridColumns } function getColumnEditor(columnDefinition: SupaColumn, columnType: ColumnType) { if (columnDefinition.isPrimaryKey || !columnDefinition.isUpdatable) { - return; + return } switch (columnType) { case 'boolean': { - return columnDefinition.isNullable - ? NullableBooleanEditor - : BooleanEditor; + return columnDefinition.isNullable ? NullableBooleanEditor : BooleanEditor } case 'date': { - return DateEditor; + return DateEditor } case 'datetime': { - return columnDefinition.format.endsWith('z') - ? DateTimeWithTimezoneEditor - : DateTimeEditor; + return columnDefinition.format.endsWith('z') ? DateTimeWithTimezoneEditor : DateTimeEditor } case 'time': { - return columnDefinition.format.endsWith('z') - ? TimeWithTimezoneEditor - : TimeEditor; + return columnDefinition.format.endsWith('z') ? TimeWithTimezoneEditor : TimeEditor } case 'enum': { const options = columnDefinition.enum!.map((x) => { - return { label: x, value: x }; - }); - return (p: any) => ; + return { label: x, value: x } + }) + return (p: any) => } case 'array': case 'json': { - return JsonEditor; + return JsonEditor } case 'number': { - return NumberEditor; + return NumberEditor } case 'text': { - return TextEditor; + return TextEditor } default: { - return undefined; + return undefined } } } @@ -127,57 +117,57 @@ function getColumnEditor(columnDefinition: SupaColumn, columnType: ColumnType) { function getColumnFormatter(columnDef: SupaColumn, columnType: ColumnType) { switch (columnType) { case 'boolean': { - return BooleanFormatter; + return BooleanFormatter } case 'foreign_key': { if (columnDef.isPrimaryKey || !columnDef.isUpdatable) { - return DefaultFormatter; + return DefaultFormatter } else { - return ForeignKeyFormatter; + return ForeignKeyFormatter } } default: { - return DefaultFormatter; + return DefaultFormatter } } } function getColumnType(columnDef: SupaColumn): ColumnType { if (isForeignKeyColumn(columnDef)) { - return 'foreign_key'; + return 'foreign_key' } else if (isNumericalColumn(columnDef.dataType)) { - return 'number'; + return 'number' } else if (isArrayColumn(columnDef.dataType)) { - return 'array'; + return 'array' } else if (isJsonColumn(columnDef.dataType)) { - return 'json'; + return 'json' } else if (isTextColumn(columnDef.dataType)) { - return 'text'; + return 'text' } else if (isDateColumn(columnDef.format)) { - return 'date'; + return 'date' } else if (isTimeColumn(columnDef.format)) { - return 'time'; + return 'time' } else if (isDateTimeColumn(columnDef.format)) { - return 'datetime'; + return 'datetime' } else if (isBoolColumn(columnDef.dataType)) { - return 'boolean'; + return 'boolean' } else if (isEnumColumn(columnDef.dataType)) { - return 'enum'; - } else return 'unknown'; + return 'enum' + } else return 'unknown' } function getColumnWidth(columnDef: SupaColumn): string | number | undefined { if (isNumericalColumn(columnDef.dataType)) { - return 120; + return 120 } else if ( isDateTimeColumn(columnDef.format) || isDateColumn(columnDef.format) || isTimeColumn(columnDef.format) ) { - return 150; + return 150 } else if (isBoolColumn(columnDef.dataType)) { - return 120; + return 120 } else if (isEnumColumn(columnDef.dataType)) { - return 150; - } else return 250; + return 150 + } else return 250 } diff --git a/studio/components/grid/utils/hooks.tsx b/studio/components/grid/utils/hooks.tsx index 724a77c3b52..9614449501d 100644 --- a/studio/components/grid/utils/hooks.tsx +++ b/studio/components/grid/utils/hooks.tsx @@ -1,13 +1,11 @@ -import * as React from 'react'; +import * as React from 'react' -export function useFocusRef( - isCellSelected: boolean -) { - const ref = React.useRef(null); +export function useFocusRef(isCellSelected: boolean) { + const ref = React.useRef(null) React.useLayoutEffect(() => { - if (!isCellSelected) return; - ref.current?.focus({ preventScroll: true }); - }, [isCellSelected]); + if (!isCellSelected) return + ref.current?.focus({ preventScroll: true }) + }, [isCellSelected]) - return ref; + return ref } diff --git a/studio/components/grid/utils/types.ts b/studio/components/grid/utils/types.ts index a8144b6a3a7..314842196a8 100644 --- a/studio/components/grid/utils/types.ts +++ b/studio/components/grid/utils/types.ts @@ -1,4 +1,4 @@ -import { SupaColumn } from '../types'; +import { SupaColumn } from '../types' const NUMERICAL_TYPES = [ 'smallint', @@ -19,52 +19,52 @@ const NUMERICAL_TYPES = [ 'serial2', 'serial4', 'serial8', -]; +] export function isNumericalColumn(type: string) { - return NUMERICAL_TYPES.indexOf(type.toLowerCase()) > -1; + return NUMERICAL_TYPES.indexOf(type.toLowerCase()) > -1 } -const JSON_TYPES = ['json', 'jsonb', 'array']; +const JSON_TYPES = ['json', 'jsonb', 'array'] export function isJsonColumn(type: string) { - return JSON_TYPES.indexOf(type.toLowerCase()) > -1; + return JSON_TYPES.indexOf(type.toLowerCase()) > -1 } -const ARRAY_TYPES = ['array']; +const ARRAY_TYPES = ['array'] export function isArrayColumn(type: string) { - return ARRAY_TYPES.indexOf(type.toLowerCase()) > -1; + return ARRAY_TYPES.indexOf(type.toLowerCase()) > -1 } -const TEXT_TYPES = ['text', 'character varying']; +const TEXT_TYPES = ['text', 'character varying'] export function isTextColumn(type: string) { - return TEXT_TYPES.indexOf(type.toLowerCase()) > -1; + return TEXT_TYPES.indexOf(type.toLowerCase()) > -1 } -const TIMESTAMP_TYPES = ['timestamp', 'timestamptz']; +const TIMESTAMP_TYPES = ['timestamp', 'timestamptz'] export function isDateTimeColumn(type: string) { - return TIMESTAMP_TYPES.indexOf(type.toLowerCase()) > -1; + return TIMESTAMP_TYPES.indexOf(type.toLowerCase()) > -1 } -const DATE_TYPES = ['date']; +const DATE_TYPES = ['date'] export function isDateColumn(type: string) { - return DATE_TYPES.indexOf(type.toLowerCase()) > -1; + return DATE_TYPES.indexOf(type.toLowerCase()) > -1 } -const TIME_TYPES = ['time', 'timetz']; +const TIME_TYPES = ['time', 'timetz'] export function isTimeColumn(type: string) { - return TIME_TYPES.indexOf(type.toLowerCase()) > -1; + return TIME_TYPES.indexOf(type.toLowerCase()) > -1 } -const BOOL_TYPES = ['boolean', 'bool']; +const BOOL_TYPES = ['boolean', 'bool'] export function isBoolColumn(type: string) { - return BOOL_TYPES.indexOf(type.toLowerCase()) > -1; + return BOOL_TYPES.indexOf(type.toLowerCase()) > -1 } -const ENUM_TYPES = ['user-defined']; +const ENUM_TYPES = ['user-defined'] export function isEnumColumn(type: string) { - return ENUM_TYPES.indexOf(type.toLowerCase()) > -1; + return ENUM_TYPES.indexOf(type.toLowerCase()) > -1 } export function isForeignKeyColumn(columnDef: SupaColumn) { - const { targetTableSchema, targetTableName, targetColumnName } = columnDef; - return !!targetTableSchema && !!targetTableName && !!targetColumnName; + const { targetTableSchema, targetTableName, targetColumnName } = columnDef + return !!targetTableSchema && !!targetTableName && !!targetColumnName } diff --git a/studio/components/interfaces/Database/Pooling/ConnectionPooling.tsx b/studio/components/interfaces/Database/Pooling/ConnectionPooling.tsx index fce56c5dabe..c5598732a16 100644 --- a/studio/components/interfaces/Database/Pooling/ConnectionPooling.tsx +++ b/studio/components/interfaces/Database/Pooling/ConnectionPooling.tsx @@ -48,14 +48,16 @@ const ConnectionPooling: FC = () => { if (!project.pgbouncer_enabled && project.pool_mode == null) return ( - Connection Pooling is not available for this project - - } - > + title={ + + Connection Pooling is not available for this project + + } + > - Please start a new project to enable this feature. + + Please start a new project to enable this feature. + ) @@ -71,7 +73,11 @@ const ConnectionPooling: FC = () => { const bouncerInfo = pluckObjectFields(formModel, BOUNCER_FIELDS) return ( - + ) } @@ -79,140 +85,152 @@ export default observer(ConnectionPooling) interface ConfigProps { projectRef: string - bouncerInfo: {default_pool_size: number, ignore_startup_parameters: 'string', pool_mode: string, pgbouncer_enabled: boolean}, - connectionInfo: {db_host: string, db_name: string, db_port: number, db_user: string, inserted_at: string} + bouncerInfo: { + default_pool_size: number + ignore_startup_parameters: 'string' + pool_mode: string + pgbouncer_enabled: boolean + } + connectionInfo: { + db_host: string + db_name: string + db_port: number + db_user: string + inserted_at: string + } } -export const PgbouncerConfig: FC = observer(({ projectRef, bouncerInfo, connectionInfo }) => { +export const PgbouncerConfig: FC = observer( + ({ projectRef, bouncerInfo, connectionInfo }) => { + const { ui } = useStore() - const { ui } = useStore() + const [updates, setUpdates] = useState({ + pgbouncer_enabled: bouncerInfo.pgbouncer_enabled, + pool_mode: bouncerInfo.pool_mode || 'transaction', + default_pool_size: bouncerInfo.default_pool_size || '', + ignore_startup_parameters: bouncerInfo.ignore_startup_parameters || '', + }) - const [updates, setUpdates] = useState({ - pgbouncer_enabled: bouncerInfo.pgbouncer_enabled, - pool_mode: bouncerInfo.pool_mode || 'transaction', - default_pool_size: bouncerInfo.default_pool_size || '', - ignore_startup_parameters: bouncerInfo.ignore_startup_parameters || '', - }) - - const updateConfig = async (updatedConfig: any) => { - try { - const response = await patch(`${API_URL}/props/pooling/${projectRef}/config`, updatedConfig) - if (response.error) { - throw response.error - } else { - setUpdates({ ...response.project }) - ui.setNotification({ category: 'success', message: 'Successfully saved settings' }) + const updateConfig = async (updatedConfig: any) => { + try { + const response = await patch(`${API_URL}/props/pooling/${projectRef}/config`, updatedConfig) + if (response.error) { + throw response.error + } else { + setUpdates({ ...response.project }) + ui.setNotification({ category: 'success', message: 'Successfully saved settings' }) + } + } catch (error: any) { + ui.setNotification({ + category: 'error', + message: `Failed to update config: ${error.message}`, + }) } - } catch (error: any) { - ui.setNotification({ - category: 'error', - message: `Failed to update config: ${error.message}`, - }) } + + const formSchema = { + properties: { + pgbouncer_enabled: { + title: 'Enabled', + type: 'boolean', + help: 'Activates / deactivates Connection Pooling.', + }, + pool_mode: { + title: 'Pool Mode', + type: 'string', + options: [ + { + label: 'Transaction', + value: 'transaction', + }, + { + label: 'Session', + value: 'session', + }, + { + label: 'Statement', + value: 'statement', + }, + ], + }, + ignore_startup_parameters: { + title: 'Ignore Startup Parameters', + type: 'string', + readOnly: true, + help: 'Defaults are either blank or "extra_float_digits"', + }, + }, + required: ['pool_mode'], + type: 'object', + } + + return ( + setUpdates(model)} + onSubmit={(model: any) => updateConfig(model)} + onReset={() => setUpdates(bouncerInfo)} + > +
+ + + + + {updates.pgbouncer_enabled && ( + <> + +
+

+ Specify when a connection can be returned to the pool. To find out the most + suitable mode for your use case,{' '} + + click here + + . +

+
+ + + + )} + + + + +
+
+ ) } - - const formSchema = { - properties: { - pgbouncer_enabled: { - title: 'Enabled', - type: 'boolean', - help: 'Activates / deactivates Connection Pooling.', - }, - pool_mode: { - title: 'Pool Mode', - type: 'string', - options: [ - { - label: 'Transaction', - value: 'transaction', - }, - { - label: 'Session', - value: 'session', - }, - { - label: 'Statement', - value: 'statement', - }, - ], - }, - ignore_startup_parameters: { - title: 'Ignore Startup Parameters', - type: 'string', - readOnly: true, - help: 'Defaults are either blank or "extra_float_digits"', - }, - }, - required: ['pool_mode'], - type: 'object', - } - - return ( - setUpdates(model)} - onSubmit={(model: any) => updateConfig(model)} - onReset={() => setUpdates(bouncerInfo)} - > -
- - - - - {updates.pgbouncer_enabled && ( - <> - -
-

- Specify when a connection can be returned to the pool. To find out the most - suitable mode for your use case,{' '} - - click here - - . -

-
- - - - )} - - - - -
-
- ) -}) +) diff --git a/studio/components/interfaces/Home/ExampleProject.tsx b/studio/components/interfaces/Home/ExampleProject.tsx index e81b5d27f0a..568acc4674a 100644 --- a/studio/components/interfaces/Home/ExampleProject.tsx +++ b/studio/components/interfaces/Home/ExampleProject.tsx @@ -16,7 +16,7 @@ const ExampleProject: FC = ({ framework, title, description, url }) => { return ( - +
= ({ framework, title, description, url }) => {
{`${framework} = ({ data, onBarClick }) => { data={aggregated} attribute="count" label="Events" - onBarClick={(v?: {activePayload?: {payload: any}[]}) => { + onBarClick={(v?: { activePayload?: { payload: any }[] }) => { if (!v || !v?.activePayload?.[0]?.payload) return const timestamp = v.activePayload[0].payload.timestamp // 60s before diff --git a/studio/components/interfaces/Settings/Logs/LogSelection.tsx b/studio/components/interfaces/Settings/Logs/LogSelection.tsx index 60f8edc5a2d..cbbcbd29373 100644 --- a/studio/components/interfaces/Settings/Logs/LogSelection.tsx +++ b/studio/components/interfaces/Settings/Logs/LogSelection.tsx @@ -40,7 +40,6 @@ const LogSelection: FC = ({ log, onClose, queryType, isLoading }) => { break default: - if (log && isDefaultLogPreviewFormat(log)) { return } diff --git a/studio/components/interfaces/Settings/Logs/LogSelectionRenderers/FunctionInvocationSelectionRender.tsx b/studio/components/interfaces/Settings/Logs/LogSelectionRenderers/FunctionInvocationSelectionRender.tsx index 8f5bc84e5dc..4256bb514ff 100644 --- a/studio/components/interfaces/Settings/Logs/LogSelectionRenderers/FunctionInvocationSelectionRender.tsx +++ b/studio/components/interfaces/Settings/Logs/LogSelectionRenderers/FunctionInvocationSelectionRender.tsx @@ -24,7 +24,11 @@ const FunctionInvocationSelectionRender = ({ log }: any) => { return (
{label} - + {value}
diff --git a/studio/components/interfaces/Settings/Logs/Logs.DatePickers.tsx b/studio/components/interfaces/Settings/Logs/Logs.DatePickers.tsx index c53b8677b0d..ed4fb75d0d8 100644 --- a/studio/components/interfaces/Settings/Logs/Logs.DatePickers.tsx +++ b/studio/components/interfaces/Settings/Logs/Logs.DatePickers.tsx @@ -7,7 +7,7 @@ import { DatetimeHelper, getDefaultHelper, LOGS_LARGE_DATE_RANGE_DAYS_THRESHOLD interface Props { to: string from: string - onChange: React.ComponentProps["onChange"] + onChange: React.ComponentProps['onChange'] helpers: DatetimeHelper[] } const DatePickers: React.FC = ({ to, from, onChange, helpers }) => { @@ -73,9 +73,13 @@ const DatePickers: React.FC = ({ to, from, onChange, helpers }) => { to={!helperValue ? to : undefined} from={!helperValue ? from : undefined} renderFooter={({ to, from }) => { - if (to && from && Math.abs(dayjs(from).diff(dayjs(to), 'day')) > LOGS_LARGE_DATE_RANGE_DAYS_THRESHOLD) { + if ( + to && + from && + Math.abs(dayjs(from).diff(dayjs(to), 'day')) > LOGS_LARGE_DATE_RANGE_DAYS_THRESHOLD + ) { return ( - + Large ranges may result in memory errors for big projects. ) diff --git a/studio/components/interfaces/Settings/Logs/Logs.SqlSnippetCode.tsx b/studio/components/interfaces/Settings/Logs/Logs.SqlSnippetCode.tsx index 465be25e72e..fee91e43620 100644 --- a/studio/components/interfaces/Settings/Logs/Logs.SqlSnippetCode.tsx +++ b/studio/components/interfaces/Settings/Logs/Logs.SqlSnippetCode.tsx @@ -1,6 +1,5 @@ - -const SqlSnippetCode: React.FC = ({ children }) =>( +const SqlSnippetCode: React.FC = ({ children }) => (
{children}
) -export default SqlSnippetCode; \ No newline at end of file +export default SqlSnippetCode diff --git a/studio/components/interfaces/Settings/Logs/Logs.types.ts b/studio/components/interfaces/Settings/Logs/Logs.types.ts index 276778d3740..c6c60123672 100644 --- a/studio/components/interfaces/Settings/Logs/Logs.types.ts +++ b/studio/components/interfaces/Settings/Logs/Logs.types.ts @@ -1,4 +1,4 @@ -import React from "react" +import React from 'react' interface Metadata { [key: string]: string | number | Object | Object[] @@ -59,7 +59,7 @@ export type Count = LFResponse export type Logs = LFResponse -export type QueryType = 'api' | 'database' | 'functions' | 'fn_edge' | "auth" +export type QueryType = 'api' | 'database' | 'functions' | 'fn_edge' | 'auth' export type Mode = 'simple' | 'custom' diff --git a/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx b/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx index ab4f139581b..6eb2977f558 100644 --- a/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx +++ b/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx @@ -168,7 +168,7 @@ export const LogsPreviewer: React.FC = ({ - +
)} {error && ( diff --git a/studio/components/interfaces/Settings/Logs/RecentQueriesItem.tsx b/studio/components/interfaces/Settings/Logs/RecentQueriesItem.tsx index 2094958288b..5d6a7532283 100644 --- a/studio/components/interfaces/Settings/Logs/RecentQueriesItem.tsx +++ b/studio/components/interfaces/Settings/Logs/RecentQueriesItem.tsx @@ -13,26 +13,24 @@ const RecentQueriesItem: React.FC = ({ item }) => { const { ref } = router.query return ( - - + + {item.sql} + + + - - + Run + + + ) } diff --git a/studio/components/interfaces/Settings/Logs/index.ts b/studio/components/interfaces/Settings/Logs/index.ts index a6ebf8dac2d..3b642f686dd 100644 --- a/studio/components/interfaces/Settings/Logs/index.ts +++ b/studio/components/interfaces/Settings/Logs/index.ts @@ -5,4 +5,4 @@ export { default as LogsSavedQueriesItem } from './Logs.SavedQueriesItem' export { default as LogsQueryPanel } from './LogsQueryPanel' export { default as LogTable } from './LogTable' export { default as LogEventChart } from './LogEventChart' -export { default as LogsFilterPopover } from "./LogsFilterPopover" \ No newline at end of file +export { default as LogsFilterPopover } from './LogsFilterPopover' diff --git a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index d6aa813cbdb..f79f86b6d34 100644 --- a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -17,11 +17,18 @@ const GridHeaderActions: FC = ({ table }) => { return (
- +
) diff --git a/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/index.tsx b/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/index.tsx index b1edc82c6ae..29f19f4a857 100644 --- a/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/index.tsx +++ b/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/index.tsx @@ -1,7 +1,11 @@ import { FC, Fragment, useState } from 'react' import { useRouter } from 'next/router' import { Button, IconBell, Popover } from '@supabase/ui' -import { Notification, NotificationStatus, ActionType } from '@supabase/shared-types/out/notifications' +import { + Notification, + NotificationStatus, + ActionType, +} from '@supabase/shared-types/out/notifications' import { Project } from 'types' import { useNotifications, useStore } from 'hooks' @@ -48,7 +52,7 @@ const NotificationsPopover: FC = () => { const { id: projectId, ref, region } = projectToRestart const serviceNamesByActionName: Record = { [ActionType.PgBouncerRestart]: 'pgbouncer', - [ActionType.SchedulePostgresRestart]: 'postgresql' + [ActionType.SchedulePostgresRestart]: 'postgresql', } const services: string[] = targetNotification.meta.actions_available .map((action) => action.action_type) diff --git a/studio/components/to-be-cleaned/Charts/ChartHandler.tsx b/studio/components/to-be-cleaned/Charts/ChartHandler.tsx index 1c5519e67ab..7e2b16a16a4 100644 --- a/studio/components/to-be-cleaned/Charts/ChartHandler.tsx +++ b/studio/components/to-be-cleaned/Charts/ChartHandler.tsx @@ -128,7 +128,7 @@ const ChartHandler: FC = ({ ? chartData?.total : provider === 'log-stats' ? chartData?.totalGrouped?.[attribute] - : chartData?.data[chartData?.data.length -1]?.[attribute] + : chartData?.data[chartData?.data.length - 1]?.[attribute] if (loading) { return ( diff --git a/studio/components/to-be-cleaned/Docs/Pages/UserManagement.js b/studio/components/to-be-cleaned/Docs/Pages/UserManagement.js index 5f6a8f8e113..29b37f763b1 100644 --- a/studio/components/to-be-cleaned/Docs/Pages/UserManagement.js +++ b/studio/components/to-be-cleaned/Docs/Pages/UserManagement.js @@ -156,8 +156,8 @@ export default function UserManagement({ autoApiService, selectedLang, showApiKe

- Users can log in with Third Party OAuth like Google, Facebook, GitHub, and more. You must - first enable each of these in the{' '} + Users can log in with Third Party OAuth like Google, Facebook, GitHub, and more. You + must first enable each of these in the{' '} Auth Settings @@ -166,7 +166,10 @@ export default function UserManagement({ autoApiService, selectedLang, showApiKe tab.

- Vew all the available Third Part OAuth providers + Vew all the available{' '} + + Third Part OAuth providers +

After they have logged in, all interactions using the Supabase JS client will be diff --git a/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.js b/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.js index 38e81fe71ee..8209a9efc95 100644 --- a/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.js +++ b/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.js @@ -15,7 +15,8 @@ import { IconX, IconEdit2, IconLoader, - Typography, IconChevronsUp, + Typography, + IconChevronsUp, } from '@supabase/ui' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' import { STORAGE_VIEWS, STORAGE_SORT_BY, STORAGE_SORT_BY_ORDER } from '../Storage.constants.ts' @@ -334,7 +335,11 @@ const FileExplorerHeader = ({ + Asc Desc , @@ -342,7 +347,13 @@ const FileExplorerHeader = ({ > + : 'This is the password to your postgres database, so it must be a strong password and hard to guess.'}{' '} + ) diff --git a/studio/components/ui/SqlEditor.tsx b/studio/components/ui/SqlEditor.tsx index c7a83688f3a..77ac9a755bf 100644 --- a/studio/components/ui/SqlEditor.tsx +++ b/studio/components/ui/SqlEditor.tsx @@ -4,12 +4,12 @@ import { Typography } from '@supabase/ui' import { useStore } from 'hooks' interface Props { - contextmenu?: boolean; - defaultValue?: string; - language?: string; - onInputChange?: OnChange; - queryId?: string; - readOnly?: boolean; + contextmenu?: boolean + defaultValue?: string + language?: string + onInputChange?: OnChange + queryId?: string + readOnly?: boolean } const SqlEditor: FC = ({ diff --git a/studio/hooks/analytics/useLogsQuery.tsx b/studio/hooks/analytics/useLogsQuery.tsx index 4806f481013..310a3903af6 100644 --- a/studio/hooks/analytics/useLogsQuery.tsx +++ b/studio/hooks/analytics/useLogsQuery.tsx @@ -28,8 +28,12 @@ const useLogsQuery = ( const [params, setParams] = useState({ sql: '', project: projectRef, - iso_timestamp_start: initialParams.iso_timestamp_start ? initialParams.iso_timestamp_start : defaultHelper.calcFrom(), - iso_timestamp_end: initialParams.iso_timestamp_end ? initialParams.iso_timestamp_end : defaultHelper.calcTo(), + iso_timestamp_start: initialParams.iso_timestamp_start + ? initialParams.iso_timestamp_start + : defaultHelper.calcFrom(), + iso_timestamp_end: initialParams.iso_timestamp_end + ? initialParams.iso_timestamp_end + : defaultHelper.calcTo(), }) const queryParams = genQueryParams(params as any) diff --git a/studio/hooks/queries/useProjectPaygStatistics.ts b/studio/hooks/queries/useProjectPaygStatistics.ts index ee4507ff5e4..3af268448ac 100644 --- a/studio/hooks/queries/useProjectPaygStatistics.ts +++ b/studio/hooks/queries/useProjectPaygStatistics.ts @@ -50,12 +50,16 @@ function getPaygStats(data: any): PaygStats { let dataModified: any = [] data.map((x: any) => { - dataModified.push({ ...x, total_egress_modified: (x.total_egress == undefined ? 0 : x.total_egress) - (x.total_storage_egress == undefined ? 0 : x.total_storage_egress) }) + dataModified.push({ + ...x, + total_egress_modified: + (x.total_egress == undefined ? 0 : x.total_egress) - + (x.total_storage_egress == undefined ? 0 : x.total_storage_egress), + }) }) chargeableProducts.forEach((product) => { product.features.forEach((feature) => { - // calculate max const max = _get(maxBy(dataModified, feature.attribute), feature.attribute) ?? 0 diff --git a/studio/jest.config.js b/studio/jest.config.js index b07758343ba..cb7f3c95b01 100644 --- a/studio/jest.config.js +++ b/studio/jest.config.js @@ -1,13 +1,13 @@ module.exports = { moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], moduleDirectories: ['', 'node_modules'], - setupFiles: ["jest-canvas-mock", "./tests/setup/radix"], + setupFiles: ['jest-canvas-mock', './tests/setup/radix'], testEnvironment: 'jsdom', testRegex: '(.*\\.test.(js|jsx|ts|tsx)$)', transform: { '^.+\\.(t|j)sx?$': 'ts-jest' }, globals: { 'ts-jest': { - tsconfig: 'tsconfig.test.json' - } - } + tsconfig: 'tsconfig.test.json', + }, + }, } diff --git a/studio/lib/gotrue.ts b/studio/lib/gotrue.ts index 5a711db5152..de73677ac57 100644 --- a/studio/lib/gotrue.ts +++ b/studio/lib/gotrue.ts @@ -1,6 +1,7 @@ import { GoTrueClient, User } from '@supabase/gotrue-js' -export const GOTRUE_URL = process.env.NEXT_PUBLIC_GOTRUE_URL || `${process.env.SUPABASE_URL}/auth/v1` +export const GOTRUE_URL = + process.env.NEXT_PUBLIC_GOTRUE_URL || `${process.env.SUPABASE_URL}/auth/v1` export const auth = new GoTrueClient({ url: GOTRUE_URL, diff --git a/studio/localStores/storageExplorer/StorageExplorerStore.js b/studio/localStores/storageExplorer/StorageExplorerStore.js index 9aaa6abf345..5474ac9a404 100644 --- a/studio/localStores/storageExplorer/StorageExplorerStore.js +++ b/studio/localStores/storageExplorer/StorageExplorerStore.js @@ -65,7 +65,11 @@ class StorageExplorerStore { selectedItemsToMove = [] selectedFilePreview = {} - DEFAULT_OPTIONS = { limit: LIMIT, offset: OFFSET, sortBy: { column: this.sortBy, order: this.sortByOrder } } + DEFAULT_OPTIONS = { + limit: LIMIT, + offset: OFFSET, + sortBy: { column: this.sortBy, order: this.sortByOrder }, + } /* Supabase client */ supabaseClient = null @@ -1134,10 +1138,10 @@ class StorageExplorerStore { const { error } = await this.supabaseClient.storage .from(this.selectedBucket.name) .move(fromPath, toPath) - if (error) { - hasErrors = true - toast.error(`Failed to move ${fromPath} to the new folder`) - } + if (error) { + hasErrors = true + toast.error(`Failed to move ${fromPath} to the new folder`) + } resolve() }) } @@ -1193,19 +1197,23 @@ class StorageExplorerStore { formattedPathToFolder = `${prefix}/${name}` } - const options = { limit: LIMIT, offset: OFFSET, sortBy: { column: this.sortBy, order: this.sortByOrder } } + const options = { + limit: LIMIT, + offset: OFFSET, + sortBy: { column: this.sortBy, order: this.sortByOrder }, + } let folderContents = [] - for (;;) { - const { data } = await this.supabaseClient.storage - .from(this.selectedBucket.name) - .list(formattedPathToFolder, options) - folderContents = folderContents.concat(data) - options.offset += options.limit - if (data.length < options.limit) { - break - } + for (;;) { + const { data } = await this.supabaseClient.storage + .from(this.selectedBucket.name) + .list(formattedPathToFolder, options) + folderContents = folderContents.concat(data) + options.offset += options.limit + if (data.length < options.limit) { + break } + } const subfolders = folderContents?.filter((item) => isNull(item.id)) ?? [] const folderItems = folderContents?.filter((item) => !isNull(item.id)) ?? [] diff --git a/studio/next.config.js b/studio/next.config.js index 629de76bc2d..302385c445a 100644 --- a/studio/next.config.js +++ b/studio/next.config.js @@ -60,7 +60,7 @@ const nextConfig = { ] }, images: { - domains: ['github.com'] + domains: ['github.com'], }, } diff --git a/studio/package-lock.json b/studio/package-lock.json index d912c0e883e..f7bb68ce929 100644 --- a/studio/package-lock.json +++ b/studio/package-lock.json @@ -108,6 +108,7 @@ "jest": "^27.4.0", "jest-canvas-mock": "^2.3.1", "postcss": "^8.4.6", + "prettier": "^2.7.1", "storybook-dark-mode": "^1.0.4", "tailwindcss": "^3.0.22", "ts-jest": "^27.0.7", @@ -5973,6 +5974,18 @@ "node": ">=8.9.0" } }, + "node_modules/@storybook/addon-essentials/node_modules/prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@storybook/addon-essentials/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7312,6 +7325,18 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/csf-tools/node_modules/prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@storybook/instrumenter": { "version": "6.4.19", "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.4.19.tgz", @@ -8128,6 +8153,18 @@ "node": ">=8.9.0" } }, + "node_modules/@storybook/source-loader/node_modules/prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@storybook/store": { "version": "6.4.19", "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.4.19.tgz", @@ -22382,15 +22419,18 @@ } }, "node_modules/prettier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/pretty-error": { @@ -33440,6 +33480,12 @@ "json5": "^2.1.2" } }, + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -34398,6 +34444,14 @@ "prettier": ">=2.2.1 <=2.3.0", "regenerator-runtime": "^0.13.7", "ts-dedent": "^2.0.0" + }, + "dependencies": { + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true + } } }, "@storybook/instrumenter": { @@ -34962,6 +35016,12 @@ "emojis-list": "^3.0.0", "json5": "^2.1.2" } + }, + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true } } }, @@ -46170,9 +46230,9 @@ "dev": true }, "prettier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true }, "pretty-error": { diff --git a/studio/package.json b/studio/package.json index 74955c82559..a9f6e5342ac 100644 --- a/studio/package.json +++ b/studio/package.json @@ -9,7 +9,9 @@ "test": "jest", "deploy:staging": "VERCEL_ORG_ID=team_E6KJ1W561hMTjon1QSwOh0WO VERCEL_PROJECT_ID=QmcmhbiAtCMFTAHCuGgQscNbke4TzgWULECctNcKmxWCoT vercel --prod -A .vercel/staging.json", "storybook": "start-storybook -p 6006", - "build-storybook": "build-storybook" + "build-storybook": "build-storybook", + "prettier:check": "prettier --check .", + "prettier:write": "prettier --write ." }, "dependencies": { "@headlessui/react": "^1.4.1", @@ -112,6 +114,7 @@ "jest": "^27.4.0", "jest-canvas-mock": "^2.3.1", "postcss": "^8.4.6", + "prettier": "^2.7.1", "storybook-dark-mode": "^1.0.4", "tailwindcss": "^3.0.22", "ts-jest": "^27.0.7", diff --git a/studio/pages/api/auth/[ref]/config.ts b/studio/pages/api/auth/[ref]/config.ts index 2a057163300..540bc005430 100644 --- a/studio/pages/api/auth/[ref]/config.ts +++ b/studio/pages/api/auth/[ref]/config.ts @@ -103,7 +103,7 @@ const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => { EXTERNAL_ZOOM_ENABLED: false, EXTERNAL_ZOOM_CLIENT_ID: null, EXTERNAL_ZOOM_SECRET: null, - + MAILER_SUBJECTS_INVITE: 'You have been invited', MAILER_SUBJECTS_CONFIRMATION: 'Confirm Your Signup', MAILER_SUBJECTS_RECOVERY: 'Reset Your Password', diff --git a/studio/pages/project/[ref]/functions/[id]/invocations.tsx b/studio/pages/project/[ref]/functions/[id]/invocations.tsx index d5bca274f48..9757e9a47a4 100644 --- a/studio/pages/project/[ref]/functions/[id]/invocations.tsx +++ b/studio/pages/project/[ref]/functions/[id]/invocations.tsx @@ -16,7 +16,7 @@ export const LogPage: NextPageWithLayout = () => { ) } diff --git a/studio/pages/project/[ref]/logs-explorer/index.tsx b/studio/pages/project/[ref]/logs-explorer/index.tsx index ad7e953faea..710ed9f8e99 100644 --- a/studio/pages/project/[ref]/logs-explorer/index.tsx +++ b/studio/pages/project/[ref]/logs-explorer/index.tsx @@ -35,8 +35,8 @@ export const LogsExplorerPage: NextPageWithLayout = () => { const [{ params, logData, error, isLoading }, { changeQuery, runQuery, setParams }] = useLogsQuery(ref as string, { - iso_timestamp_start: its ? its as string : undefined, - iso_timestamp_end: ite ? ite as string : undefined, + iso_timestamp_start: its ? (its as string) : undefined, + iso_timestamp_end: ite ? (ite as string) : undefined, }) useEffect(() => { diff --git a/studio/pages/project/[ref]/logs-explorer/recent.tsx b/studio/pages/project/[ref]/logs-explorer/recent.tsx index 424fd1cc3b2..edc8ae71d12 100644 --- a/studio/pages/project/[ref]/logs-explorer/recent.tsx +++ b/studio/pages/project/[ref]/logs-explorer/recent.tsx @@ -23,28 +23,27 @@ export const LogsSavedPage: NextPageWithLayout = () => { return ( <> {recent.length > 0 && ( - - Snippets - - - - - } - body={recent.map((item: LogSqlSnippets.Content) => ( - - )) - } - /> +
+ Snippets + + + + + } + body={recent.map((item: LogSqlSnippets.Content) => ( + + ))} + /> )} {recent.length === 0 && ( <> diff --git a/studio/pages/project/[ref]/settings/database.tsx b/studio/pages/project/[ref]/settings/database.tsx index c37f79a0e09..67e06b87f14 100644 --- a/studio/pages/project/[ref]/settings/database.tsx +++ b/studio/pages/project/[ref]/settings/database.tsx @@ -49,7 +49,7 @@ export default observer(ProjectSettings) const Usage: FC = ({ project }) => { const [dateRange, setDateRange] = useState(undefined) const router = useRouter() - const ref = router.query.ref as string; + const ref = router.query.ref as string return ( <> diff --git a/studio/styles/editor.scss b/studio/styles/editor.scss index 79a9780187d..493f4e66af1 100644 --- a/studio/styles/editor.scss +++ b/studio/styles/editor.scss @@ -20,4 +20,4 @@ .column-type-disabled .sbui-listbox-label { @apply opacity-50; -} \ No newline at end of file +} diff --git a/studio/styles/grid.scss b/studio/styles/grid.scss index 14f190e2c30..bbca5f35d16 100644 --- a/studio/styles/grid.scss +++ b/studio/styles/grid.scss @@ -707,4 +707,3 @@ header/sort/SortRow .sb-grid-sort-row__item__move { @apply flex cursor-move; } - diff --git a/studio/tests/fixtures.ts b/studio/tests/fixtures.ts index ef0c012d015..ba88b7fdbe8 100644 --- a/studio/tests/fixtures.ts +++ b/studio/tests/fixtures.ts @@ -1,9 +1,9 @@ -import { LogData } from "components/interfaces/Settings/Logs"; +import { LogData } from 'components/interfaces/Settings/Logs' export const logDataFixture = (attrs: Partial): LogData => ({ id: `some-uuid-${new Date().getTime()}`, timestamp: new Date().getTime() * 1000, event_message: 'first event', metadata: {}, - ...attrs -}) \ No newline at end of file + ...attrs, +}) diff --git a/studio/tests/pages/projects/LogTable.test.js b/studio/tests/pages/projects/LogTable.test.js index 458aa84a6f0..4b2dd8a53a2 100644 --- a/studio/tests/pages/projects/LogTable.test.js +++ b/studio/tests/pages/projects/LogTable.test.js @@ -64,14 +64,13 @@ test('toggle histogram', async () => { expect(mockFn).toBeCalled() }) - test('error message handling', async () => { - const {rerender} = render() - await expect(screen.findByText("some \nstring")).rejects.toThrow() + const { rerender } = render() + await expect(screen.findByText('some \nstring')).rejects.toThrow() await screen.findByDisplayValue(/some/) await screen.findByDisplayValue(/string/) - rerender() + rerender() await screen.findByText(/some \\nstring/) await screen.findByText(/some/) await screen.findByText(/string/) diff --git a/studio/tests/pages/projects/PreviewFilterPanel.test.js b/studio/tests/pages/projects/PreviewFilterPanel.test.js index 64f6a249da9..1808d4119eb 100644 --- a/studio/tests/pages/projects/PreviewFilterPanel.test.js +++ b/studio/tests/pages/projects/PreviewFilterPanel.test.js @@ -94,10 +94,7 @@ test.todo('timestamp to/from filter value change') // await screen.findByTitle(/Clear timestamp filter/) // }) - - test('shortened count to K', async () => { render() await screen.findByText(/1\.2K/) }) - diff --git a/studio/types/userContent.ts b/studio/types/userContent.ts index f7e9e755d7e..24e4a25c382 100644 --- a/studio/types/userContent.ts +++ b/studio/types/userContent.ts @@ -1,4 +1,6 @@ -export interface UserContent { +export interface UserContent< + T = Dashboards.Content | SqlSnippets.Content | LogSqlSnippets.Content +> { id?: string name: string description?: string