From 843234e153ad16e303b332e02852f268211530a7 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Thu, 2 Oct 2025 01:26:14 +0800 Subject: [PATCH 01/15] Add flag to hide email and phone columns in auth users (#39151) * add flag to hide email and phone columns in auth users * fix: add authentication:show_email_phone_columns to required schema --------- Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> --- .../interfaces/Auth/Users/Users.utils.tsx | 8 ++++--- .../interfaces/Auth/Users/UsersV2.tsx | 22 +++++++++++++++---- .../enabled-features/enabled-features.json | 7 +++--- .../enabled-features.schema.json | 17 +++++++++----- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/apps/studio/components/interfaces/Auth/Users/Users.utils.tsx b/apps/studio/components/interfaces/Auth/Users/Users.utils.tsx index 92c05be3e02df..ca935717c1d48 100644 --- a/apps/studio/components/interfaces/Auth/Users/Users.utils.tsx +++ b/apps/studio/components/interfaces/Auth/Users/Users.utils.tsx @@ -15,7 +15,7 @@ import { copyToClipboard, } from 'ui' import { PROVIDERS_SCHEMAS } from '../AuthProvidersFormValidation' -import { ColumnConfiguration, USERS_TABLE_COLUMNS } from './Users.constants' +import { ColumnConfiguration, UsersTableColumn } from './Users.constants' import { HeaderCell } from './UsersGridComponents' const GITHUB_AVATAR_URL = 'https://avatars.githubusercontent.com' @@ -250,21 +250,23 @@ export function getAvatarUrl(user: User): string | undefined { } export const formatUserColumns = ({ + columns, config, users, visibleColumns = [], setSortByValue, onSelectDeleteUser, }: { + columns: UsersTableColumn[] config: ColumnConfiguration[] users: User[] visibleColumns?: string[] setSortByValue: (val: string) => void onSelectDeleteUser: (user: User) => void }) => { - const columnOrder = config.map((c) => c.id) ?? USERS_TABLE_COLUMNS.map((c) => c.id) + const columnOrder = config.map((c) => c.id) ?? columns.map((c) => c.id) - let gridColumns = USERS_TABLE_COLUMNS.map((col) => { + let gridColumns = columns.map((col) => { const savedConfig = config.find((c) => c.id === col.id) const res: Column = { key: col.id, diff --git a/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx b/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx index d156475772753..6570110caf0da 100644 --- a/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx +++ b/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx @@ -86,13 +86,25 @@ export const UsersV2 = () => { authenticationShowSortByEmail: showSortByEmail, authenticationShowSortByPhone: showSortByPhone, authenticationShowUserTypeFilter: showUserTypeFilter, + authenticationShowEmailPhoneColumns: showEmailPhoneColumns, } = useIsFeatureEnabled([ 'authentication:show_provider_filter', 'authentication:show_sort_by_email', 'authentication:show_sort_by_phone', 'authentication:show_user_type_filter', + 'authentication:show_email_phone_columns', ]) + const userTableColumns = useMemo(() => { + if (showEmailPhoneColumns) return USERS_TABLE_COLUMNS + else { + return USERS_TABLE_COLUMNS.filter((col) => { + if (col.id === 'email' || col.id === 'phone') return false + return true + }) + } + }, [showEmailPhoneColumns]) + const [columns, setColumns] = useState[]>([]) const [search, setSearch] = useState('') const [filter, setFilter] = useState('all') @@ -265,6 +277,7 @@ export const UsersV2 = () => { (isErrorStorage && (errorStorage as Error).message.includes('data is undefined'))) ) { const columns = formatUserColumns({ + columns: userTableColumns, config: columnConfiguration ?? [], users: users ?? [], visibleColumns: selectedColumns, @@ -272,7 +285,7 @@ export const UsersV2 = () => { onSelectDeleteUser: setSelectedUserToDelete, }) setColumns(columns) - if (columns.length < USERS_TABLE_COLUMNS.length) { + if (columns.length < userTableColumns.length) { setSelectedColumns(columns.filter((col) => col.key !== 'img').map((col) => col.key)) } } @@ -386,7 +399,7 @@ export const UsersV2 = () => { name={selectedColumns.length === 0 ? 'All columns' : 'Columns'} title="Select columns to show" buttonType={selectedColumns.length === 0 ? 'dashed' : 'default'} - options={USERS_TABLE_COLUMNS.slice(1)} // Ignore user image column + options={userTableColumns.slice(1)} // Ignore user image column labelKey="name" valueKey="id" labelClass="text-xs" @@ -401,19 +414,20 @@ export const UsersV2 = () => { let updatedConfig = (columnConfiguration ?? []).slice() if (value.length === 0) { - updatedConfig = USERS_TABLE_COLUMNS.map((c) => ({ id: c.id, width: c.width })) + updatedConfig = userTableColumns.map((c) => ({ id: c.id, width: c.width })) } else { value.forEach((col) => { const hasExisting = updatedConfig.find((c) => c.id === col) if (!hasExisting) updatedConfig.push({ id: col, - width: USERS_TABLE_COLUMNS.find((c) => c.id === col)?.width, + width: userTableColumns.find((c) => c.id === col)?.width, }) }) } const updatedColumns = formatUserColumns({ + columns: userTableColumns, config: updatedConfig, users: users ?? [], visibleColumns: value, diff --git a/packages/common/enabled-features/enabled-features.json b/packages/common/enabled-features/enabled-features.json index 3ecd75981cfaf..6bef25c14fcbf 100644 --- a/packages/common/enabled-features/enabled-features.json +++ b/packages/common/enabled-features/enabled-features.json @@ -14,14 +14,15 @@ "authentication:attack_protection": true, "authentication:advanced": true, - "authentication:show_providers": true, + + "authentication:show_email_phone_columns": true, "authentication:show_manual_linking": true, - "authentication:show_send_invitation": true, "authentication:show_provider_filter": true, + "authentication:show_providers": true, + "authentication:show_send_invitation": true, "authentication:show_sort_by_email": true, "authentication:show_sort_by_phone": true, "authentication:show_user_type_filter": true, - "billing:all": true, "dashboard_auth:sign_up": true, diff --git a/packages/common/enabled-features/enabled-features.schema.json b/packages/common/enabled-features/enabled-features.schema.json index e678d317abcfe..3ee5912786554 100644 --- a/packages/common/enabled-features/enabled-features.schema.json +++ b/packages/common/enabled-features/enabled-features.schema.json @@ -80,6 +80,10 @@ "type": "boolean", "description": "Show the user type filter in the authentication users page" }, + "authentication:show_email_phone_columns": { + "type": "boolean", + "description": "Show the email and phone columns in the authentication users page" + }, "billing:all": { "type": "boolean", @@ -366,20 +370,21 @@ "ai:opt_in_level_schema", "ai:opt_in_level_schema_and_log", "ai:opt_in_level_schema_and_log_and_data", - "authentication:sign_in_providers", - "authentication:third_party_auth", - "authentication:rate_limits", + "authentication:advanced", + "authentication:attack_protection", "authentication:emails", "authentication:multi_factor", - "authentication:attack_protection", - "authentication:advanced", - "authentication:show_providers", + "authentication:rate_limits", + "authentication:show_email_phone_columns", "authentication:show_manual_linking", "authentication:show_provider_filter", + "authentication:show_providers", "authentication:show_send_invitation", "authentication:show_sort_by_email", "authentication:show_sort_by_phone", "authentication:show_user_type_filter", + "authentication:sign_in_providers", + "authentication:third_party_auth", "billing:all", "dashboard_auth:sign_up", "dashboard_auth:sign_in_with_github", From 579332fda3f6ef8047fb495a85723c150260a61d Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Thu, 2 Oct 2025 01:34:20 +0800 Subject: [PATCH 02/15] Add flag to disable wrappers UI (#39150) --- .../Landing/AvailableIntegrations.tsx | 8 ++-- .../Landing/useInstalledIntegrations.tsx | 46 ++++++++++++------- .../DatabaseLayout/Database.Commands.tsx | 21 +++++---- .../layouts/DatabaseLayout/DatabaseLayout.tsx | 10 ++-- .../DatabaseLayout/DatabaseMenu.utils.tsx | 20 +++++--- .../layouts/Integrations/layout.tsx | 33 +++++++++---- .../Integrations.Commands.tsx | 8 ++-- .../integrations/[id]/[pageId]/index.tsx | 9 +++- .../enabled-features/enabled-features.json | 2 +- .../enabled-features.schema.json | 6 +-- 10 files changed, 102 insertions(+), 61 deletions(-) diff --git a/apps/studio/components/interfaces/Integrations/Landing/AvailableIntegrations.tsx b/apps/studio/components/interfaces/Integrations/Landing/AvailableIntegrations.tsx index 2d740de982bfa..864c3338fa164 100644 --- a/apps/studio/components/interfaces/Integrations/Landing/AvailableIntegrations.tsx +++ b/apps/studio/components/interfaces/Integrations/Landing/AvailableIntegrations.tsx @@ -18,9 +18,7 @@ const CATEGORIES = [ ] as const export const AvailableIntegrations = () => { - const { integrationsShowStripeWrapper } = useIsFeatureEnabled([ - 'integrations:show_stripe_wrapper', - ]) + const { integrationsWrappers } = useIsFeatureEnabled(['integrations:wrappers']) const [selectedCategory, setSelectedCategory] = useQueryState( 'category', @@ -43,9 +41,9 @@ export const AvailableIntegrations = () => { const installedIds = installedIntegrations.map((i) => i.id) // available integrations for install - const availableIntegrations = integrationsShowStripeWrapper + const availableIntegrations = integrationsWrappers ? allIntegrations - : allIntegrations.filter((x) => x.id !== 'stripe_wrapper') + : allIntegrations.filter((x) => !x.id.endsWith('_wrapper')) const integrationsByCategory = selectedCategory === 'all' ? availableIntegrations diff --git a/apps/studio/components/interfaces/Integrations/Landing/useInstalledIntegrations.tsx b/apps/studio/components/interfaces/Integrations/Landing/useInstalledIntegrations.tsx index 9df420f1b1318..0834121c2ea63 100644 --- a/apps/studio/components/interfaces/Integrations/Landing/useInstalledIntegrations.tsx +++ b/apps/studio/components/interfaces/Integrations/Landing/useInstalledIntegrations.tsx @@ -3,6 +3,7 @@ import { useMemo } from 'react' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useSchemasQuery } from 'data/database/schemas-query' import { useFDWsQuery } from 'data/fdw/fdws-query' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { EMPTY_ARR } from 'lib/void' import { wrapperMetaComparator } from '../Wrappers/Wrappers.utils' @@ -10,6 +11,15 @@ import { INTEGRATIONS } from './Integrations.constants' export const useInstalledIntegrations = () => { const { data: project } = useSelectedProjectQuery() + const { integrationsWrappers } = useIsFeatureEnabled(['integrations:wrappers']) + + const allIntegrations = useMemo(() => { + if (integrationsWrappers) { + return INTEGRATIONS + } else { + return INTEGRATIONS.filter((integration) => !integration.id.endsWith('_wrapper')) + } + }, [integrationsWrappers]) const { data, @@ -47,28 +57,30 @@ export const useInstalledIntegrations = () => { const wrappers = useMemo(() => data ?? EMPTY_ARR, [data]) const installedIntegrations = useMemo(() => { - return INTEGRATIONS.filter((i) => { - // special handling for supabase webhooks - if (i.id === 'webhooks') { - return isHooksEnabled - } - if (i.type === 'wrapper') { - return wrappers.find((w) => wrapperMetaComparator(i.meta, w)) - } - if (i.type === 'postgres_extension') { - return i.requiredExtensions.every((extName) => { - const foundExtension = (extensions ?? []).find((ext) => ext.name === extName) - return !!foundExtension?.installed_version - }) - } - return false - }).sort((a, b) => a.name.localeCompare(b.name)) + return allIntegrations + .filter((i) => { + // special handling for supabase webhooks + if (i.id === 'webhooks') { + return isHooksEnabled + } + if (i.type === 'wrapper') { + return wrappers.find((w) => wrapperMetaComparator(i.meta, w)) + } + if (i.type === 'postgres_extension') { + return i.requiredExtensions.every((extName) => { + const foundExtension = (extensions ?? []).find((ext) => ext.name === extName) + return !!foundExtension?.installed_version + }) + } + return false + }) + .sort((a, b) => a.name.localeCompare(b.name)) }, [wrappers, extensions, isHooksEnabled]) // available integrations are all integrations that can be installed. If an integration can't be installed (needed // extensions are not available on this DB image), the UI will provide a tooltip explaining why. const availableIntegrations = useMemo( - () => INTEGRATIONS.sort((a, b) => a.name.localeCompare(b.name)), + () => allIntegrations.sort((a, b) => a.name.localeCompare(b.name)), [] ) diff --git a/apps/studio/components/layouts/DatabaseLayout/Database.Commands.tsx b/apps/studio/components/layouts/DatabaseLayout/Database.Commands.tsx index 3abd34af48c7a..ddfb6dd7f72fa 100644 --- a/apps/studio/components/layouts/DatabaseLayout/Database.Commands.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/Database.Commands.tsx @@ -12,9 +12,10 @@ export function useDatabaseGotoCommands(options?: CommandOptions) { let { ref } = useParams() ref ||= '_' - const { databaseReplication, databaseRoles } = useIsFeatureEnabled([ + const { databaseReplication, databaseRoles, integrationsWrappers } = useIsFeatureEnabled([ 'database:replication', 'database:roles', + 'integrations:wrappers', ]) useRegisterCommands( @@ -102,13 +103,17 @@ export function useDatabaseGotoCommands(options?: CommandOptions) { route: `/project/${ref}/database/backups/scheduled`, defaultHidden: true, }, - { - id: 'nav-database-wrappers', - name: 'Wrappers', - value: 'Database: Wrappers', - route: `/project/${ref}/integrations/wrappers`, - defaultHidden: true, - }, + ...(integrationsWrappers + ? [ + { + id: 'nav-database-wrappers', + name: 'Wrappers', + value: 'Database: Wrappers', + route: `/project/${ref}/integrations?category=wrappers`, + defaultHidden: true, + } as IRouteCommand, + ] + : []), { id: 'nav-database-migrations', name: 'Migrations', diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx b/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx index 4919aac04a7c7..59f74122a4f34 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx @@ -33,10 +33,11 @@ const DatabaseProductMenu = () => { const columnLevelPrivileges = useIsColumnLevelPrivilegesEnabled() const enablePgReplicate = useFlag('enablePgReplicate') - const { databaseReplication: showPgReplicate, databaseRoles: showRoles } = useIsFeatureEnabled([ - 'database:replication', - 'database:roles', - ]) + const { + databaseReplication: showPgReplicate, + databaseRoles: showRoles, + integrationsWrappers: showWrappers, + } = useIsFeatureEnabled(['database:replication', 'database:roles', 'integrations:wrappers']) return ( <> @@ -49,6 +50,7 @@ const DatabaseProductMenu = () => { enablePgReplicate, showPgReplicate, showRoles, + showWrappers, })} /> diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx index 8226871f54a53..d551edcc0bde9 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx @@ -13,6 +13,7 @@ export const generateDatabaseMenu = ( enablePgReplicate: boolean showPgReplicate: boolean showRoles: boolean + showWrappers: boolean } ): ProductMenuGroup[] => { const ref = project?.ref ?? 'default' @@ -23,6 +24,7 @@ export const generateDatabaseMenu = ( enablePgReplicate, showPgReplicate, showRoles, + showWrappers, } = flags || {} return [ @@ -134,13 +136,17 @@ export const generateDatabaseMenu = ( url: `/project/${ref}/database/migrations`, items: [], }, - { - name: 'Wrappers', - key: 'wrappers', - url: `/project/${ref}/integrations?category=wrapper`, - rightIcon: , - items: [], - }, + ...(showWrappers + ? [ + { + name: 'Wrappers', + key: 'wrappers', + url: `/project/${ref}/integrations?category=wrapper`, + rightIcon: , + items: [], + }, + ] + : []), ...(!!pgNetExtensionExists ? [ { diff --git a/apps/studio/components/layouts/Integrations/layout.tsx b/apps/studio/components/layouts/Integrations/layout.tsx index bef2d1ce074e6..87732d1a80d8b 100644 --- a/apps/studio/components/layouts/Integrations/layout.tsx +++ b/apps/studio/components/layouts/Integrations/layout.tsx @@ -1,13 +1,13 @@ import { useRouter } from 'next/router' import { PropsWithChildren } from 'react' -import { useFlag } from 'common' import { useInstalledIntegrations } from 'components/interfaces/Integrations/Landing/useInstalledIntegrations' import ProjectLayout from 'components/layouts/ProjectLayout/ProjectLayout' import AlertError from 'components/ui/AlertError' import { ProductMenu } from 'components/ui/ProductMenu' import { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' import ProductMenuItem from 'components/ui/ProductMenu/ProductMenuItem' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' import { Menu, Separator } from 'ui' @@ -20,6 +20,7 @@ import { GenericSkeletonLoader } from 'ui-patterns' const IntegrationsLayout = ({ children }: PropsWithChildren) => { const router = useRouter() const { data: project } = useSelectedProjectQuery() + const { integrationsWrappers: showWrappers } = useIsFeatureEnabled(['integrations:wrappers']) const segments = router.asPath.split('/') // construct the page url to be used to determine the active state for the sidebar @@ -65,7 +66,7 @@ const IntegrationsLayout = ({ children }: PropsWithChildren) => { : 'integrations' : page } - menu={generateIntegrationsMenu({ projectRef: project?.ref })} + menu={generateIntegrationsMenu({ projectRef: project?.ref, flags: { showWrappers } })} />
@@ -110,7 +111,15 @@ const IntegrationsLayout = ({ children }: PropsWithChildren) => { // Wrap component with authentication HOC before exporting export default withAuth(IntegrationsLayout) -const generateIntegrationsMenu = ({ projectRef }: { projectRef?: string }): ProductMenuGroup[] => { +const generateIntegrationsMenu = ({ + projectRef, + flags, +}: { + projectRef?: string + flags?: { showWrappers: boolean } +}): ProductMenuGroup[] => { + const { showWrappers } = flags ?? {} + return [ { title: 'Explore', @@ -122,13 +131,17 @@ const generateIntegrationsMenu = ({ projectRef }: { projectRef?: string }): Prod pages: ['integrations'], items: [], }, - { - name: 'Wrappers', - key: 'integrations-wrapper', - url: `/project/${projectRef}/integrations?category=wrapper`, - pages: ['integrations?category=wrapper'], - items: [], - }, + ...(showWrappers + ? [ + { + name: 'Wrappers', + key: 'integrations-wrapper', + url: `/project/${projectRef}/integrations?category=wrapper`, + pages: ['integrations?category=wrapper'], + items: [], + }, + ] + : []), { name: 'Postgres Modules', key: 'integrations-postgres_extension', diff --git a/apps/studio/components/layouts/IntegrationsLayout/Integrations.Commands.tsx b/apps/studio/components/layouts/IntegrationsLayout/Integrations.Commands.tsx index 510407e9c728e..6a775092ea8e6 100644 --- a/apps/studio/components/layouts/IntegrationsLayout/Integrations.Commands.tsx +++ b/apps/studio/components/layouts/IntegrationsLayout/Integrations.Commands.tsx @@ -13,13 +13,11 @@ export function useIntegrationsGotoCommands(options?: CommandOptions) { let { ref } = useParams() ref ||= '_' - const { integrationsShowStripeWrapper } = useIsFeatureEnabled([ - 'integrations:show_stripe_wrapper', - ]) + const { integrationsWrappers } = useIsFeatureEnabled(['integrations:wrappers']) - const allIntegrations = integrationsShowStripeWrapper + const allIntegrations = integrationsWrappers ? INTEGRATIONS - : INTEGRATIONS.filter((x) => x.id !== 'stripe_wrapper') + : INTEGRATIONS.filter((x) => !x.id.endsWith('_wrapper')) const getName = (integration: IntegrationDefinition) => { switch (integration.id) { diff --git a/apps/studio/pages/project/[ref]/integrations/[id]/[pageId]/index.tsx b/apps/studio/pages/project/[ref]/integrations/[id]/[pageId]/index.tsx index b0eb70e5efe46..1b7ced2f8eee2 100644 --- a/apps/studio/pages/project/[ref]/integrations/[id]/[pageId]/index.tsx +++ b/apps/studio/pages/project/[ref]/integrations/[id]/[pageId]/index.tsx @@ -3,9 +3,11 @@ import { INTEGRATIONS } from 'components/interfaces/Integrations/Landing/Integra import { useInstalledIntegrations } from 'components/interfaces/Integrations/Landing/useInstalledIntegrations' import DefaultLayout from 'components/layouts/DefaultLayout' import IntegrationsLayout from 'components/layouts/Integrations/layout' -import { PageLayout, NavigationItem } from 'components/layouts/PageLayout/PageLayout' +import { NavigationItem, PageLayout } from 'components/layouts/PageLayout/PageLayout' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' +import { UnknownInterface } from 'components/ui/UnknownInterface' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { useRouter } from 'next/compat/router' import { useEffect, useMemo } from 'react' import { NextPageWithLayout } from 'types' @@ -14,6 +16,7 @@ import { Admonition } from 'ui-patterns' const IntegrationPage: NextPageWithLayout = () => { const router = useRouter() const { ref, id, pageId, childId } = useParams() + const { integrationsWrappers } = useIsFeatureEnabled(['integrations:wrappers']) const { installedIntegrations: installedIntegrations, isLoading: isIntegrationsLoading } = useInstalledIntegrations() @@ -117,6 +120,10 @@ const IntegrationPage: NextPageWithLayout = () => { return null } + if (!integrationsWrappers && id?.endsWith('_wrapper')) { + return + } + return ( Date: Thu, 2 Oct 2025 01:42:23 +0800 Subject: [PATCH 03/15] Add flag for metadata IP logs explorer template (#39152) * Add flag for metadata IP logs explorer template * Flip true * fix(log explorer): also remove metadata ip template from templates page when flag disabled --------- Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> --- .../pages/project/[ref]/logs/explorer/index.tsx | 11 +++++++++-- .../pages/project/[ref]/logs/explorer/templates.tsx | 10 ++++++++-- .../common/enabled-features/enabled-features.json | 1 + .../enabled-features/enabled-features.schema.json | 5 +++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx index 79f7ff78c29b7..8fe0c6e02e10b 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx @@ -3,7 +3,7 @@ import { useLocalStorage } from '@uidotdev/usehooks' import dayjs from 'dayjs' import { editor } from 'monaco-editor' import { useRouter } from 'next/router' -import { useEffect, useRef, useState } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' import { toast } from 'sonner' import { IS_PLATFORM, LOCAL_STORAGE_KEYS, useParams } from 'common' @@ -37,6 +37,7 @@ import { import useLogsQuery from 'hooks/analytics/useLogsQuery' import { useLogsUrlState } from 'hooks/analytics/useLogsUrlState' import { useCustomContent } from 'hooks/custom-content/useCustomContent' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt' import { uuidv4 } from 'lib/helpers' @@ -66,6 +67,12 @@ export const LogsExplorerPage: NextPageWithLayout = () => { const { ref, q, queryId } = useParams() const projectRef = ref as string const { data: organization } = useSelectedOrganizationQuery() + const { logsShowMetadataIpTemplate } = useIsFeatureEnabled(['logs:show_metadata_ip_template']) + + const allTemplates = useMemo(() => { + if (logsShowMetadataIpTemplate) return TEMPLATES + else return TEMPLATES.filter((x) => x.label !== 'Metadata IP') + }, [logsShowMetadataIpTemplate]) const editorRef = useRef() const [editorId] = useState(uuidv4()) @@ -301,7 +308,7 @@ export const LogsExplorerPage: NextPageWithLayout = () => { defaultTo={timestampEnd || ''} onDateChange={handleDateChange} onSelectSource={handleInsertSource} - templates={TEMPLATES.filter((template) => template.mode === 'custom')} + templates={allTemplates.filter((template) => template.mode === 'custom')} onSelectTemplate={onSelectTemplate} warnings={warnings} /> diff --git a/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx b/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx index 9c93527c5706f..15a52d0cbc4cd 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx @@ -15,17 +15,23 @@ import { Button, Popover, cn } from 'ui' export const LogsTemplatesPage: NextPageWithLayout = () => { const { ref: projectRef } = useParams() - const isTemplatesEnabled = useIsFeatureEnabled('logs:templates') + const { logsTemplates: isTemplatesEnabled, logsShowMetadataIpTemplate: showMetadataIpTemplate } = + useIsFeatureEnabled(['logs:templates', 'logs:show_metadata_ip_template']) if (!isTemplatesEnabled) { return } + const allTemplates = showMetadataIpTemplate + ? TEMPLATES + : TEMPLATES.filter((template) => template.label !== 'Metadata IP') + return (
- {TEMPLATES.sort((a, b) => a.label!.localeCompare(b.label!)) + {allTemplates + .sort((a, b) => a.label!.localeCompare(b.label!)) .filter((template) => template.mode === 'custom') .map((template, i) => { return