mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
Update Dev toolbar to support filtering feature flags (#48137)
## Context Only applies for local development - adds a way to filter feature flags in the dev toolbar <img width="1385" height="223" alt="image" src="https://github.com/user-attachments/assets/323d29f6-209e-4fc3-a7d0-4160b62b5707" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added search and filtering for feature flags from PostHog and ConfigCat. * Added a clear button for quickly resetting searches. * Added an informative empty state when no feature flags match the search. * Search terms reset automatically when switching between flag providers. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
bc0c1999ca
commit
76f44bfa71
1 file changed
+48
-3
@@ -212,6 +212,7 @@ export function DevToolbar({ extraTabs = [] }: { extraTabs?: ExtraTab[] }) {
|
||||
const [activeTab, setActiveTab] = useState<string>('events')
|
||||
const [flagsSubTab, setFlagsSubTab] = useState<'posthog' | 'configcat'>('posthog')
|
||||
const [eventFilter, setEventFilter] = useState<string>('')
|
||||
const [flagFilter, setFlagFilter] = useState<string>('')
|
||||
const { posthog: posthogFlags, configcat: configcatFlags } = useFeatureFlags()
|
||||
const [phFlagOverrides, setPhFlagOverrides] = useState<Record<string, unknown>>({})
|
||||
const [ccFlagOverrides, setCcFlagOverrides] = useState<Record<string, unknown>>({})
|
||||
@@ -353,6 +354,20 @@ export function DevToolbar({ extraTabs = [] }: { extraTabs?: ExtraTab[] }) {
|
||||
const ccOverrideCount = Object.keys(ccFlagOverrides).length
|
||||
const totalOverrideCount = phOverrideCount + ccOverrideCount
|
||||
|
||||
const normalizedFlagFilter = flagFilter.trim().toLowerCase()
|
||||
|
||||
const filteredPosthogEntries = normalizedFlagFilter
|
||||
? Object.entries(posthogFlags).filter(([flagName]) =>
|
||||
flagName.toLowerCase().includes(normalizedFlagFilter)
|
||||
)
|
||||
: Object.entries(posthogFlags)
|
||||
|
||||
const filteredConfigcatEntries = normalizedFlagFilter
|
||||
? Object.entries(configcatFlags).filter(([flagName]) =>
|
||||
flagName.toLowerCase().includes(normalizedFlagFilter)
|
||||
)
|
||||
: Object.entries(configcatFlags)
|
||||
|
||||
if (!IS_TOOLBAR_ENABLED || !isEnabled) return null
|
||||
|
||||
return (
|
||||
@@ -493,7 +508,10 @@ export function DevToolbar({ extraTabs = [] }: { extraTabs?: ExtraTab[] }) {
|
||||
<button
|
||||
key={id}
|
||||
type="button"
|
||||
onClick={() => setFlagsSubTab(id)}
|
||||
onClick={() => {
|
||||
setFlagsSubTab(id)
|
||||
setFlagFilter('')
|
||||
}}
|
||||
className={cn(
|
||||
'flex items-center justify-between px-3 py-1.5 rounded-sm text-sm text-left uppercase font-mono tracking-wide',
|
||||
flagsSubTab === id
|
||||
@@ -520,13 +538,35 @@ export function DevToolbar({ extraTabs = [] }: { extraTabs?: ExtraTab[] }) {
|
||||
{/* Flag list */}
|
||||
<div className="flex-1 min-h-0 overflow-y-auto pb-6">
|
||||
<div className="divide-y">
|
||||
<div className="flex items-center gap-x-1 p-2">
|
||||
<Input
|
||||
size="tiny"
|
||||
value={flagFilter}
|
||||
onChange={(e) => setFlagFilter(e.target.value)}
|
||||
placeholder="Search flag"
|
||||
className="w-64"
|
||||
/>
|
||||
{!!flagFilter && (
|
||||
<Button
|
||||
className="px-1"
|
||||
variant="text"
|
||||
icon={<X />}
|
||||
onClick={() => setFlagFilter('')}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{flagsSubTab === 'posthog' &&
|
||||
(Object.keys(posthogFlags).length === 0 ? (
|
||||
<div className="text-center text-foreground-lighter py-8 text-sm">
|
||||
No PostHog feature flags loaded yet.
|
||||
</div>
|
||||
) : filteredPosthogEntries.length === 0 ? (
|
||||
<div className="text-center text-foreground-lighter py-8 text-sm">
|
||||
No PostHog flags match "{flagFilter}".
|
||||
</div>
|
||||
) : (
|
||||
Object.entries(posthogFlags).map(([flagName, flagValue]) => (
|
||||
filteredPosthogEntries.map(([flagName, flagValue]) => (
|
||||
<FlagRow
|
||||
key={flagName}
|
||||
flagName={flagName}
|
||||
@@ -539,13 +579,18 @@ export function DevToolbar({ extraTabs = [] }: { extraTabs?: ExtraTab[] }) {
|
||||
/>
|
||||
))
|
||||
))}
|
||||
|
||||
{flagsSubTab === 'configcat' &&
|
||||
(Object.keys(configcatFlags).length === 0 ? (
|
||||
<div className="text-center text-foreground-lighter py-8 text-sm">
|
||||
No ConfigCat feature flags loaded yet.
|
||||
</div>
|
||||
) : filteredConfigcatEntries.length === 0 ? (
|
||||
<div className="text-center text-foreground-lighter py-8 text-sm">
|
||||
No ConfigCat flags match "{flagFilter}".
|
||||
</div>
|
||||
) : (
|
||||
Object.entries(configcatFlags).map(([flagName, flagValue]) => (
|
||||
filteredConfigcatEntries.map(([flagName, flagValue]) => (
|
||||
<FlagRow
|
||||
key={flagName}
|
||||
flagName={flagName}
|
||||
|
||||
Reference in new issue
Block a user