Merge pull request #8019 from supabase/edge-functions-sidepanel-modal

Edge functions sidepanel modal
This commit is contained in:
Joshen Lim authored and GitHub committed 2022-08-03 18:21:17 +08:00
commit 8d2027524a
3 files changed
+44 -23

No files matched your search

@@ -1,4 +1,4 @@
import { FC, useEffect, useContext, createContext, FormEvent } from 'react'
import { FC, useEffect, useContext, createContext, FormEvent, useState } from 'react'
import { isEmpty, mapValues, has, filter, keyBy, isUndefined, partition, isNull } from 'lodash'
import { observer, useLocalObservable } from 'mobx-react-lite'
import {
@@ -12,6 +12,7 @@ import {
Radio,
IconPlus,
Toggle,
Modal,
} from '@supabase/ui'
import { Dictionary } from 'components/grid'
import { makeAutoObservable } from 'mobx'
@@ -20,6 +21,7 @@ import { useStore } from 'hooks'
import Panel from 'components/ui/Panel'
import SqlEditor from 'components/ui/SqlEditor'
import { POSTGRES_DATA_TYPES } from 'components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.constants'
import ConfirmationModal from 'components/ui/ConfirmationModal'
class CreateFunctionFormState {
id: number | undefined
@@ -145,6 +147,7 @@ class CreateFunctionStore implements ICreateFunctionStore {
meta = null
schemas = []
advancedVisible = false
isDirty = false
constructor() {
makeAutoObservable(this)
@@ -172,7 +175,12 @@ class CreateFunctionStore implements ICreateFunctionStore {
this.loading = value
}
setIsDirty = (value: boolean) => {
this.isDirty = value
}
onFormChange = ({ key, value }: { key: string; value: any }) => {
this.isDirty = true
if (has(this.formState, key)) {
const temp = (this.formState as any)[key] as any
;(this.formState as any)[key] = { ...temp, value, error: undefined }
@@ -296,6 +304,8 @@ const CreateFunction: FC<CreateFunctionProps> = ({ func, visible, setVisible })
const _localState = useLocalObservable(() => new CreateFunctionStore())
_localState.meta = meta as any
const [isClosingPanel, setIsClosingPanel] = useState<boolean>(false)
useEffect(() => {
const fetchSchemas = async () => {
await (_localState!.meta as any).schemas.load()
@@ -308,6 +318,7 @@ const CreateFunction: FC<CreateFunctionProps> = ({ func, visible, setVisible })
useEffect(() => {
_localState.formState.reset(func)
_localState.setIsDirty(false)
}, [visible, func])
async function handleSubmit() {
@@ -348,12 +359,16 @@ const CreateFunction: FC<CreateFunctionProps> = ({ func, visible, setVisible })
}
}
function isClosingSidePanel() {
_localState.isDirty ? setIsClosingPanel(true) : setVisible(!visible)
}
return (
<>
<SidePanel
size="large"
visible={visible}
onCancel={() => setVisible(!visible)}
onCancel={isClosingSidePanel}
header={_localState.title}
className="hooks-sidepanel transform transition-all duration-300 ease-in-out mr-0"
loading={_localState.loading}
@@ -436,6 +451,24 @@ const CreateFunction: FC<CreateFunctionProps> = ({ func, visible, setVisible })
)}
</div>
</CreateFunctionContext.Provider>
<ConfirmationModal
visible={isClosingPanel}
header="Confirm to close"
buttonLabel="Confirm"
onSelectCancel={() => setIsClosingPanel(false)}
onSelectConfirm={() => {
setIsClosingPanel(false)
setVisible(!visible)
}}
children={
<Modal.Content>
<p className="text-scale-1100 py-4 text-sm">
There are unsaved changes. Are you sure you want to close the panel? Your changes
will be lost.
</p>
</Modal.Content>
}
/>
</SidePanel>
</>
)
@@ -2,12 +2,11 @@ import Link from 'next/link'
import { useRouter } from 'next/router'
import React, { useEffect } from 'react'
import { observer } from 'mobx-react-lite'
import { IconCode, Loading, Badge } from '@supabase/ui'
import { IconCode, Loading } from '@supabase/ui'
import { useStore, withAuth } from 'hooks'
import FunctionsNav from './FunctionsNav'
import BaseLayout from 'components/layouts'
import WarningBanner from 'components/ui/WarningBanner'
const FunctionsLayout = ({ children }: { children?: React.ReactNode }) => {
const { functions, ui } = useStore()
@@ -58,7 +57,7 @@ const FunctionsLayout = ({ children }: { children?: React.ReactNode }) => {
<IconCode size={14} strokeWidth={3} />
</div>
<div className="flex items-center space-x-4">
<h1 className="text-2xl text-scale-1200">Functions</h1>
<h1 className="text-2xl text-scale-1200">Edge Functions</h1>
<p className="text-scale-1000 mt-1">Beta</p>
</div>
</div>
@@ -85,10 +84,11 @@ const FunctionsLayout = ({ children }: { children?: React.ReactNode }) => {
>
<IconCode size={14} strokeWidth={3} />
</div>
<div className="flex items-center space-x-4">
<Link href={`/project/${ref}/functions`}>
<h1 className="transition-colors text-2xl text-scale-1200 cursor-pointer hover:text-scale-1100">
Functions
Edge Functions
</h1>
</Link>
<p className="text-scale-1000 mt-1">Beta</p>
@@ -119,22 +119,10 @@ const FunctionsLayout = ({ children }: { children?: React.ReactNode }) => {
{item && <FunctionsNav item={item} />}
</div>
<div
// weird repetative styling
className="
h-full flex flex-col flex-grow
w-full mx-auto
transition-all
px-5
lg:px-16
xl:px-24
1xl:px-28
2xl:px-32
gap-4
"
className={[
'h-full flex flex-col flex-grow w-full mx-auto transition-all',
'px-5 lg:px-16 xl:px-24 1xl:px-28 2xl:px-32 gap-4',
].join(' ')}
>
{children}
</div>
@@ -72,7 +72,7 @@ export const generateProductRoutes = (ref: string, project?: ProjectBase): Route
? [
{
key: 'functions',
label: 'Functions',
label: 'Edge Functions',
icon: <IconCode size={18} strokeWidth={2} />,
link: isProjectBuilding ? buildingUrl : `/project/${ref}/functions`,
},