Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ import type { GlobalMenuItems, NavMenuConstant, NavMenuSection } from '../Naviga
const {
authenticationShowProviders: allAuthProvidersEnabled,
billingAll: billingEnabled,
docsAuth: authEnabled,
docsAuthArchitecture: authArchitectureEnabled,
docsAuthConfiguration: authConfigurationEnabled,
docsAuthFlows: authFlowsEnabled,
docsAuthFullSecurity: authFullSecurityEnabled,
docsAuthTroubleshooting: authTroubleshootingEnabled,
docsCompliance: complianceEnabled,
docsContribution: contributionEnabled,
'docsSelf-hosting': selfHostingEnabled,
docsFrameworkQuickstarts: frameworkQuickstartsEnabled,
docsFullPlatform: fullPlatformEnabled,
docsLocalDevelopment: localDevelopmentEnabled,
docsMobileTutorials: mobileTutorialsEnabled,
docsPgtap: pgTapEnabled,
docsProductionChecklist: productionChecklistEnabled,
Expand All @@ -26,12 +31,17 @@ const {
} = isFeatureEnabled([
'authentication:show_providers',
'billing:all',
'docs:auth',
'docs:contribution',
'docs:auth_architecture',
'docs:auth_configuration',
'docs:auth_flows',
'docs:auth_full_security',
'docs:auth_troubleshooting',
'docs:compliance',
'docs:contribution',
'docs:self-hosting',
'docs:framework_quickstarts',
'docs:full_platform',
'docs:local_development',
'docs:mobile_tutorials',
'docs:pgtap',
'docs:production_checklist',
Expand Down Expand Up @@ -72,7 +82,6 @@ export const GLOBAL_MENU_ITEMS: GlobalMenuItems = [
icon: 'auth',
href: '/guides/auth' as `/${string}`,
level: 'auth',
enabled: authEnabled,
},
{
label: 'Storage',
Expand Down Expand Up @@ -127,6 +136,7 @@ export const GLOBAL_MENU_ITEMS: GlobalMenuItems = [
icon: 'dev-cli',
href: '/guides/local-development' as `/${string}`,
level: 'local_development',
enabled: localDevelopmentEnabled,
},
{
label: 'Deployment',
Expand Down Expand Up @@ -638,7 +648,6 @@ export const PhoneLoginsItems = [
export const auth: NavMenuConstant = {
icon: 'auth',
title: 'Auth',
enabled: authEnabled,
items: [
{
name: 'Overview',
Expand All @@ -647,9 +656,11 @@ export const auth: NavMenuConstant = {
{
name: 'Architecture',
url: '/guides/auth/architecture',
enabled: authArchitectureEnabled,
},
{
name: 'Getting Started',
enabled: frameworkQuickstartsEnabled,
items: [
{
name: 'Next.js',
Expand Down Expand Up @@ -684,6 +695,7 @@ export const auth: NavMenuConstant = {
},
{
name: 'Flows (How-tos)',
enabled: authFlowsEnabled,
items: [
{
name: 'Server-Side Rendering',
Expand Down Expand Up @@ -773,7 +785,11 @@ export const auth: NavMenuConstant = {
name: 'Debugging',
items: [
{ name: 'Error Codes', url: '/guides/auth/debugging/error-codes' },
{ name: 'Troubleshooting', url: '/guides/auth/troubleshooting' },
{
name: 'Troubleshooting',
url: '/guides/auth/troubleshooting',
enabled: authTroubleshootingEnabled,
},
],
},
{
Expand All @@ -790,6 +806,7 @@ export const auth: NavMenuConstant = {
},
{
name: 'Configuration',
enabled: authConfigurationEnabled,
items: [
{
name: 'General Configuration',
Expand Down Expand Up @@ -837,16 +854,29 @@ export const auth: NavMenuConstant = {
{
name: 'Security',
items: [
{ name: 'Password Security', url: '/guides/auth/password-security' },
{ name: 'Rate Limits', url: '/guides/auth/rate-limits' },
{ name: 'Bot Detection (CAPTCHA)', url: '/guides/auth/auth-captcha' },
{ name: 'Audit Logs', url: '/guides/auth/audit-logs' },
{
name: 'Password Security',
url: '/guides/auth/password-security',
enabled: authFullSecurityEnabled,
},
{ name: 'Rate Limits', url: '/guides/auth/rate-limits', enabled: authFullSecurityEnabled },
{
name: 'Bot Detection (CAPTCHA)',
url: '/guides/auth/auth-captcha',
enabled: authFullSecurityEnabled,
},
{ name: 'Audit Logs', url: '/guides/auth/audit-logs', enabled: authFullSecurityEnabled },
{
name: 'JSON Web Tokens (JWT)',
url: '/guides/auth/jwts',
enabled: authFullSecurityEnabled,
items: [{ name: 'Claims Reference', url: '/guides/auth/jwt-fields' }],
},
{ name: 'JWT Signing Keys', url: '/guides/auth/signing-keys' },
{
name: 'JWT Signing Keys',
url: '/guides/auth/signing-keys',
enabled: authFullSecurityEnabled,
},
{ name: 'Row Level Security', url: '/guides/database/postgres/row-level-security' },
{
name: 'Column Level Security',
Expand Down Expand Up @@ -2097,6 +2127,7 @@ export const ai: NavMenuConstant = {
export const local_development: NavMenuConstant = {
icon: 'dev-cli',
title: 'Local Dev / CLI',
enabled: localDevelopmentEnabled,
url: '/guides/local-development',
items: [
{ name: 'Overview', url: '/guides/local-development' },
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/content/guides/auth.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Auth also enables access control to your database's automatically generated [RES
<$Partial path="providers.mdx" />
</$Show>

<$Show if="billing:all">

## Pricing

Charges apply to Monthly Active Users (MAU), Monthly Active Third-Party Users (Third-Party MAU), and Monthly Active SSO Users (SSO MAU) and Advanced MFA Add-ons. For a detailed breakdown of how these charges are calculated, refer to the following pages:
Expand All @@ -39,3 +41,5 @@ Charges apply to Monthly Active Users (MAU), Monthly Active Third-Party Users (T
- [Pricing Third-Party MAU](/docs/guides/platform/manage-your-usage/monthly-active-users-third-party)
- [Pricing SSO MAU](/docs/guides/platform/manage-your-usage/monthly-active-users-sso)
- [Advanced MFA - Phone](/docs/guides/platform/manage-your-usage/advanced-mfa-phone)

</$Show>
2 changes: 1 addition & 1 deletion apps/docs/features/docs/Reference.navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function ReferenceNavigation({
}: ReferenceNavigationProps) {
const navSections = await getReferenceSections(libraryId, version)
const filteredNavSections = navSections?.filter((section) => section.title !== 'Auth')
const displayedNavSections = isFeatureEnabled('docs:auth') ? navSections : filteredNavSections
const displayedNavSections = isFeatureEnabled('sdk:auth') ? navSections : filteredNavSections

const basePath = `/reference/${libPath}${isLatestVersion ? '' : `/${version}`}`

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/features/docs/Reference.sections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async function RefSections({ libraryId, version }: RefSectionsProps) {
flattenedSections = trimIntro(flattenedSections)
}

if (!isFeatureEnabled('docs:auth')) {
if (!isFeatureEnabled('sdk:auth')) {
flattenedSections = flattenedSections?.filter(
(section) =>
'product' in section && section.product !== 'auth' && section.product !== 'auth-admin'
Expand Down
72 changes: 47 additions & 25 deletions apps/studio/components/grid/SupabaseGrid.utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import AwesomeDebouncePromise from 'awesome-debounce-promise'
import { compact } from 'lodash'
import { useEffect } from 'react'
import { compact, filter } from 'lodash'
import { useEffect, useState } from 'react'
import { CalculatedColumn, CellKeyboardEvent } from 'react-data-grid'

import type { Filter, SavedState } from 'components/grid/types'
Expand All @@ -11,6 +11,9 @@ import { FilterOperatorOptions } from './components/header/filter/Filter.constan
import { STORAGE_KEY_PREFIX } from './constants'
import type { Sort, SupaColumn, SupaTable } from './types'
import { formatClipboardValue } from './utils/common'
import { parseAsArrayOf, parseAsBoolean, parseAsString, useQueryStates } from 'nuqs'

export const LOAD_TAB_FROM_CACHE_PARAM = 'loadFromCache'

export function formatSortURLParams(tableName: string, sort?: string[]): Sort[] {
if (Array.isArray(sort)) {
Expand Down Expand Up @@ -176,41 +179,60 @@ export const saveTableEditorStateToLocalStorageDebounced = AwesomeDebouncePromis
500
)

export function useLoadTableEditorStateFromLocalStorageIntoUrl({
function getLatestParams() {
const queryParams = new URLSearchParams(window.location.search)
const sort = queryParams.getAll('sort')
const filter = queryParams.getAll('filter')
const loadFromCache = !!queryParams.get(LOAD_TAB_FROM_CACHE_PARAM)
return { sort, filter, loadFromCache }
}

export function useSyncTableEditorStateFromLocalStorageWithUrl({
projectRef,
table,
}: {
projectRef: string | undefined
table: Entity | undefined
}) {
const [_, setParams] = useUrlState({
arrayKeys: ['sort', 'filter'],
})
const [urlParams, updateUrlParams] = useQueryStates(
{
sort: parseAsArrayOf(parseAsString).withDefault([]),
filter: parseAsArrayOf(parseAsString).withDefault([]),
[LOAD_TAB_FROM_CACHE_PARAM]: parseAsBoolean.withDefault(false),
},
{
history: 'replace',
}
)

useEffect(() => {
if (!projectRef || !table) {
return
}

const searchParams = new URLSearchParams(window.location.search)

const savedState = loadTableEditorStateFromLocalStorage(projectRef, table.name, table.schema)

// If no sort params are set, use saved state

let params: { sort?: string[]; filter?: string[] } | undefined

if (searchParams.getAll('sort').length <= 0 && savedState?.sorts) {
params = { ...params, sort: savedState.sorts }
}

if (searchParams.getAll('filter').length <= 0 && savedState?.filters) {
params = { ...params, filter: savedState.filters }
}

if (params) {
setParams((prevParams) => ({ ...prevParams, ...params }))
// `urlParams` from `useQueryStates` can be stale so always get the latest from the URL
const latestUrlParams = getLatestParams()

if (latestUrlParams.loadFromCache) {
const savedState = loadTableEditorStateFromLocalStorage(projectRef, table.name, table.schema)
updateUrlParams(
{
sort: savedState?.sorts ?? [],
filter: savedState?.filters ?? [],
loadFromCache: false,
},
{ clearOnDefault: true }
)
} else {
saveTableEditorStateToLocalStorage({
projectRef,
tableName: table.name,
schema: table.schema,
sorts: latestUrlParams.sort,
filters: latestUrlParams.filter,
})
}
}, [projectRef, table])
}, [urlParams, table, projectRef])
}

export const handleCopyCell = (
Expand Down
58 changes: 0 additions & 58 deletions apps/studio/components/grid/hooks/useSaveTableEditorState.ts

This file was deleted.

5 changes: 1 addition & 4 deletions apps/studio/components/grid/hooks/useTableFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,22 @@ import { useCallback } from 'react'
import { filtersToUrlParams, formatFilterURLParams } from 'components/grid/SupabaseGrid.utils'
import type { Filter } from 'components/grid/types'
import { useTableEditorFiltersSort } from 'hooks/misc/useTableEditorFiltersSort'
import { useSaveTableEditorState } from './useSaveTableEditorState'

/**
* Hook for managing table filter URL parameters and saving.
* NO direct snapshot interaction.
*/
export function useTableFilter() {
const { filters: urlFilters, setParams } = useTableEditorFiltersSort()
const { saveFiltersAndTriggerSideEffects } = useSaveTableEditorState()

const filters = formatFilterURLParams(urlFilters)

const onApplyFilters = useCallback(
(appliedFilters: Filter[]) => {
const newUrlFilters = filtersToUrlParams(appliedFilters)
setParams((prevParams) => ({ ...prevParams, filter: newUrlFilters }))
saveFiltersAndTriggerSideEffects(newUrlFilters)
},
[setParams, saveFiltersAndTriggerSideEffects]
[setParams]
)

return {
Expand Down
Loading
Loading