Skip to content

Commit 5025560

Browse files
SaxonFCopilotcharislamjoshenlim
authored
Moves inline editor from feature preview to setting (supabase#39892)
* sidebar-manager * storage keys * tests * more ai spots * test fix * revert to default * remove ref * Update apps/studio/state/sidebar-manager-state.tsx Co-authored-by: Copilot <[email protected]> * Update apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx Co-authored-by: Copilot <[email protected]> * fix ts * fix * fux * fux query param * clean * fix * more * mock local storage * simplify * remove provider test * remve useopensidebar * fix(new homepage): open ai assistant on advisor card button clicks * Update apps/studio/components/layouts/ProjectLayout/LayoutSidebar/index.tsx Co-authored-by: Charis <[email protected]> * Update apps/studio/state/sidebar-manager-state.tsx Co-authored-by: Charis <[email protected]> * refine * editor sidebar manager * reset results * move inline editor to account setting * update analytics to standard * copy * add tracking * update copy * fixes * Update apps/studio/pages/project/[ref]/database/functions.tsx Co-authored-by: Copilot <[email protected]> * Update apps/studio/pages/project/[ref]/auth/policies.tsx Co-authored-by: Copilot <[email protected]> * zod resolver * Nit refacotr * Small fixes * missed two pieces * change event --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Charis Lam <[email protected]> Co-authored-by: Joshen Lim <[email protected]>
1 parent 2fdba90 commit 5025560

File tree

12 files changed

+273
-74
lines changed

12 files changed

+273
-74
lines changed

apps/studio/components/interfaces/Account/Preferences/AnalyticsSettings.tsx

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,72 @@
1-
import { Toggle } from 'ui'
1+
import { zodResolver } from '@hookform/resolvers/zod'
2+
import { useForm } from 'react-hook-form'
23
import { toast } from 'sonner'
4+
import * as z from 'zod'
5+
36
import { useConsentState } from 'common'
47
import Panel from 'components/ui/Panel'
58
import { useSendResetMutation } from 'data/telemetry/send-reset-mutation'
9+
import { FormControl_Shadcn_, FormField_Shadcn_, Form_Shadcn_, Switch } from 'ui'
10+
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
11+
12+
const AnalyticsSchema = z.object({
13+
telemetryEnabled: z.boolean(),
14+
})
615

716
export const AnalyticsSettings = () => {
817
const { hasAccepted, acceptAll, denyAll, categories } = useConsentState()
918
const hasLoaded = categories !== null
1019

1120
const { mutate: sendReset } = useSendResetMutation()
1221

13-
const onToggleOptIn = () => {
22+
const form = useForm<z.infer<typeof AnalyticsSchema>>({
23+
resolver: zodResolver(AnalyticsSchema),
24+
values: { telemetryEnabled: hasAccepted },
25+
})
26+
27+
const handleToggle = (value: boolean) => {
1428
if (!hasLoaded) {
15-
toast.error(
29+
return toast.error(
1630
"We couldn't load the privacy settings due to an ad blocker or network error. Please disable any ad blockers and try again. If the problem persists, please contact support."
1731
)
18-
return
1932
}
2033

21-
if (hasAccepted) {
34+
if (value) {
35+
acceptAll()
36+
} else {
2237
denyAll()
2338
sendReset()
24-
} else {
25-
acceptAll()
2639
}
40+
41+
form.setValue('telemetryEnabled', value)
2742
}
2843

2944
return (
3045
<Panel title={<h5 key="panel-title">Analytics and Marketing</h5>}>
3146
<Panel.Content>
32-
<Toggle
33-
checked={hasAccepted}
34-
onChange={onToggleOptIn}
35-
label="Send telemetry data from Supabase services"
36-
descriptionText="By opting in to sharing telemetry data, Supabase can analyze usage patterns to enhance user experience and use it for marketing and advertising purposes"
37-
/>
47+
<Form_Shadcn_ {...form}>
48+
<FormField_Shadcn_
49+
control={form.control}
50+
name="telemetryEnabled"
51+
render={({ field }) => (
52+
<FormItemLayout
53+
layout="flex-row-reverse"
54+
label="Send telemetry data from Supabase services"
55+
description="By opting in to sharing telemetry data, Supabase can analyze usage patterns to enhance user experience and use it for marketing and advertising purposes"
56+
>
57+
<FormControl_Shadcn_>
58+
<Switch
59+
checked={field.value}
60+
onCheckedChange={(value) => {
61+
field.onChange(value)
62+
handleToggle(value)
63+
}}
64+
/>
65+
</FormControl_Shadcn_>
66+
</FormItemLayout>
67+
)}
68+
/>
69+
</Form_Shadcn_>
3870
</Panel.Content>
3971
</Panel>
4072
)
Lines changed: 104 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
import { zodResolver } from '@hookform/resolvers/zod'
2+
import { useForm } from 'react-hook-form'
3+
import * as z from 'zod'
4+
15
import { LOCAL_STORAGE_KEYS } from 'common'
26
import { SIDEBAR_KEYS } from 'components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
37
import Panel from 'components/ui/Panel'
48
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
5-
import { KeyboardShortcut, Toggle } from 'ui'
9+
import { FormControl_Shadcn_, FormField_Shadcn_, Form_Shadcn_, KeyboardShortcut, Switch } from 'ui'
10+
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
11+
12+
const HotkeySchema = z.object({
13+
commandMenuEnabled: z.boolean(),
14+
aiAssistantEnabled: z.boolean(),
15+
inlineEditorEnabled: z.boolean(),
16+
})
617

718
export const HotkeySettings = () => {
819
const [inlineEditorEnabled, setInlineEditorEnabled] = useLocalStorageQuery(
@@ -18,6 +29,15 @@ export const HotkeySettings = () => {
1829
true
1930
)
2031

32+
const form = useForm<z.infer<typeof HotkeySchema>>({
33+
resolver: zodResolver(HotkeySchema),
34+
values: {
35+
commandMenuEnabled: commandMenuEnabled ?? true,
36+
aiAssistantEnabled: aiAssistantEnabled ?? true,
37+
inlineEditorEnabled: inlineEditorEnabled ?? true,
38+
},
39+
})
40+
2141
return (
2242
<Panel
2343
title={
@@ -29,38 +49,89 @@ export const HotkeySettings = () => {
2949
</div>
3050
}
3151
>
32-
<Panel.Content className="space-y-2">
33-
<Toggle
34-
checked={commandMenuEnabled}
35-
onChange={() => setCommandMenuEnabled(!commandMenuEnabled)}
36-
label={
37-
<div className="flex items-center gap-x-3">
38-
<KeyboardShortcut keys={['Meta', 'k']} />
39-
<span>Command menu</span>
40-
</div>
41-
}
42-
/>
43-
<Toggle
44-
checked={aiAssistantEnabled}
45-
onChange={() => setAiAssistantEnabled(!aiAssistantEnabled)}
46-
label={
47-
<div className="flex items-center gap-x-3">
48-
<KeyboardShortcut keys={['Meta', 'i']} />
49-
<span>AI Assistant Panel</span>
50-
</div>
51-
}
52-
/>
53-
<Toggle
54-
checked={inlineEditorEnabled}
55-
onChange={() => setInlineEditorEnabled(!inlineEditorEnabled)}
56-
label={
57-
<div className="flex items-center gap-x-3">
58-
<KeyboardShortcut keys={['Meta', 'e']} />
59-
<span>Inline SQL Editor Panel</span>
60-
</div>
61-
}
62-
/>
63-
</Panel.Content>
52+
<Form_Shadcn_ {...form}>
53+
<Panel.Content className="border-b">
54+
<FormField_Shadcn_
55+
control={form.control}
56+
name="commandMenuEnabled"
57+
render={({ field }) => (
58+
<FormItemLayout
59+
layout="flex-row-reverse"
60+
label={
61+
<div className="flex items-center gap-x-3">
62+
<KeyboardShortcut keys={['Meta', 'k']} />
63+
<span>Command menu</span>
64+
</div>
65+
}
66+
>
67+
<FormControl_Shadcn_>
68+
<Switch
69+
checked={field.value}
70+
onCheckedChange={(value) => {
71+
field.onChange(value)
72+
setCommandMenuEnabled(value)
73+
}}
74+
/>
75+
</FormControl_Shadcn_>
76+
</FormItemLayout>
77+
)}
78+
/>
79+
</Panel.Content>
80+
<Panel.Content className="border-b">
81+
<FormField_Shadcn_
82+
control={form.control}
83+
name="aiAssistantEnabled"
84+
render={({ field }) => (
85+
<FormItemLayout
86+
layout="flex-row-reverse"
87+
label={
88+
<div className="flex items-center gap-x-3">
89+
<KeyboardShortcut keys={['Meta', 'i']} />
90+
<span>AI Assistant Panel</span>
91+
</div>
92+
}
93+
>
94+
<FormControl_Shadcn_>
95+
<Switch
96+
checked={field.value}
97+
onCheckedChange={(value) => {
98+
field.onChange(value)
99+
setAiAssistantEnabled(value)
100+
}}
101+
/>
102+
</FormControl_Shadcn_>
103+
</FormItemLayout>
104+
)}
105+
/>
106+
</Panel.Content>
107+
<Panel.Content>
108+
<FormField_Shadcn_
109+
control={form.control}
110+
name="inlineEditorEnabled"
111+
render={({ field }) => (
112+
<FormItemLayout
113+
layout="flex-row-reverse"
114+
label={
115+
<div className="flex items-center gap-x-3">
116+
<KeyboardShortcut keys={['Meta', 'e']} />
117+
<span>Inline SQL Editor Panel</span>
118+
</div>
119+
}
120+
>
121+
<FormControl_Shadcn_>
122+
<Switch
123+
checked={field.value}
124+
onCheckedChange={(value) => {
125+
field.onChange(value)
126+
setInlineEditorEnabled(value)
127+
}}
128+
/>
129+
</FormControl_Shadcn_>
130+
</FormItemLayout>
131+
)}
132+
/>
133+
</Panel.Content>
134+
</Form_Shadcn_>
64135
</Panel>
65136
)
66137
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { zodResolver } from '@hookform/resolvers/zod'
2+
import { useForm } from 'react-hook-form'
3+
import * as z from 'zod'
4+
5+
import { LOCAL_STORAGE_KEYS } from 'common'
6+
import Panel from 'components/ui/Panel'
7+
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
8+
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
9+
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
10+
import { FormControl_Shadcn_, FormField_Shadcn_, Form_Shadcn_, Switch } from 'ui'
11+
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
12+
13+
const InlineEditorSchema = z.object({
14+
inlineEditorEnabled: z.boolean(),
15+
})
16+
17+
export const useIsInlineEditorEnabled = () => {
18+
const [inlineEditorEnabled] = useLocalStorageQuery(
19+
LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR,
20+
false
21+
)
22+
23+
return inlineEditorEnabled ?? false
24+
}
25+
26+
export const InlineEditorSettings = () => {
27+
const [inlineEditorEnabled, setInlineEditorEnabled] = useLocalStorageQuery(
28+
LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR,
29+
false
30+
)
31+
const { data: org } = useSelectedOrganizationQuery()
32+
33+
const { mutate: sendEvent } = useSendEventMutation()
34+
35+
const form = useForm<z.infer<typeof InlineEditorSchema>>({
36+
resolver: zodResolver(InlineEditorSchema),
37+
values: {
38+
inlineEditorEnabled: inlineEditorEnabled ?? false,
39+
},
40+
})
41+
42+
const handleToggle = (value: boolean) => {
43+
setInlineEditorEnabled(value)
44+
form.setValue('inlineEditorEnabled', value)
45+
46+
sendEvent({
47+
action: 'inline_editor_setting_clicked',
48+
properties: {
49+
enabled: value,
50+
},
51+
groups: {
52+
organization: org?.slug,
53+
},
54+
})
55+
}
56+
57+
return (
58+
<Panel title={<h5 id="inline-editor">Dashboard</h5>}>
59+
<Panel.Content>
60+
<Form_Shadcn_ {...form}>
61+
<FormField_Shadcn_
62+
control={form.control}
63+
name="inlineEditorEnabled"
64+
render={({ field }) => (
65+
<FormItemLayout
66+
layout="flex-row-reverse"
67+
label="Edit entities in SQL"
68+
description="When enabled, view and edit policies, triggers, and functions directly in the SQL editor instead of a more beginner-friendly UI panel. Ideal for those comfortable with SQL."
69+
>
70+
<FormControl_Shadcn_>
71+
<Switch
72+
checked={field.value}
73+
onCheckedChange={(value) => {
74+
field.onChange(value)
75+
handleToggle(value)
76+
}}
77+
/>
78+
</FormControl_Shadcn_>
79+
</FormItemLayout>
80+
)}
81+
/>
82+
</Form_Shadcn_>
83+
</Panel.Content>
84+
</Panel>
85+
)
86+
}

apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,6 @@ export const FEATURE_PREVIEWS = [
2929
isNew: true,
3030
isPlatformOnly: true,
3131
},
32-
{
33-
key: LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR,
34-
name: 'Directly edit database entities',
35-
discussionsUrl: 'https://github.com/orgs/supabase/discussions/33690',
36-
isNew: false,
37-
isPlatformOnly: false,
38-
},
3932
{
4033
key: LOCAL_STORAGE_KEYS.UI_PREVIEW_API_SIDE_PANEL,
4134
name: 'Project API documentation',

apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,6 @@ export const useIsColumnLevelPrivilegesEnabled = () => {
8484
return flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_CLS]
8585
}
8686

87-
export const useIsInlineEditorEnabled = () => {
88-
const { flags } = useFeaturePreviewContext()
89-
return flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR]
90-
}
91-
9287
export const useUnifiedLogsPreview = () => {
9388
const { flags, onUpdateFlag } = useFeaturePreviewContext()
9489

apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { Branching2Preview } from './Branching2Preview'
1313
import { CLSPreview } from './CLSPreview'
1414
import { FEATURE_PREVIEWS } from './FeaturePreview.constants'
1515
import { useFeaturePreviewContext, useFeaturePreviewModal } from './FeaturePreviewContext'
16-
import { InlineEditorPreview } from './InlineEditorPreview'
1716
import { SecurityNotificationsPreview } from './SecurityNotificationsPreview'
1817
import { UnifiedLogsPreview } from './UnifiedLogsPreview'
1918

@@ -22,7 +21,6 @@ const FEATURE_PREVIEW_KEY_TO_CONTENT: {
2221
} = {
2322
[LOCAL_STORAGE_KEYS.UI_PREVIEW_BRANCHING_2_0]: <Branching2Preview />,
2423
[LOCAL_STORAGE_KEYS.UI_PREVIEW_ADVISOR_RULES]: <AdvisorRulesPreview />,
25-
[LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR]: <InlineEditorPreview />,
2624
[LOCAL_STORAGE_KEYS.UI_PREVIEW_API_SIDE_PANEL]: <APISidePanelPreview />,
2725
[LOCAL_STORAGE_KEYS.UI_PREVIEW_CLS]: <CLSPreview />,
2826
[LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS]: <UnifiedLogsPreview />,

0 commit comments

Comments
 (0)