Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 9efe84c

Browse files
Change useExperimentalFeatures to use the new useSettings API (#48125)
This PR changes the `useExperimentalFeatures` hook to use the new `useSettings` API as discussed in #47979.
1 parent ba61766 commit 9efe84c

File tree

55 files changed

+269
-257
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+269
-257
lines changed

client/shared/src/settings/settings.tsx

+33-6
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import { createContext, useContext, useMemo } from 'react'
22

33
import { cloneDeep, isFunction } from 'lodash'
44

5-
import { createAggregateError, ErrorLike, isErrorLike, parseJSONCOrError } from '@sourcegraph/common'
5+
import { createAggregateError, ErrorLike, isErrorLike, logger, parseJSONCOrError } from '@sourcegraph/common'
66

77
import { DefaultSettingFields, OrgSettingFields, SiteSettingFields, UserSettingFields } from '../graphql-operations'
8-
import { Settings as GeneratedSettingsType } from '../schema/settings.schema'
8+
import { Settings as GeneratedSettingsType, SettingsExperimentalFeatures } from '../schema/settings.schema'
99

1010
/**
1111
* A dummy type to represent the "subject" for client settings (i.e., settings stored in the client application,
@@ -245,10 +245,10 @@ export interface SettingsCascadeProps<S extends Settings = Settings> {
245245
}
246246

247247
interface SettingsContextData<S extends Settings = Settings> {
248-
settingsCascade: SettingsCascadeOrError<S> | null
248+
settingsCascade: SettingsCascadeOrError<S>
249249
}
250250
const SettingsContext = createContext<SettingsContextData>({
251-
settingsCascade: null,
251+
settingsCascade: EMPTY_SETTINGS_CASCADE,
252252
})
253253

254254
interface SettingsProviderProps {
@@ -268,8 +268,10 @@ export const SettingsProvider: React.FC<React.PropsWithChildren<SettingsProvider
268268
*/
269269
export const useSettingsCascade = (): SettingsCascadeOrError => {
270270
const { settingsCascade } = useContext(SettingsContext)
271-
if (!settingsCascade) {
272-
throw new Error('useSettingsCascade must be used within a SettingsProvider')
271+
if (settingsCascade === EMPTY_SETTINGS_CASCADE && process.env.JEST_WORKER_ID === undefined) {
272+
logger.error(
273+
'useSettingsCascade must be used within a SettingsProvider, falling back to an empty settings object'
274+
)
273275
}
274276
return settingsCascade
275277
}
@@ -281,3 +283,28 @@ export const useSettings = (): Settings | null => {
281283
const settingsCascade = useSettingsCascade()
282284
return isSettingsValid(settingsCascade) ? settingsCascade.final : null
283285
}
286+
287+
const defaultFeatures: SettingsExperimentalFeatures = {
288+
codeMonitoring: true,
289+
/**
290+
* Whether we show the multiline editor at /search/console
291+
*/
292+
showMultilineSearchConsole: false,
293+
codeMonitoringWebHooks: true,
294+
showCodeMonitoringLogs: true,
295+
codeInsightsCompute: false,
296+
editor: 'codemirror6',
297+
codeInsightsRepoUI: 'search-query-or-strict-list',
298+
applySearchQuerySuggestionOnEnter: false,
299+
setupWizard: false,
300+
isInitialized: true,
301+
}
302+
303+
/**
304+
* A React hooks that can be used to query specific feature flags. Prioritize this over the generic
305+
* useSettings() hook if all you need is a feature flag.
306+
*/
307+
export function useExperimentalFeatures<T>(selector: (features: SettingsExperimentalFeatures) => T): T {
308+
const settings = useSettings()
309+
return selector({ ...defaultFeatures, ...settings?.experimentalFeatures })
310+
}

client/web/src/Layout.tsx

+6-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Outlet, useLocation, Navigate, useMatches, useMatch } from 'react-route
66
import { TabbedPanelContent } from '@sourcegraph/branded/src/components/panel/TabbedPanelContent'
77
import { useKeyboardShortcut } from '@sourcegraph/shared/src/keyboardShortcuts/useKeyboardShortcut'
88
import { Shortcut } from '@sourcegraph/shared/src/react-shortcuts'
9+
import { useExperimentalFeatures } from '@sourcegraph/shared/src/settings/settings'
910
import { useTheme, Theme } from '@sourcegraph/shared/src/theme'
1011
import { lazyComponent } from '@sourcegraph/shared/src/util/lazyComponent'
1112
import { parseQueryAndHash } from '@sourcegraph/shared/src/util/url'
@@ -28,8 +29,6 @@ import { EnterprisePageRoutes, PageRoutes } from './routes.constants'
2829
import { parseSearchURLQuery } from './search'
2930
import { NotepadContainer } from './search/Notepad'
3031
import { SearchQueryStateObserver } from './SearchQueryStateObserver'
31-
import { useExperimentalFeatures } from './stores'
32-
import { getExperimentalFeatures } from './util/get-experimental-features'
3332
import { parseBrowserRepoURL } from './util/url'
3433

3534
import styles from './Layout.module.scss'
@@ -77,11 +76,13 @@ export const Layout: React.FC<LegacyLayoutProps> = props => {
7776
)
7877
const isSearchNotebookListPage = location.pathname === EnterprisePageRoutes.Notebooks
7978

80-
const { setupWizard } = useExperimentalFeatures()
79+
const { setupWizard, fuzzyFinder } = useExperimentalFeatures(features => ({
80+
setupWizard: features.setupWizard,
81+
// enable fuzzy finder by default unless it's explicitly disabled in settings
82+
fuzzyFinder: features.fuzzyFinder ?? true,
83+
}))
8184
const isSetupWizardPage = setupWizard && location.pathname.startsWith(PageRoutes.SetupWizard)
8285

83-
// enable fuzzy finder by default unless it's explicitly disabled in settings
84-
const fuzzyFinder = getExperimentalFeatures(props.settingsCascade.final).fuzzyFinder ?? true
8586
const [isFuzzyFinderVisible, setFuzzyFinderVisible] = useState(false)
8687
const userHistory = useUserHistory(isRepositoryRelatedPage)
8788

client/web/src/LegacyLayout.tsx

+6-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { matchPath, useLocation, Route, Routes, Navigate } from 'react-router-do
66
import { TabbedPanelContent } from '@sourcegraph/branded/src/components/panel/TabbedPanelContent'
77
import { useKeyboardShortcut } from '@sourcegraph/shared/src/keyboardShortcuts/useKeyboardShortcut'
88
import { Shortcut } from '@sourcegraph/shared/src/react-shortcuts'
9+
import { useExperimentalFeatures } from '@sourcegraph/shared/src/settings/settings'
910
import { useTheme, Theme } from '@sourcegraph/shared/src/theme'
1011
import { lazyComponent } from '@sourcegraph/shared/src/util/lazyComponent'
1112
import { parseQueryAndHash } from '@sourcegraph/shared/src/util/url'
@@ -29,8 +30,6 @@ import { EnterprisePageRoutes, PageRoutes } from './routes.constants'
2930
import { parseSearchURLQuery } from './search'
3031
import { NotepadContainer } from './search/Notepad'
3132
import { SearchQueryStateObserver } from './SearchQueryStateObserver'
32-
import { useExperimentalFeatures } from './stores'
33-
import { getExperimentalFeatures } from './util/get-experimental-features'
3433
import { parseBrowserRepoURL } from './util/url'
3534

3635
import styles from './Layout.module.scss'
@@ -64,11 +63,13 @@ export const LegacyLayout: FC<LegacyLayoutProps> = props => {
6463
const isSearchNotebookListPage = location.pathname === EnterprisePageRoutes.Notebooks
6564
const isRepositoryRelatedPage = routeMatch === PageRoutes.RepoContainer ?? false
6665

67-
const { setupWizard } = useExperimentalFeatures()
66+
const { setupWizard, fuzzyFinder } = useExperimentalFeatures(features => ({
67+
setupWizard: features.setupWizard,
68+
// enable fuzzy finder by default unless it's explicitly disabled in settings
69+
fuzzyFinder: features.fuzzyFinder ?? true,
70+
}))
6871
const isSetupWizardPage = setupWizard && location.pathname.startsWith(PageRoutes.SetupWizard)
6972

70-
// enable fuzzy finder by default unless it's explicitly disabled in settings
71-
const fuzzyFinder = getExperimentalFeatures(props.settingsCascade.final).fuzzyFinder ?? true
7273
const [isFuzzyFinderVisible, setFuzzyFinderVisible] = useState(false)
7374
const userHistory = useUserHistory(isRepositoryRelatedPage)
7475

client/web/src/LegacySourcegraphWebApp.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ import { parseSearchURL } from './search'
5555
import { SearchResultsCacheProvider } from './search/results/SearchResultsCacheProvider'
5656
import { GLOBAL_SEARCH_CONTEXT_SPEC } from './SearchQueryStateObserver'
5757
import { StaticAppConfig } from './staticAppConfig'
58-
import { setQueryStateFromSettings, setExperimentalFeaturesFromSettings, useNavbarQueryState } from './stores'
58+
import { setQueryStateFromSettings, useNavbarQueryState } from './stores'
5959
import { eventLogger } from './tracking/eventLogger'
6060
import { UserSessionStores } from './UserSessionStores'
6161
import { siteSubjectNoAdmin, viewerSubjectFromSettings } from './util/settings'
@@ -142,7 +142,6 @@ export class LegacySourcegraphWebApp extends React.Component<StaticAppConfig, Le
142142
// Start with `undefined` while we don't know if the viewer is authenticated or not.
143143
authenticatedUserSubject,
144144
]).subscribe(([settingsCascade, authenticatedUser]) => {
145-
setExperimentalFeaturesFromSettings(settingsCascade)
146145
setQueryStateFromSettings(settingsCascade)
147146
this.setState({
148147
settingsCascade,

client/web/src/SourcegraphWebApp.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import { parseSearchURL } from './search'
4545
import { SearchResultsCacheProvider } from './search/results/SearchResultsCacheProvider'
4646
import { GLOBAL_SEARCH_CONTEXT_SPEC } from './SearchQueryStateObserver'
4747
import { StaticAppConfig } from './staticAppConfig'
48-
import { setQueryStateFromSettings, setExperimentalFeaturesFromSettings, useNavbarQueryState } from './stores'
48+
import { setQueryStateFromSettings, useNavbarQueryState } from './stores'
4949
import { UserSessionStores } from './UserSessionStores'
5050
import { siteSubjectNoAdmin, viewerSubjectFromSettings } from './util/settings'
5151

@@ -213,7 +213,6 @@ export const SourcegraphWebApp: FC<StaticAppConfig> = props => {
213213
subscriptions.add(
214214
combineLatest([from(platformContext.settings), authenticatedUserSubject]).subscribe(
215215
([settingsCascade, authenticatedUser]) => {
216-
setExperimentalFeaturesFromSettings(settingsCascade)
217216
setQueryStateFromSettings(settingsCascade)
218217
setSettingsCascade(settingsCascade)
219218
setResolvedAuthenticatedUser(authenticatedUser ?? null)

client/web/src/codeintel/ReferencesPanel.test.tsx

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
import { within, fireEvent } from '@testing-library/react'
22
import { createPath } from 'react-router-dom'
33

4+
import { SettingsProvider } from '@sourcegraph/shared/src/settings/settings'
45
import { MockedTestProvider, waitForNextApolloResponse } from '@sourcegraph/shared/src/testing/apollo'
56
import '@sourcegraph/shared/src/testing/mockReactVisibilitySensor'
67
import { renderWithBrandedContext } from '@sourcegraph/wildcard/src/testing'
78

8-
import { setExperimentalFeaturesFromSettings } from '../stores'
9-
109
import { ReferencesPanel } from './ReferencesPanel'
1110
import { buildReferencePanelMocks, defaultProps } from './ReferencesPanel.mocks'
1211

1312
describe('ReferencesPanel', () => {
1413
async function renderReferencesPanel() {
1514
const { url, requestMocks } = buildReferencePanelMocks()
1615

17-
// TODO: we won't need to set experimental features explicitly once we cover CodeMirror side blob view with tests:
18-
// https://github.com./sourcegraph/sourcegraph/issues/48049
19-
setExperimentalFeaturesFromSettings(defaultProps.settingsCascade)
20-
2116
const result = renderWithBrandedContext(
2217
<MockedTestProvider mocks={requestMocks}>
23-
<ReferencesPanel {...defaultProps} />
18+
<SettingsProvider
19+
settingsCascade={{
20+
final: { experimentalFeatures: { enableCodeMirrorFileView: false } },
21+
subjects: [],
22+
}}
23+
>
24+
<ReferencesPanel {...defaultProps} />
25+
</SettingsProvider>
2426
</MockedTestProvider>,
2527
{ route: url }
2628
)

client/web/src/codeintel/ReferencesPanel.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { ExtensionsControllerProps } from '@sourcegraph/shared/src/extensions/co
2929
import { HighlightResponseFormat } from '@sourcegraph/shared/src/graphql-operations'
3030
import { getModeFromPath } from '@sourcegraph/shared/src/languages'
3131
import { PlatformContextProps } from '@sourcegraph/shared/src/platform/context'
32-
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
32+
import { SettingsCascadeProps, useExperimentalFeatures } from '@sourcegraph/shared/src/settings/settings'
3333
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
3434
import {
3535
RepoSpec,
@@ -63,7 +63,6 @@ import { CodeMirrorBlob } from '../repo/blob/CodeMirrorBlob'
6363
import { LegacyBlob } from '../repo/blob/LegacyBlob'
6464
import * as BlobAPI from '../repo/blob/use-blob-store'
6565
import { HoverThresholdProps } from '../repo/RepoContainer'
66-
import { useExperimentalFeatures } from '../stores'
6766
import { parseBrowserRepoURL } from '../util/url'
6867

6968
import { Location, LocationGroup, locationGroupQuality, buildRepoLocationGroups, RepoLocationGroup } from './location'

client/web/src/components/WebStory.tsx

+8-5
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { FC } from 'react'
22

33
import { RouterProvider, createMemoryRouter, MemoryRouterProps } from 'react-router-dom'
44

5+
import { EMPTY_SETTINGS_CASCADE, SettingsProvider } from '@sourcegraph/shared/src/settings/settings'
56
import { MockedStoryProvider, MockedStoryProviderProps } from '@sourcegraph/shared/src/stories'
67
import { NOOP_TELEMETRY_SERVICE, TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
78
import { ThemeContext, ThemeSetting } from '@sourcegraph/shared/src/theme'
89
import { WildcardThemeContext } from '@sourcegraph/wildcard'
910
import { usePrependStyles, useStorybookTheme } from '@sourcegraph/wildcard/src/stories'
1011

1112
import { SourcegraphContext } from '../jscontext'
12-
import { setExperimentalFeaturesForTesting } from '../stores/experimentalFeatures'
1313

1414
import { BreadcrumbSetters, BreadcrumbsProps, useBreadcrumbs } from './Breadcrumbs'
1515

@@ -50,7 +50,6 @@ export const WebStory: FC<WebStoryProps> = ({
5050
const breadcrumbSetters = useBreadcrumbs()
5151

5252
usePrependStyles('web-styles', webStyles)
53-
setExperimentalFeaturesForTesting()
5453

5554
const routes = [
5655
{
@@ -73,9 +72,13 @@ export const WebStory: FC<WebStoryProps> = ({
7372
return (
7473
<MockedStoryProvider mocks={mocks} useStrictMocking={useStrictMocking}>
7574
<WildcardThemeContext.Provider value={{ isBranded: true }}>
76-
<ThemeContext.Provider value={{ themeSetting: isLightTheme ? ThemeSetting.Light : ThemeSetting.Dark }}>
77-
<RouterProvider router={router} />
78-
</ThemeContext.Provider>
75+
<SettingsProvider settingsCascade={EMPTY_SETTINGS_CASCADE}>
76+
<ThemeContext.Provider
77+
value={{ themeSetting: isLightTheme ? ThemeSetting.Light : ThemeSetting.Dark }}
78+
>
79+
<RouterProvider router={router} />
80+
</ThemeContext.Provider>
81+
</SettingsProvider>
7982
</WildcardThemeContext.Provider>
8083
</MockedStoryProvider>
8184
)

client/web/src/components/fuzzyFinder/FuzzyFinder.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export const FuzzyFinderContainer: React.FunctionComponent<FuzzyFinderContainerP
7878
[setActiveTab, setIsVisible, toggleScope, setQuery]
7979
)
8080

81-
const shortcuts = useFuzzyShortcuts(props.settingsCascade.final)
81+
const shortcuts = useFuzzyShortcuts()
8282

8383
useEffect(() => {
8484
if (isVisible) {
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
import { SettingsExperimentalFeatures } from '@sourcegraph/shared/src/schema/settings.schema'
2-
import { Settings, SettingsCascadeOrError } from '@sourcegraph/shared/src/settings/settings'
1+
import type { SettingsExperimentalFeatures } from '@sourcegraph/shared/src/schema/settings.schema'
2+
import { useExperimentalFeatures } from '@sourcegraph/shared/src/settings/settings'
33

4-
import { getExperimentalFeatures } from '../../util/get-experimental-features'
5-
6-
export function getFuzzyFinderFeatureFlags(
7-
finalSettings?: SettingsCascadeOrError<Settings>['final']
8-
): Pick<
4+
export function useFuzzyFinderFeatureFlags(): Pick<
95
SettingsExperimentalFeatures,
106
'fuzzyFinderAll' | 'fuzzyFinderActions' | 'fuzzyFinderRepositories' | 'fuzzyFinderSymbols' | 'fuzzyFinderNavbar'
117
> {
12-
let { fuzzyFinderAll, fuzzyFinderActions, fuzzyFinderRepositories, fuzzyFinderSymbols, fuzzyFinderNavbar } =
13-
getExperimentalFeatures(finalSettings)
14-
// enable fuzzy finder unless it's explicitly disabled in settings
15-
fuzzyFinderAll = fuzzyFinderAll ?? true
16-
// Intentionally skip fuzzyFinderActions because we don't have enough actions implemented
17-
// Intentionally skip fuzzyFinderNavbar because the navbar is already too busy and we need to explore alternative solutions for the discoverability problem
18-
fuzzyFinderRepositories = fuzzyFinderAll || fuzzyFinderRepositories
19-
fuzzyFinderSymbols = fuzzyFinderAll || fuzzyFinderSymbols
20-
return { fuzzyFinderAll, fuzzyFinderActions, fuzzyFinderRepositories, fuzzyFinderSymbols, fuzzyFinderNavbar }
8+
return useExperimentalFeatures(features => {
9+
let { fuzzyFinderAll, fuzzyFinderActions, fuzzyFinderRepositories, fuzzyFinderSymbols, fuzzyFinderNavbar } =
10+
features
11+
12+
// enable fuzzy finder unless it's explicitly disabled in settings
13+
fuzzyFinderAll = fuzzyFinderAll ?? true
14+
// Intentionally skip fuzzyFinderActions because we don't have enough actions implemented
15+
// Intentionally skip fuzzyFinderNavbar because the navbar is already too busy and we need to explore alternative solutions for the discoverability problem
16+
fuzzyFinderRepositories = fuzzyFinderAll || fuzzyFinderRepositories
17+
fuzzyFinderSymbols = fuzzyFinderAll || fuzzyFinderSymbols
18+
return {
19+
fuzzyFinderAll,
20+
fuzzyFinderActions,
21+
fuzzyFinderRepositories,
22+
fuzzyFinderSymbols,
23+
fuzzyFinderNavbar,
24+
}
25+
})
2126
}

client/web/src/components/fuzzyFinder/FuzzyShortcuts.ts

+3-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
import { useMemo } from 'react'
2-
31
import { KeyboardShortcut } from '@sourcegraph/shared/src/keyboardShortcuts'
42
import { useKeyboardShortcut } from '@sourcegraph/shared/src/keyboardShortcuts/useKeyboardShortcut'
5-
import { Settings, SettingsCascadeOrError } from '@sourcegraph/shared/src/settings/settings'
63

7-
import { getFuzzyFinderFeatureFlags } from './FuzzyFinderFeatureFlag'
4+
import { useFuzzyFinderFeatureFlags } from './FuzzyFinderFeatureFlag'
85
import { FuzzyTabKey } from './FuzzyTabs'
96

107
interface FuzzyShortcut {
@@ -13,11 +10,8 @@ interface FuzzyShortcut {
1310
shortcut: KeyboardShortcut | undefined
1411
}
1512

16-
export function useFuzzyShortcuts(settings?: SettingsCascadeOrError<Settings>['final']): FuzzyShortcut[] {
17-
const { fuzzyFinderActions, fuzzyFinderRepositories, fuzzyFinderSymbols } = useMemo(
18-
() => getFuzzyFinderFeatureFlags(settings),
19-
[settings]
20-
)
13+
export function useFuzzyShortcuts(): FuzzyShortcut[] {
14+
const { fuzzyFinderActions, fuzzyFinderRepositories, fuzzyFinderSymbols } = useFuzzyFinderFeatureFlags()
2115
const fuzzyFinderShortcut = useKeyboardShortcut('fuzzyFinder')
2216
const fuzzyFinderActionsShortcut = useKeyboardShortcut('fuzzyFinderActions')
2317
const fuzzyFinderReposShortcut = useKeyboardShortcut('fuzzyFinderRepos')

client/web/src/components/fuzzyFinder/FuzzyTabs.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { UserHistory } from '../useUserHistory'
1616

1717
import { createActionsFSM, getAllFuzzyActions } from './FuzzyActions'
1818
import { FuzzyFiles, FuzzyRepoFiles } from './FuzzyFiles'
19-
import { getFuzzyFinderFeatureFlags } from './FuzzyFinderFeatureFlag'
19+
import { useFuzzyFinderFeatureFlags } from './FuzzyFinderFeatureFlag'
2020
import { FuzzyFSM } from './FuzzyFsm'
2121
import { FuzzyRepoRevision } from './FuzzyRepoRevision'
2222
import { FuzzyRepos } from './FuzzyRepos'
@@ -252,7 +252,7 @@ export function useFuzzyState(props: FuzzyTabsProps): FuzzyState {
252252
repoRevisionRef.current = repoRevision
253253

254254
const { fuzzyFinderAll, fuzzyFinderActions, fuzzyFinderRepositories, fuzzyFinderSymbols } =
255-
getFuzzyFinderFeatureFlags(props.settingsCascade.final)
255+
useFuzzyFinderFeatureFlags()
256256

257257
const [activeTab, setActiveTab] = useState<FuzzyTabKey>('all')
258258

client/web/src/enterprise/code-monitoring/CodeMonitoringPage.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { catchError, map } from 'rxjs/operators'
77

88
import { asError, isErrorLike } from '@sourcegraph/common'
99
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
10-
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
10+
import { SettingsCascadeProps, useExperimentalFeatures } from '@sourcegraph/shared/src/settings/settings'
1111
import {
1212
PageHeader,
1313
LoadingSpinner,
@@ -21,7 +21,6 @@ import {
2121
import { AuthenticatedUser } from '../../auth'
2222
import { CodeMonitoringLogo } from '../../code-monitoring/CodeMonitoringLogo'
2323
import { PageTitle } from '../../components/PageTitle'
24-
import { useExperimentalFeatures } from '../../stores'
2524
import { eventLogger } from '../../tracking/eventLogger'
2625

2726
import {

0 commit comments

Comments
 (0)