mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
Shift refresh button to header in table editor and make realtime + API docs button smaller (#38463)
* Shift refresh button to header in table editor and make realtime button + api docs button smaller * Fix ts
This commit is contained in:
1 parent
b9c8b3087c
commit
f066c02c69
12 files changed
+73
-68
No files matched your search
@@ -13,9 +13,9 @@ import { useTableEditorStateSnapshot } from 'state/table-editor'
|
||||
import { useTableEditorTableStateSnapshot } from 'state/table-editor-table'
|
||||
|
||||
import { Shortcuts } from './components/common/Shortcuts'
|
||||
import Footer from './components/footer/Footer'
|
||||
import { Footer } from './components/footer/Footer'
|
||||
import { Grid } from './components/grid/Grid'
|
||||
import Header, { HeaderProps } from './components/header/Header'
|
||||
import { Header, HeaderProps } from './components/header/Header'
|
||||
import { RowContextMenu } from './components/menu'
|
||||
import { GridProps } from './types'
|
||||
|
||||
@@ -84,7 +84,7 @@ export const SupabaseGrid = ({
|
||||
return (
|
||||
<DndProvider backend={HTML5Backend} context={window}>
|
||||
<div className="sb-grid h-full flex flex-col">
|
||||
<Header customHeader={customHeader} />
|
||||
<Header customHeader={customHeader} isRefetching={isRefetching} />
|
||||
|
||||
{children || (
|
||||
<>
|
||||
@@ -99,7 +99,7 @@ export const SupabaseGrid = ({
|
||||
filters={filters}
|
||||
onApplyFilters={onApplyFilters}
|
||||
/>
|
||||
<Footer isRefetching={isRefetching} />
|
||||
<Footer />
|
||||
<Shortcuts gridRef={gridRef} rows={rows} />
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -5,14 +5,9 @@ import { useTableEditorQuery } from 'data/table-editor/table-editor-query'
|
||||
import { isTableLike, isViewLike } from 'data/table-editor/table-editor-types'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { useUrlState } from 'hooks/ui/useUrlState'
|
||||
import RefreshButton from '../header/RefreshButton'
|
||||
import { Pagination } from './pagination'
|
||||
|
||||
export interface FooterProps {
|
||||
isRefetching?: boolean
|
||||
}
|
||||
|
||||
const Footer = ({ isRefetching }: FooterProps) => {
|
||||
export const Footer = () => {
|
||||
const { id: _id } = useParams()
|
||||
const id = _id ? Number(_id) : undefined
|
||||
const { data: project } = useSelectedProjectQuery()
|
||||
@@ -41,10 +36,6 @@ const Footer = ({ isRefetching }: FooterProps) => {
|
||||
{selectedView === 'data' && <Pagination />}
|
||||
|
||||
<div className="ml-auto flex items-center gap-x-2">
|
||||
{entity && selectedView === 'data' && (
|
||||
<RefreshButton tableId={entity.id} isRefetching={isRefetching} />
|
||||
)}
|
||||
|
||||
{(isViewSelected || isTableSelected) && (
|
||||
<TwoOptionToggle
|
||||
width={75}
|
||||
@@ -58,5 +49,3 @@ const Footer = ({ isRefetching }: FooterProps) => {
|
||||
</GridFooter>
|
||||
)
|
||||
}
|
||||
|
||||
export default Footer
|
||||
@@ -8,7 +8,7 @@ import { toast } from 'sonner'
|
||||
import { useParams } from 'common'
|
||||
import { useTableFilter } from 'components/grid/hooks/useTableFilter'
|
||||
import { useTableSort } from 'components/grid/hooks/useTableSort'
|
||||
import GridHeaderActions from 'components/interfaces/TableGridEditor/GridHeaderActions'
|
||||
import { GridHeaderActions } from 'components/interfaces/TableGridEditor/GridHeaderActions'
|
||||
import { formatTableRowsToSQL } from 'components/interfaces/TableGridEditor/TableEntity.utils'
|
||||
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
|
||||
import { useTableRowsCountQuery } from 'data/table-rows/table-rows-count-query'
|
||||
@@ -56,9 +56,10 @@ export const MAX_EXPORT_ROW_COUNT_MESSAGE = (
|
||||
|
||||
export type HeaderProps = {
|
||||
customHeader: ReactNode
|
||||
isRefetching: boolean
|
||||
}
|
||||
|
||||
const Header = ({ customHeader }: HeaderProps) => {
|
||||
export const Header = ({ customHeader, isRefetching }: HeaderProps) => {
|
||||
const snap = useTableEditorTableStateSnapshot()
|
||||
|
||||
return (
|
||||
@@ -71,14 +72,12 @@ const Header = ({ customHeader }: HeaderProps) => {
|
||||
) : (
|
||||
<DefaultHeader />
|
||||
)}
|
||||
<GridHeaderActions table={snap.originalTable} />
|
||||
<GridHeaderActions table={snap.originalTable} isRefetching={isRefetching} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Header
|
||||
|
||||
const DefaultHeader = () => {
|
||||
const { ref: projectRef } = useParams()
|
||||
const { data: org } = useSelectedOrganizationQuery()
|
||||
|
||||
@@ -2,15 +2,15 @@ import { useQueryClient } from '@tanstack/react-query'
|
||||
import { RefreshCw } from 'lucide-react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
|
||||
import { tableRowKeys } from 'data/table-rows/keys'
|
||||
import { Button } from 'ui'
|
||||
|
||||
export type RefreshButtonProps = {
|
||||
tableId?: number
|
||||
isRefetching?: boolean
|
||||
}
|
||||
|
||||
const RefreshButton = ({ tableId, isRefetching }: RefreshButtonProps) => {
|
||||
export const RefreshButton = ({ tableId, isRefetching }: RefreshButtonProps) => {
|
||||
const { ref } = useParams()
|
||||
const queryClient = useQueryClient()
|
||||
const queryKey = tableRowKeys.tableRowsAndCount(ref, tableId)
|
||||
@@ -20,14 +20,18 @@ const RefreshButton = ({ tableId, isRefetching }: RefreshButtonProps) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
type="text"
|
||||
<ButtonTooltip
|
||||
type="outline"
|
||||
loading={isRefetching}
|
||||
icon={<RefreshCw className="text-foreground-muted" strokeWidth={1.5} />}
|
||||
icon={<RefreshCw />}
|
||||
onClick={() => onClick()}
|
||||
>
|
||||
Refresh
|
||||
</Button>
|
||||
className="w-7 h-7 p-0"
|
||||
tooltip={{
|
||||
content: {
|
||||
side: 'bottom',
|
||||
text: 'Refresh table data',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
export default RefreshButton
|
||||
@@ -8,7 +8,7 @@ import { toast } from 'sonner'
|
||||
import { LOCAL_STORAGE_KEYS, useParams } from 'common'
|
||||
import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
|
||||
import AlertError from 'components/ui/AlertError'
|
||||
import APIDocsButton from 'components/ui/APIDocsButton'
|
||||
import { APIDocsButton } from 'components/ui/APIDocsButton'
|
||||
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
|
||||
import { FilterPopover } from 'components/ui/FilterPopover'
|
||||
import { FormHeader } from 'components/ui/Forms/FormHeader'
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
|
||||
import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
|
||||
import APIDocsButton from 'components/ui/APIDocsButton'
|
||||
import { APIDocsButton } from 'components/ui/APIDocsButton'
|
||||
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
|
||||
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useStorageExplorerStateSnapshot } from 'state/storage-explorer'
|
||||
|
||||
@@ -5,8 +5,9 @@ import { useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { RefreshButton } from 'components/grid/components/header/RefreshButton'
|
||||
import { getEntityLintDetails } from 'components/interfaces/TableGridEditor/TableEntity.utils'
|
||||
import APIDocsButton from 'components/ui/APIDocsButton'
|
||||
import { APIDocsButton } from 'components/ui/APIDocsButton'
|
||||
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
|
||||
import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query'
|
||||
import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query'
|
||||
@@ -45,9 +46,10 @@ import ViewEntityAutofixSecurityModal from './ViewEntityAutofixSecurityModal'
|
||||
|
||||
export interface GridHeaderActionsProps {
|
||||
table: Entity
|
||||
isRefetching: boolean
|
||||
}
|
||||
|
||||
const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {
|
||||
export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProps) => {
|
||||
const { ref } = useParams()
|
||||
const { data: project } = useSelectedProjectQuery()
|
||||
const { data: org } = useSelectedOrganizationQuery()
|
||||
@@ -277,13 +279,13 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {
|
||||
<PopoverContent_Shadcn_
|
||||
// using `portal` for a safari fix. issue with rendering outside of body element
|
||||
portal
|
||||
className="min-w-[395px] text-sm"
|
||||
className="w-80 text-sm"
|
||||
align="end"
|
||||
>
|
||||
<h3 className="flex items-center gap-2">
|
||||
<h4 className="flex items-center gap-2">
|
||||
<Lock size={16} /> Row Level Security (RLS)
|
||||
</h3>
|
||||
<div className="grid gap-2 mt-4 text-foreground-light text-sm">
|
||||
</h4>
|
||||
<div className="grid gap-2 mt-4 text-foreground-light text-xs">
|
||||
<p>
|
||||
You can restrict and control who can read, write and update data in this table
|
||||
using Row Level Security.
|
||||
@@ -293,14 +295,13 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {
|
||||
table.
|
||||
</p>
|
||||
{!isSchemaLocked && (
|
||||
<div className="mt-2">
|
||||
<Button
|
||||
type="default"
|
||||
onClick={() => setRlsConfirmModalOpen(!rlsConfirmModalOpen)}
|
||||
>
|
||||
Enable RLS for this table
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
type="default"
|
||||
className="mt-2 w-min"
|
||||
onClick={() => setRlsConfirmModalOpen(!rlsConfirmModalOpen)}
|
||||
>
|
||||
Enable RLS for this table
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</PopoverContent_Shadcn_>
|
||||
@@ -443,8 +444,9 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {
|
||||
<RoleImpersonationPopover serviceRoleLabel="postgres" />
|
||||
|
||||
{isTable && realtimeEnabled && (
|
||||
<Button
|
||||
<ButtonTooltip
|
||||
type="default"
|
||||
size="tiny"
|
||||
icon={
|
||||
<MousePointer2
|
||||
strokeWidth={1.5}
|
||||
@@ -452,11 +454,23 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {
|
||||
/>
|
||||
}
|
||||
onClick={() => setShowEnableRealtime(true)}
|
||||
className={cn(isRealtimeEnabled && 'w-7 h-7 p-0 text-brand hover:text-brand-hover')}
|
||||
tooltip={{
|
||||
content: {
|
||||
side: 'bottom',
|
||||
text: isRealtimeEnabled
|
||||
? 'Click to disable realtime for this table'
|
||||
: 'Click to enable realtime for this table',
|
||||
},
|
||||
}}
|
||||
>
|
||||
Realtime {isRealtimeEnabled ? 'on' : 'off'}
|
||||
</Button>
|
||||
{!isRealtimeEnabled && 'Enable Realtime'}
|
||||
</ButtonTooltip>
|
||||
)}
|
||||
|
||||
{doesHaveAutoGeneratedAPIDocs && <APIDocsButton section={['entities', table.name]} />}
|
||||
|
||||
<RefreshButton tableId={table.id} isRefetching={isRefetching} />
|
||||
</div>
|
||||
)}
|
||||
<ConfirmationModal
|
||||
@@ -506,5 +520,3 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default GridHeaderActions
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { DndProvider } from 'react-dnd'
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import RefreshButton from 'components/grid/components/header/RefreshButton'
|
||||
import { RefreshButton } from 'components/grid/components/header/RefreshButton'
|
||||
import { FilterPopoverPrimitive } from 'components/grid/components/header/filter/FilterPopoverPrimitive'
|
||||
import { SortPopoverPrimitive } from 'components/grid/components/header/sort/SortPopoverPrimitive'
|
||||
import type { Filter, Sort } from 'components/grid/types'
|
||||
|
||||
@@ -4,7 +4,7 @@ import Link from 'next/link'
|
||||
import { useMemo, useRef } from 'react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import Footer from 'components/grid/components/footer/Footer'
|
||||
import { Footer } from 'components/grid/components/footer/Footer'
|
||||
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
||||
import { useTableDefinitionQuery } from 'data/database/table-definition-query'
|
||||
import { useViewDefinitionQuery } from 'data/database/view-definition-query'
|
||||
@@ -24,7 +24,7 @@ export interface TableDefinitionProps {
|
||||
entity?: Entity
|
||||
}
|
||||
|
||||
const TableDefinition = ({ entity }: TableDefinitionProps) => {
|
||||
export const TableDefinition = ({ entity }: TableDefinitionProps) => {
|
||||
const { ref } = useParams()
|
||||
const editorRef = useRef(null)
|
||||
const monacoRef = useRef(null)
|
||||
@@ -132,5 +132,3 @@ const TableDefinition = ({ entity }: TableDefinitionProps) => {
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default TableDefinition
|
||||
@@ -22,7 +22,7 @@ import { Button } from 'ui'
|
||||
import { Admonition, GenericSkeletonLoader } from 'ui-patterns'
|
||||
import DeleteConfirmationDialogs from './DeleteConfirmationDialogs'
|
||||
import SidePanelEditor from './SidePanelEditor/SidePanelEditor'
|
||||
import TableDefinition from './TableDefinition'
|
||||
import { TableDefinition } from './TableDefinition'
|
||||
|
||||
export interface TableGridEditorProps {
|
||||
isLoadingSelectedTable?: boolean
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useParams } from 'common'
|
||||
import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
|
||||
import { EdgeFunctionTesterSheet } from 'components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet'
|
||||
import { PageLayout } from 'components/layouts/PageLayout/PageLayout'
|
||||
import APIDocsButton from 'components/ui/APIDocsButton'
|
||||
import { APIDocsButton } from 'components/ui/APIDocsButton'
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import NoPermission from 'components/ui/NoPermission'
|
||||
import { useEdgeFunctionBodyQuery } from 'data/edge-functions/edge-function-body-query'
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
import { Code } from 'lucide-react'
|
||||
import { BookOpenText } from 'lucide-react'
|
||||
import { useAppStateSnapshot } from 'state/app-state'
|
||||
import { Button } from 'ui'
|
||||
import { ButtonTooltip } from './ButtonTooltip'
|
||||
|
||||
interface APIDocsButtonProps {
|
||||
section?: string[]
|
||||
}
|
||||
|
||||
const APIDocsButton = ({ section }: APIDocsButtonProps) => {
|
||||
export const APIDocsButton = ({ section }: APIDocsButtonProps) => {
|
||||
const snap = useAppStateSnapshot()
|
||||
|
||||
return (
|
||||
<Button
|
||||
<ButtonTooltip
|
||||
size="tiny"
|
||||
type="default"
|
||||
onClick={() => {
|
||||
if (section) snap.setActiveDocsSection(section)
|
||||
snap.setShowProjectApiDocs(true)
|
||||
}}
|
||||
icon={<Code strokeWidth={1.5} className="text-foreground-muted" />}
|
||||
>
|
||||
API Docs
|
||||
</Button>
|
||||
icon={<BookOpenText />}
|
||||
className="h-7 w-7"
|
||||
tooltip={{
|
||||
content: {
|
||||
side: 'bottom',
|
||||
text: 'API Docs',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default APIDocsButton
|
||||
Reference in new issue
Block a user