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
38 changes: 30 additions & 8 deletions apps/studio/components/interfaces/BranchManagement/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,14 @@ const PreviewBranchActions = ({

const { data } = useBranchQuery({ projectRef, branchRef })
const isBranchActiveHealthy = data?.status === 'ACTIVE_HEALTHY'
const isPersistentBranch = branch.persistent

const [showConfirmResetModal, setShowConfirmResetModal] = useState(false)
const [showBranchModeSwitch, setShowBranchModeSwitch] = useState(false)
const [
showPersistentBranchDeleteConfirmationModal,
setShowPersistentBranchDeleteConfirmationModal,
] = useState(false)
const [showEditBranchModal, setShowEditBranchModal] = useState(false)

const { mutate: resetBranch, isLoading: isResetting } = useBranchResetMutation({
Expand Down Expand Up @@ -210,6 +215,15 @@ const PreviewBranchActions = ({
updateBranch({ branchRef, projectRef, persistent: !branch.persistent })
}

const onDeleteBranch = (e: Event | React.MouseEvent<HTMLDivElement>) => {
if (isPersistentBranch) {
setShowPersistentBranchDeleteConfirmationModal(true)
} else {
e.stopPropagation()
onSelectDeleteBranch()
}
}

return (
<>
<DropdownMenu>
Expand Down Expand Up @@ -307,14 +321,8 @@ const PreviewBranchActions = ({
<DropdownMenuItemTooltip
className="gap-x-2"
disabled={!canDeleteBranches}
onSelect={(e) => {
e.stopPropagation()
onSelectDeleteBranch()
}}
onClick={(e) => {
e.stopPropagation()
onSelectDeleteBranch()
}}
onSelect={onDeleteBranch}
onClick={onDeleteBranch}
tooltip={{
content: {
side: 'left',
Expand Down Expand Up @@ -373,6 +381,20 @@ const PreviewBranchActions = ({
</p>
</ConfirmationModal>

<ConfirmationModal
variant="warning"
visible={showPersistentBranchDeleteConfirmationModal}
confirmLabel={'Switch to preview'}
title="Branch must be switched to preview before deletion"
loading={isUpdatingBranch}
onCancel={() => setShowPersistentBranchDeleteConfirmationModal(false)}
onConfirm={onTogglePersistent}
>
<p className="text-sm text-foreground-light">
You must switch the branch "{branch.name}" to preview before deleting it.
</p>
</ConfirmationModal>

<EditBranchModal
branch={branch}
visible={showEditBranchModal}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
TRIGGER_ORIENTATIONS,
TRIGGER_TYPES,
} from './Triggers.constants'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'

const formId = 'create-trigger'

Expand Down Expand Up @@ -75,20 +76,27 @@ const defaultValues: z.infer<typeof FormSchema> = {

interface TriggerSheetProps {
selectedTrigger?: PostgresTrigger
isDuplicatingTrigger?: boolean
open: boolean
setOpen: (val: boolean) => void
onClose: () => void
}

export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetProps) => {
export const TriggerSheet = ({
selectedTrigger,
isDuplicatingTrigger,
open,
onClose,
}: TriggerSheetProps) => {
const { data: project } = useSelectedProjectQuery()

const [isClosingPanel, setIsClosingPanel] = useState(false)
const [showFunctionSelector, setShowFunctionSelector] = useState(false)

const { mutate: createDatabaseTrigger, isLoading: isCreating } = useDatabaseTriggerCreateMutation(
{
onSuccess: (res) => {
toast.success(`Successfully created trigger ${res.name}`)
setOpen(false)
onSuccess: () => {
toast.success(`Successfully created trigger`)
onClose()
},
onError: (error) => {
toast.error(`Failed to create trigger: ${error.message}`)
Expand All @@ -97,9 +105,9 @@ export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetPro
)
const { mutate: updateDatabaseTrigger, isLoading: isUpdating } = useDatabaseTriggerUpdateMutation(
{
onSuccess: (res) => {
toast.success(`Successfully updated trigger ${res.name}`)
setOpen(false)
onSuccess: () => {
toast.success(`Successfully updated trigger`)
onClose()
},
onError: (error) => {
toast.error(`Failed to update trigger: ${error.message}`)
Expand All @@ -117,7 +125,7 @@ export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetPro
const tables = data
.sort((a, b) => a.schema.localeCompare(b.schema))
.filter((a) => !protectedSchemas.find((s) => s.name === a.schema))
const isEditing = !!selectedTrigger
const isEditing = !isDuplicatingTrigger && !!selectedTrigger

const form = useForm<z.infer<typeof FormSchema>>({
mode: 'onSubmit',
Expand All @@ -127,6 +135,10 @@ export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetPro
})
const { function_name, function_schema } = form.watch()

function isClosingSidePanel() {
form.formState.isDirty ? setIsClosingPanel(true) : onClose()
}

const onSubmit: SubmitHandler<z.infer<typeof FormSchema>> = async (values) => {
if (!project) return console.error('Project is required')
const { tableId, ...payload } = values
Expand All @@ -151,7 +163,16 @@ export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetPro
if (open && isSuccess) {
form.clearErrors()

if (isEditing) {
if (isDuplicatingTrigger && selectedTrigger) {
const initalSelectedTable = tables.find((t) => t.name === selectedTrigger.table)

form.reset({
...selectedTrigger,
tableId: initalSelectedTable?.id.toString(),
table: initalSelectedTable?.name,
schema: initalSelectedTable?.schema,
})
} else if (isEditing) {
form.reset(selectedTrigger)
} else if (tables.length > 0) {
form.reset({
Expand All @@ -167,13 +188,15 @@ export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetPro

return (
<>
<Sheet open={open} onOpenChange={setOpen}>
<Sheet open={open} onOpenChange={isClosingSidePanel}>
<SheetContent size="lg" className="flex flex-col gap-0">
<SheetHeader>
<SheetTitle>
{isEditing
? `Edit database trigger: ${selectedTrigger.name}`
: 'Create a new database trigger'}
{isDuplicatingTrigger
? 'Duplicate trigger'
: isEditing
? `Edit database trigger: ${selectedTrigger.name}`
: 'Create a new database trigger'}
</SheetTitle>
</SheetHeader>

Expand Down Expand Up @@ -250,10 +273,12 @@ export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetPro
<Select_Shadcn_
defaultValue={field.value}
onValueChange={(val) => {
// mark table ID as dirty to trigger validation
field.onChange(val)
const table = tables.find((x) => x.id.toString() === val)
if (table) {
form.setValue('table', table.name)
form.setValue('schema', table.schema)
form.setValue('table', table.name, { shouldDirty: true })
form.setValue('schema', table.schema, { shouldDirty: true })
}
}}
>
Expand Down Expand Up @@ -446,14 +471,30 @@ export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetPro
type="default"
htmlType="reset"
disabled={isCreating || isUpdating}
onClick={() => setOpen(false)}
onClick={onClose}
>
Cancel
</Button>
<Button form={formId} htmlType="submit" loading={isCreating || isUpdating}>
{isEditing ? 'Save' : 'Create'} trigger
</Button>
</SheetFooter>

<ConfirmationModal
visible={isClosingPanel}
title="Discard changes"
confirmLabel="Discard"
onCancel={() => setIsClosingPanel(false)}
onConfirm={() => {
setIsClosingPanel(false)
onClose()
}}
>
<p className="text-sm text-foreground-light">
There are unsaved changes. Are you sure you want to close the panel? Your changes will
be lost.
</p>
</ConfirmationModal>
</SheetContent>
</Sheet>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { includes, sortBy } from 'lodash'
import { Check, Edit, Edit2, MoreVertical, Trash, X } from 'lucide-react'
import { Check, Copy, Edit, Edit2, MoreVertical, Trash, X } from 'lucide-react'

import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { useDatabaseTriggersQuery } from 'data/database-triggers/database-triggers-query'
Expand All @@ -13,6 +13,7 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
TableCell,
TableRow,
Expand All @@ -21,20 +22,23 @@ import {
TooltipTrigger,
} from 'ui'
import { generateTriggerCreateSQL } from './TriggerList.utils'
import { PostgresTrigger } from '@supabase/postgres-meta'

interface TriggerListProps {
schema: string
filterString: string
isLocked: boolean
editTrigger: (trigger: any) => void
deleteTrigger: (trigger: any) => void
editTrigger: (trigger: PostgresTrigger) => void
duplicateTrigger: (trigger: PostgresTrigger) => void
deleteTrigger: (trigger: PostgresTrigger) => void
}

const TriggerList = ({
schema,
filterString,
isLocked,
editTrigger,
duplicateTrigger,
deleteTrigger,
}: TriggerListProps) => {
const { data: project } = useSelectedProjectQuery()
Expand Down Expand Up @@ -197,6 +201,11 @@ const TriggerList = ({
<Edit size={14} />
<p>Edit with Assistant</p>
</DropdownMenuItem>
<DropdownMenuItem className="space-x-2" onClick={() => duplicateTrigger(x)}>
<Copy size={14} />
<p>Duplicate trigger</p>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem className="space-x-2" onClick={() => deleteTrigger(x)}>
<Trash stroke="red" size={14} />
<p>Delete trigger</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ import Link from 'next/link'
interface TriggersListProps {
createTrigger: () => void
editTrigger: (trigger: PostgresTrigger) => void
duplicateTrigger: (trigger: PostgresTrigger) => void
deleteTrigger: (trigger: PostgresTrigger) => void
}

const TriggersList = ({
createTrigger = noop,
editTrigger = noop,
duplicateTrigger = noop,
deleteTrigger = noop,
}: TriggersListProps) => {
const { data: project } = useSelectedProjectQuery()
Expand Down Expand Up @@ -232,6 +234,7 @@ const TriggersList = ({
filterString={filterString}
isLocked={isSchemaLocked}
editTrigger={editTrigger}
duplicateTrigger={duplicateTrigger}
deleteTrigger={deleteTrigger}
/>
</TableBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useEffect, useState } from 'react'

import { Markdown } from 'components/interfaces/Markdown'
import { onErrorChat } from 'components/ui/AIAssistantPanel/AIAssistant.utils'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { BASE_PATH } from 'lib/constants'
import { useTrack } from 'lib/telemetry/track'
import { AiIconAnimation, Button, Label_Shadcn_, Textarea } from 'ui'

interface SupabaseService {
Expand Down Expand Up @@ -34,7 +34,7 @@ export const SchemaGenerator = ({
const [hasSql, setHasSql] = useState(false)

const [promptIntendSent, setPromptIntendSent] = useState(false)
const { mutate: sendEvent } = useSendEventMutation()
const track = useTrack()

const { messages, setMessages, sendMessage, status, addToolResult } = useChat({
id: 'schema-generator',
Expand Down Expand Up @@ -193,18 +193,12 @@ export const SchemaGenerator = ({
const isNewPrompt = messages.length == 0
// distinguish between initial step or second step
if (step === 'initial') {
sendEvent({
action: 'project_creation_initial_step_prompt_intended',
properties: {
isNewPrompt,
},
track('project_creation_initial_step_prompt_intended', {
isNewPrompt,
})
} else {
sendEvent({
action: 'project_creation_second_step_prompt_intended',
properties: {
isNewPrompt,
},
track('project_creation_second_step_prompt_intended', {
isNewPrompt,
})
}
setPromptIntendSent(true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PostgresTable } from '@supabase/postgres-meta'
import { isEmpty, isUndefined, noop } from 'lodash'
import { useEffect, useState } from 'react'
import { useEffect, useMemo, useState } from 'react'
import { toast } from 'sonner'

import { DocsButton } from 'components/ui/DocsButton'
Expand Down Expand Up @@ -147,8 +147,12 @@ export const TableEditor = ({
connectionString: project?.connectionString,
schema: table?.schema,
})
const foreignKeys = (foreignKeyMeta ?? []).filter(
(fk) => fk.source_schema === table?.schema && fk.source_table === table?.name
const foreignKeys = useMemo(
() =>
(foreignKeyMeta ?? []).filter(
(fk) => fk.source_schema === table?.schema && fk.source_table === table?.name
),
[foreignKeyMeta, table]
)

const onUpdateField = (changes: Partial<TableField>) => {
Expand Down Expand Up @@ -245,7 +249,7 @@ export const TableEditor = ({
} else {
const tableFields = generateTableFieldFromPostgresTable(
table,
foreignKeyMeta || [],
foreignKeyMeta ?? [],
isDuplicating,
isRealtimeEnabled
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export enum QuickstartVariant {
CONTROL = 'control',
AI = 'ai',
TEMPLATES = 'templates',
ASSISTANT = 'assistant',
}

export type TableSuggestion = {
Expand Down
Loading
Loading