mirror of
https://github.com/supabase/supabase.git
synced 2026-07-04 06:44:22 +08:00
# Conflicts: # studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx # studio/components/interfaces/Home/ProjectUsage.tsx # studio/components/ui/Usage.tsx # studio/pages/project/[ref]/auth/settings.tsx
759 lines
22 KiB
TypeScript
759 lines
22 KiB
TypeScript
import { FC, useEffect, createContext, useContext } from 'react'
|
|
import { makeAutoObservable } from 'mobx'
|
|
import { observer, useLocalObservable } from 'mobx-react-lite'
|
|
import { isEmpty, mapValues, has, without, union } from 'lodash'
|
|
import {
|
|
Input,
|
|
SidePanel,
|
|
Checkbox,
|
|
Listbox,
|
|
Typography,
|
|
IconPlayCircle,
|
|
IconPauseCircle,
|
|
IconTerminal,
|
|
Badge,
|
|
Button,
|
|
} from '@supabase/ui'
|
|
import { Dictionary } from 'components/grid'
|
|
import { useRouter } from 'next/router'
|
|
import SVG from 'react-inlinesvg'
|
|
|
|
import ChooseFunctionForm from './ChooseFunctionForm'
|
|
import FormEmptyBox from 'components/ui/FormBoxEmpty'
|
|
import NoTableState from 'components/ui/States/NoTableState'
|
|
import { useStore } from 'hooks'
|
|
|
|
class CreateTriggerFormState {
|
|
id: number | undefined
|
|
originalName: string | undefined
|
|
// @ts-ignore
|
|
activation: { value: string; error?: string }
|
|
// @ts-ignore
|
|
enabledMode: { value: string }
|
|
// @ts-ignore
|
|
events: { value: string[]; error?: string }
|
|
// @ts-ignore
|
|
functionName: { value: string; error?: string }
|
|
// @ts-ignore
|
|
functionSchema: { value: string; error?: string }
|
|
// @ts-ignore
|
|
orientation: { value: string; error?: string }
|
|
// @ts-ignore
|
|
name: { value: string; error?: string }
|
|
// @ts-ignore
|
|
schema: { value: string }
|
|
// @ts-ignore
|
|
table: { value: string }
|
|
// @ts-ignore
|
|
tableId: { value: number; error?: string }
|
|
|
|
constructor() {
|
|
makeAutoObservable(this)
|
|
this.reset()
|
|
}
|
|
|
|
get requestBody() {
|
|
return {
|
|
id: this.id,
|
|
activation: this.activation.value,
|
|
enabled_mode: this.enabledMode.value,
|
|
events: this.events.value,
|
|
function_name: this.functionName.value,
|
|
function_schema: this.functionSchema.value,
|
|
orientation: this.orientation.value,
|
|
name: this.name.value,
|
|
schema: this.schema.value,
|
|
table: this.table.value,
|
|
}
|
|
}
|
|
|
|
reset(trigger?: Dictionary<any>) {
|
|
this.id = trigger?.id
|
|
this.originalName = trigger?.name
|
|
this.activation = { value: trigger?.activation ?? 'BEFORE' }
|
|
this.enabledMode = { value: trigger?.enabled_mode ?? 'ORIGIN' }
|
|
this.events = { value: trigger?.events ?? [] }
|
|
this.functionName = { value: trigger?.function_name ?? '' }
|
|
this.functionSchema = { value: trigger?.function_schema ?? '' }
|
|
this.orientation = { value: trigger?.orientation ?? 'STATEMENT' }
|
|
this.name = { value: trigger?.name ?? '' }
|
|
this.schema = { value: trigger?.schema ?? '' }
|
|
this.table = { value: trigger?.table ?? '' }
|
|
this.tableId = { value: trigger?.table_id ?? '' }
|
|
}
|
|
|
|
update(state: Dictionary<any>) {
|
|
this.activation = state.activation
|
|
this.enabledMode = state.enabledMode
|
|
this.events = state.events
|
|
this.functionName = state.functionName
|
|
this.functionSchema = state.functionSchema
|
|
this.orientation = state.orientation
|
|
this.name = state.name
|
|
this.schema = state.schema
|
|
this.table = state.table
|
|
this.tableId = state.tableId
|
|
}
|
|
}
|
|
|
|
interface ICreateTriggerStore {
|
|
chooseFunctionFormVisible: boolean
|
|
loading: boolean
|
|
formState: CreateTriggerFormState
|
|
meta: any
|
|
selectedFunction?: Dictionary<any>[]
|
|
tables: Dictionary<any>[]
|
|
triggerFunctions: Dictionary<any>[]
|
|
onFormChange: ({ key, value }: { key: string; value: any }) => void
|
|
onSelectFunction: (id: number) => void
|
|
setChooseFunctionFormVisible: (value: boolean) => void
|
|
setDefaultSelectedTable: () => void
|
|
setLoading: (value: boolean) => void
|
|
setTables: (value: Dictionary<any>[]) => void
|
|
setTriggerFunctions: (value: Dictionary<any>[]) => void
|
|
validateForm: () => boolean
|
|
}
|
|
|
|
class CreateTriggerStore implements ICreateTriggerStore {
|
|
chooseFunctionFormVisible = false
|
|
loading = false
|
|
formState = new CreateTriggerFormState()
|
|
meta = null
|
|
tables = []
|
|
triggerFunctions = []
|
|
|
|
constructor() {
|
|
makeAutoObservable(this)
|
|
}
|
|
|
|
get selectedFunction() {
|
|
const func = this.triggerFunctions.find(
|
|
(x: any) =>
|
|
x.name == this.formState.functionName.value &&
|
|
x.schema == this.formState.functionSchema.value
|
|
)
|
|
return func
|
|
}
|
|
|
|
get title() {
|
|
return this.formState.id ? `Edit '${this.formState.originalName}' trigger` : 'Add a new Trigger'
|
|
}
|
|
|
|
get isEditing() {
|
|
return this.formState.id != undefined
|
|
}
|
|
|
|
setChooseFunctionFormVisible = (value: boolean) => {
|
|
this.chooseFunctionFormVisible = value
|
|
}
|
|
|
|
// set first table as default selection
|
|
setDefaultSelectedTable = () => {
|
|
if (this.tables?.length != 0) {
|
|
this.formState.table.value = (this.tables[0] as any).name
|
|
this.formState.schema.value = (this.tables[0] as any).schema
|
|
this.formState.tableId.value = (this.tables[0] as any).id
|
|
}
|
|
}
|
|
|
|
setLoading = (value: boolean) => {
|
|
this.loading = value
|
|
}
|
|
|
|
setTables = (value: Dictionary<any>[]) => {
|
|
this.tables = value as any
|
|
this.setDefaultSelectedTable()
|
|
}
|
|
|
|
setTriggerFunctions = (value: Dictionary<any>[]) => {
|
|
this.triggerFunctions = value as any
|
|
}
|
|
|
|
onFormChange = ({ key, value }: { key: string; value: any }) => {
|
|
if (has(this.formState, key)) {
|
|
const temp = (this.formState as any)[key]
|
|
// @ts-ignore
|
|
this.formState[key] = { ...temp, value, error: undefined }
|
|
} else {
|
|
// @ts-ignore
|
|
this.formState[key] = { value }
|
|
}
|
|
}
|
|
|
|
onSelectFunction = (id: number) => {
|
|
const func = this.triggerFunctions.find((x: any) => x.id == id)
|
|
if (func) {
|
|
this.formState.functionName.value = (func as any).name
|
|
this.formState.functionSchema.value = (func as any).schema
|
|
}
|
|
}
|
|
|
|
validateForm = () => {
|
|
let isValidated = true
|
|
const _state = mapValues(this.formState, (x: { value: any }, key: string) => {
|
|
switch (key) {
|
|
case 'name': {
|
|
if (isEmpty(x.value) || hasWhitespace(x.value)) {
|
|
isValidated = false
|
|
return { ...x, error: 'Invalid trigger name' }
|
|
} else {
|
|
return x
|
|
}
|
|
}
|
|
case 'activation': {
|
|
if (isEmpty(x.value)) {
|
|
isValidated = false
|
|
return { ...x, error: 'you have an error' }
|
|
} else {
|
|
return x
|
|
}
|
|
}
|
|
case 'events': {
|
|
if (isEmpty(x.value)) {
|
|
isValidated = false
|
|
return { ...x, error: 'Select at least 1 event' }
|
|
} else {
|
|
return x
|
|
}
|
|
}
|
|
case 'tableId': {
|
|
if (isEmpty(`${x.value}`)) {
|
|
isValidated = false
|
|
return { ...x, error: 'You must choose a table' }
|
|
} else {
|
|
return x
|
|
}
|
|
}
|
|
default:
|
|
return x
|
|
}
|
|
})
|
|
if (!isValidated) {
|
|
this.formState.update(_state)
|
|
}
|
|
return isValidated
|
|
}
|
|
}
|
|
|
|
function hasWhitespace(value: string) {
|
|
return /\s/.test(value)
|
|
}
|
|
|
|
const CreateTriggerContext = createContext<ICreateTriggerStore | null>(null)
|
|
|
|
type CreateTriggerProps = {
|
|
trigger?: any
|
|
visible: boolean
|
|
setVisible: (value: boolean) => void
|
|
} & any
|
|
|
|
const CreateTrigger: FC<CreateTriggerProps> = ({ trigger, visible, setVisible }) => {
|
|
const { ui, meta } = useStore()
|
|
const _localState = useLocalObservable(() => new CreateTriggerStore())
|
|
_localState.meta = meta as any
|
|
|
|
// for the empty 'no tables' state link
|
|
const router = useRouter()
|
|
const { ref } = router.query
|
|
|
|
useEffect(() => {
|
|
const fetchTables = async () => {
|
|
await (_localState!.meta as any)!.tables!.load()
|
|
const tables = (_localState!.meta as any)!.tables.list()
|
|
_localState.setTables(tables)
|
|
}
|
|
const fetchFunctions = async () => {
|
|
await (_localState.meta as any).functions.load()
|
|
const triggerFuncs = (_localState!.meta as any)!.functions.listTriggerFunctions()
|
|
_localState.setTriggerFunctions(triggerFuncs)
|
|
}
|
|
|
|
fetchTables()
|
|
fetchFunctions()
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (trigger) {
|
|
_localState.formState.reset(trigger)
|
|
} else {
|
|
_localState.formState.reset()
|
|
_localState.setDefaultSelectedTable()
|
|
}
|
|
}, [visible, trigger])
|
|
|
|
async function handleSubmit() {
|
|
try {
|
|
if (_localState.validateForm()) {
|
|
_localState.setLoading(true)
|
|
|
|
const body = _localState.formState.requestBody
|
|
const response: any = _localState.isEditing
|
|
? await (_localState.meta as any).triggers.update(body.id, body)
|
|
: await (_localState.meta as any).triggers.create(body)
|
|
|
|
if (response.error) {
|
|
ui.setNotification({
|
|
category: 'error',
|
|
message: `Failed to create trigger: ${
|
|
response.error?.message ?? 'submit request failed'
|
|
}`,
|
|
})
|
|
_localState.setLoading(false)
|
|
} else {
|
|
ui.setNotification({
|
|
category: 'success',
|
|
message: `${_localState.isEditing ? 'Updated' : 'Created new'} trigger called ${
|
|
response.name
|
|
}`,
|
|
})
|
|
_localState.setLoading(false)
|
|
setVisible(!visible)
|
|
}
|
|
}
|
|
} catch (error: any) {
|
|
ui.setNotification({
|
|
category: 'error',
|
|
message: `Filed to create trigger: ${error.message}`,
|
|
})
|
|
_localState.setLoading(false)
|
|
}
|
|
}
|
|
|
|
const hasPublicTables = _localState.tables.length >= 1
|
|
|
|
return (
|
|
<>
|
|
<SidePanel
|
|
size="large"
|
|
visible={visible}
|
|
onCancel={() => setVisible(!visible)}
|
|
header={_localState.title}
|
|
hideFooter={!hasPublicTables}
|
|
className={
|
|
_localState.chooseFunctionFormVisible
|
|
? 'hooks-sidepanel transform transition-all duration-300 ease-in-out mr-16'
|
|
: 'hooks-sidepanel transform transition-all duration-300 ease-in-out mr-0'
|
|
}
|
|
loading={_localState.loading}
|
|
onConfirm={handleSubmit}
|
|
>
|
|
{hasPublicTables ? (
|
|
<div className="">
|
|
<CreateTriggerContext.Provider value={_localState}>
|
|
<div className="space-y-10 my-6">
|
|
{_localState.isEditing ? (
|
|
<div className="px-6 space-y-6">
|
|
<InputName />
|
|
<SelectEnabledMode />
|
|
</div>
|
|
) : (
|
|
<>
|
|
<div className="px-6">
|
|
<InputName />
|
|
</div>
|
|
<SidePanel.Seperator />
|
|
<div className="px-6 space-y-12">
|
|
<Typography.Title level={5}>Conditions to fire trigger</Typography.Title>
|
|
<ListboxTable />
|
|
<CheckboxEvents />
|
|
<ListboxActivation />
|
|
<SelectOrientation />
|
|
</div>
|
|
<SidePanel.Seperator />
|
|
<FunctionForm />
|
|
</>
|
|
)}
|
|
</div>
|
|
<ChooseFunctionForm
|
|
triggerFunctions={_localState.triggerFunctions}
|
|
visible={_localState.chooseFunctionFormVisible}
|
|
setVisible={_localState.setChooseFunctionFormVisible}
|
|
onChange={(id: number) => _localState.onSelectFunction(id)}
|
|
/>
|
|
</CreateTriggerContext.Provider>
|
|
</div>
|
|
) : (
|
|
<NoTableState message="You will need to create a table first before you can make a trigger" />
|
|
)}
|
|
</SidePanel>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default observer(CreateTrigger)
|
|
|
|
const InputName: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
return (
|
|
<Input
|
|
id="name"
|
|
label="Name of trigger"
|
|
layout="horizontal"
|
|
placeholder="Name of trigger"
|
|
value={_localState!.formState.name.value}
|
|
onChange={(e) =>
|
|
_localState!.onFormChange({
|
|
key: 'name',
|
|
value: e.target.value,
|
|
})
|
|
}
|
|
size="small"
|
|
error={_localState!.formState.name.error}
|
|
descriptionText="The name is also stored as the actual postgres name of the trigger. Do not use spaces/whitespace."
|
|
/>
|
|
)
|
|
})
|
|
|
|
const SelectEnabledMode: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
return (
|
|
<Listbox
|
|
id="enabled-mode"
|
|
label="Enabled mode"
|
|
layout="horizontal"
|
|
value={_localState!.formState.enabledMode.value}
|
|
onChange={(value) =>
|
|
_localState!.onFormChange({
|
|
key: 'enabledMode',
|
|
value: value,
|
|
})
|
|
}
|
|
size="small"
|
|
descriptionText="Determines if a trigger should or should not fire. Can also be used to disable a trigger, but not delete it."
|
|
>
|
|
<Listbox.Option
|
|
addOnBefore={({ active, selected }: any) => {
|
|
return (
|
|
<div className="bg-green-900 border border-green-700 shadow-sm w-3 h-3 rounded-full"></div>
|
|
)
|
|
}}
|
|
value="ORIGIN"
|
|
label="Origin"
|
|
>
|
|
Origin
|
|
<span className="text-scale-900 block">This is a default behaviour</span>
|
|
</Listbox.Option>
|
|
<Listbox.Option
|
|
addOnBefore={({ active, selected }: any) => {
|
|
return (
|
|
<div className="bg-green-900 border border-green-700 shadow-sm w-3 h-3 rounded-full"></div>
|
|
)
|
|
}}
|
|
value="REPLICA"
|
|
label="Replica"
|
|
>
|
|
Replica
|
|
<span className="text-scale-900 block">
|
|
Will only fire if the session is in “replica” mode
|
|
</span>
|
|
</Listbox.Option>
|
|
<Listbox.Option
|
|
addOnBefore={({ active, selected }: any) => {
|
|
return (
|
|
<div className="bg-green-900 border border-green-700 shadow-sm w-3 h-3 rounded-full"></div>
|
|
)
|
|
}}
|
|
value="ALWAYS"
|
|
label="Always"
|
|
>
|
|
Always
|
|
<span className="text-scale-900 block">
|
|
Will fire regardless of the current replication role
|
|
</span>
|
|
</Listbox.Option>
|
|
<Listbox.Option
|
|
addOnBefore={({ active, selected }: any) => {
|
|
return (
|
|
<div className="bg-red-900 border border-red-700 shadow-sm w-3 h-3 rounded-full"></div>
|
|
)
|
|
}}
|
|
value="DISABLED"
|
|
label="Disabled"
|
|
>
|
|
Disabled
|
|
<span className="text-scale-900 block">Will not fire</span>
|
|
</Listbox.Option>
|
|
</Listbox>
|
|
)
|
|
})
|
|
|
|
const SelectOrientation: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
return (
|
|
<Listbox
|
|
id="orientation"
|
|
label="Orientation"
|
|
layout="horizontal"
|
|
value={_localState!.formState.orientation.value}
|
|
onChange={(value) =>
|
|
_localState!.onFormChange({
|
|
key: 'orientation',
|
|
value: value,
|
|
})
|
|
}
|
|
size="small"
|
|
descriptionText="Identifies whether the trigger fires once for each processed row or once for each statement"
|
|
>
|
|
<Listbox.Option value="ROW" label="Row">
|
|
Row
|
|
<span className="text-scale-900 block">fires once for each processed row</span>
|
|
</Listbox.Option>
|
|
<Listbox.Option value="STATEMENT" label="Statement">
|
|
Statement
|
|
<span className="text-scale-900 block">fires once for each statement</span>
|
|
</Listbox.Option>
|
|
</Listbox>
|
|
)
|
|
})
|
|
|
|
const ListboxTable: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
|
|
return (
|
|
<Listbox
|
|
id="table"
|
|
label="Table"
|
|
layout="horizontal"
|
|
value={_localState!.formState.tableId.value}
|
|
onChange={(id) => {
|
|
const _table = _localState!.tables.find((x) => x.id === id)
|
|
if (_table) {
|
|
_localState!.onFormChange({
|
|
key: 'table',
|
|
value: _table.name,
|
|
})
|
|
_localState!.onFormChange({
|
|
key: 'schema',
|
|
value: _table.schema,
|
|
})
|
|
_localState!.onFormChange({
|
|
key: 'tableId',
|
|
value: id,
|
|
})
|
|
}
|
|
}}
|
|
size="small"
|
|
error={_localState!.formState.tableId.error}
|
|
descriptionText="This is the table the trigger will watch for changes. You can only select 1 table for a trigger."
|
|
>
|
|
{_localState!.tables.map((x) => {
|
|
return (
|
|
<Listbox.Option
|
|
id={x.id}
|
|
key={x.id}
|
|
value={x.id}
|
|
label={x.name}
|
|
addOnBefore={() => (
|
|
<div className="bg-scale-1200 p-1 flex items-center justify-center rounded text-scale-100 ">
|
|
<SVG
|
|
src={'/img/table-editor.svg'}
|
|
style={{ width: `16px`, height: `16px`, strokeWidth: '1px' }}
|
|
preProcessor={(code) =>
|
|
code.replace(/svg/, 'svg class="m-auto text-color-inherit"')
|
|
}
|
|
/>
|
|
</div>
|
|
)}
|
|
>
|
|
<div className="flex flex-row items-center space-x-1">
|
|
<Typography.Text>{x.name}</Typography.Text>
|
|
<Typography.Text type="secondary" className="text-scale-900" small>
|
|
{x.schema}
|
|
</Typography.Text>
|
|
</div>
|
|
</Listbox.Option>
|
|
)
|
|
})}
|
|
</Listbox>
|
|
)
|
|
})
|
|
|
|
const CheckboxEvents: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
return (
|
|
// @ts-ignore
|
|
<Checkbox.Group
|
|
name="events"
|
|
label="Events"
|
|
id="events"
|
|
labelOptional="The type of events that will trigger your trigger"
|
|
layout="horizontal"
|
|
descriptionText="These are the events that are watched by the trigger, only the events selected above will fire the trigger on the table you've selected."
|
|
size="small"
|
|
onChange={(e) => {
|
|
const temp = _localState!.formState.events.value
|
|
const value = e.target.checked
|
|
? union(temp, [e.target.value])
|
|
: without(temp, e.target.value)
|
|
_localState!.onFormChange({
|
|
key: 'events',
|
|
value: value,
|
|
})
|
|
}}
|
|
error={_localState!.formState.events.error}
|
|
>
|
|
<Checkbox
|
|
value="INSERT"
|
|
label="Insert"
|
|
description={'Any insert operation on the table'}
|
|
checked={_localState!.formState.events.value.includes('INSERT')}
|
|
/>
|
|
<Checkbox
|
|
value="UPDATE"
|
|
label="Update"
|
|
description="Any update operation, of any column in the table"
|
|
checked={_localState!.formState.events.value.includes('UPDATE')}
|
|
/>
|
|
<Checkbox
|
|
value="DELETE"
|
|
label="Delete"
|
|
description="Any deletion of a record"
|
|
checked={_localState!.formState.events.value.includes('DELETE')}
|
|
/>
|
|
</Checkbox.Group>
|
|
)
|
|
})
|
|
|
|
const ListboxActivation: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
return (
|
|
<Listbox
|
|
id="activation"
|
|
label="Trigger type"
|
|
descriptionText="This determines when your Hook fires"
|
|
onChange={(_value) => {
|
|
_localState!.onFormChange({
|
|
key: 'activation',
|
|
value: _value,
|
|
})
|
|
}}
|
|
value={_localState!.formState.activation.value}
|
|
layout="horizontal"
|
|
size="small"
|
|
error={_localState!.formState.activation.error}
|
|
>
|
|
<Listbox.Option
|
|
id={'before'}
|
|
value={'BEFORE'}
|
|
label={'Before the event'}
|
|
addOnBefore={() => (
|
|
<div className="bg-scale-1200 p-1 flex items-center justify-center rounded text-scale-100 ">
|
|
<IconPauseCircle strokeWidth={2} size="small" />
|
|
</div>
|
|
)}
|
|
>
|
|
<div className="flex flex-col">
|
|
<span>{'before'}</span>
|
|
<span className="text-scale-900 block">
|
|
Trigger fires before the operation is attempted
|
|
</span>
|
|
</div>
|
|
</Listbox.Option>
|
|
<Listbox.Option
|
|
id={'after'}
|
|
value={'AFTER'}
|
|
label={'After the event'}
|
|
addOnBefore={() => (
|
|
<div className="bg-green-1200 p-1 flex items-center justify-center rounded text-scale-100 ">
|
|
<IconPlayCircle strokeWidth={2} size="small" />
|
|
</div>
|
|
)}
|
|
>
|
|
<div className="flex flex-col">
|
|
<span>{'after'}</span>
|
|
<span className="text-scale-900 block">
|
|
Trigger fires after the operation has completed
|
|
</span>
|
|
</div>
|
|
</Listbox.Option>
|
|
</Listbox>
|
|
)
|
|
})
|
|
|
|
const FunctionForm: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="px-6 space-y-6">
|
|
<Typography.Title level={5}>Function to trigger</Typography.Title>
|
|
</div>
|
|
<div className="px-6">
|
|
{isEmpty(_localState!.formState.functionName.value) ? (
|
|
<FunctionEmpty />
|
|
) : (
|
|
<FunctionWithArguments />
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
})
|
|
|
|
const FunctionEmpty: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
return (
|
|
<button
|
|
type="button"
|
|
onClick={() => _localState!.setChooseFunctionFormVisible(true)}
|
|
className="w-full relative
|
|
transition-all
|
|
|
|
shadow-sm
|
|
border bg-scale-200 dark:bg-scale-400
|
|
border-scale-600
|
|
rounded
|
|
hover:border-scale-700
|
|
hover:bg-scale-300 dark:hover:bg-scale-500
|
|
px-5 py-1
|
|
|
|
"
|
|
>
|
|
<FormEmptyBox
|
|
icon={<IconTerminal size={14} strokeWidth={2} />}
|
|
text="Choose a function to trigger"
|
|
/>
|
|
</button>
|
|
)
|
|
})
|
|
|
|
const FunctionWithArguments: FC = observer(({}) => {
|
|
const _localState = useContext(CreateTriggerContext)
|
|
|
|
return (
|
|
<>
|
|
<div
|
|
className="
|
|
|
|
|
|
w-full
|
|
|
|
relative
|
|
transition-shadow shadow-sm
|
|
border border-scale-200 dark:border-scale-500
|
|
rounded
|
|
|
|
|
|
px-5 py-4
|
|
flex space-x-3 items-center justify-between"
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<div className="flex rounded w-6 h-6 bg-scale-1200 text-scale-100 focus-within:bg-opacity-10 items-center justify-center">
|
|
<IconTerminal size="small" strokeWidth={2} width={14} />
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Typography.Text type="secondary">
|
|
{_localState!.formState.functionName.value}
|
|
</Typography.Text>
|
|
<div>
|
|
<Badge>{_localState!.formState.functionSchema.value}</Badge>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Button type="default" onClick={() => _localState!.setChooseFunctionFormVisible(true)}>
|
|
Change function
|
|
</Button>
|
|
</div>
|
|
</>
|
|
)
|
|
})
|