Final replacements of ui setNotification with toast (#21885)

* Final replacements of ui setNotification with toast

* Rip out UiStore

* Rip out UiStore

* Shift files under authConfigSchema to components/Auth

* Rip out use of observers
This commit is contained in:
Joshen Lim authored and GitHub committed 2024-03-12 12:56:56 +08:00
1 parent d8394689ca
commit 948a2390fe
55 files changed
+309 -457

No files matched your search

+1 -3
View File
@@ -29,7 +29,6 @@
## Template for building components
```ts
import { observer } from 'mobx-react-lite'
// Declare the prop types of your component
interface ComponentAProps {
@@ -41,6 +40,5 @@ const ComponentA = ({ sampleProp }: ComponentAProps) => {
return <div>ComponentA: {sampleProp}</div>
}
// Observer is so that components listen to mobx store changes
export default observer(ComponentA)
export default ComponentA
```
@@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { PropsWithChildren, useEffect } from 'react'
import toast from 'react-hot-toast'
@@ -125,4 +124,4 @@ const RouteValidationWrapper = ({ children }: PropsWithChildren<{}>) => {
return <>{children}</>
}
export default observer(RouteValidationWrapper)
export default RouteValidationWrapper
@@ -1,10 +1,9 @@
import { useParams } from 'common'
import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, IconAlertCircle } from 'ui'
import { FormHeader } from 'components/ui/Forms'
import { HorizontalShimmerWithIcon } from 'components/ui/Shimmers'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { PROVIDERS_SCHEMAS } from 'stores/authConfig/schema'
import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, IconAlertCircle } from 'ui'
import { PROVIDERS_SCHEMAS } from '../AuthProvidersFormValidation'
import { ProviderCollapsibleClasses } from './AuthProvidersForm.constants'
import ProviderForm from './ProviderForm'
@@ -1331,7 +1331,7 @@ const EXTERNAL_PROVIDER_ZOOM = {
},
}
export const PROVIDER_SAML = {
const PROVIDER_SAML = {
$schema: JSON_SCHEMA_VERSION,
type: 'object',
title: 'SAML 2.0',
@@ -3,7 +3,7 @@ import { object, string } from 'yup'
const JSON_SCHEMA_VERSION = 'http://json-schema.org/draft-07/schema#'
export const CONFIRMATION: FormSchema = {
const CONFIRMATION: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'CONFIRMATION',
type: 'object',
@@ -37,7 +37,7 @@ export const CONFIRMATION: FormSchema = {
},
}
export const INVITE: FormSchema = {
const INVITE: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'INVITE',
type: 'object',
@@ -71,7 +71,7 @@ export const INVITE: FormSchema = {
},
}
export const MAGIC_LINK: FormSchema = {
const MAGIC_LINK: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'MAGIC_LINK',
type: 'object',
@@ -105,7 +105,7 @@ export const MAGIC_LINK: FormSchema = {
},
}
export const EMAIL_CHANGE: FormSchema = {
const EMAIL_CHANGE: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'EMAIL_CHANGE',
type: 'object',
@@ -140,7 +140,7 @@ export const EMAIL_CHANGE: FormSchema = {
},
}
export const RECOVERY: FormSchema = {
const RECOVERY: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'RECOVERY',
type: 'object',
@@ -1,3 +1,7 @@
import { useParams } from 'common'
import { FormHeader, FormPanel } from 'components/ui/Forms'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import {
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
@@ -7,14 +11,9 @@ import {
IconExternalLink,
Tabs,
} from 'ui'
import { useParams } from 'common'
import { FormHeader, FormPanel } from 'components/ui/Forms'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { TEMPLATES_SCHEMAS } from 'stores/authConfig/schema'
import TemplateEditor from './TemplateEditor'
import { TEMPLATES_SCHEMAS } from '../AuthTemplatesValidation'
import EmailRateLimitsAlert from '../EmailRateLimitsAlert'
import TemplateEditor from './TemplateEditor'
const EmailTemplates = () => {
const { ref: projectRef } = useParams()
@@ -1,13 +1,12 @@
import type { PostgresPublication, PostgresTable } from '@supabase/postgres-meta'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { observer } from 'mobx-react-lite'
import { useState } from 'react'
import { Badge, Toggle } from 'ui'
import Table from 'components/to-be-cleaned/Table'
import { useCheckPermissions } from 'hooks'
import { useDatabasePublicationUpdateMutation } from 'data/database-publications/database-publications-update-mutation'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import Table from 'components/to-be-cleaned/Table'
import { useDatabasePublicationUpdateMutation } from 'data/database-publications/database-publications-update-mutation'
import { useCheckPermissions } from 'hooks'
import toast from 'react-hot-toast'
interface PublicationsTableItemProps {
@@ -100,4 +99,4 @@ const PublicationsTableItem = ({ table, selectedPublication }: PublicationsTable
)
}
export default observer(PublicationsTableItem)
export default PublicationsTableItem
@@ -1,6 +1,7 @@
import dagre from '@dagrejs/dagre'
import type { PostgresTable } from '@supabase/postgres-meta'
import { uniqBy } from 'lodash'
import { observer } from 'mobx-react-lite'
import { useTheme } from 'next-themes'
import { useEffect, useMemo } from 'react'
import ReactFlow, {
Background,
@@ -12,12 +13,10 @@ import ReactFlow, {
ReactFlowProvider,
useReactFlow,
} from 'reactflow'
import 'reactflow/dist/style.css'
import type { PostgresTable } from '@supabase/postgres-meta'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import { useTablesQuery } from 'data/tables/tables-query'
import { useTheme } from 'next-themes'
import 'reactflow/dist/style.css'
import { IconLoader } from 'ui'
import { TABLE_NODE_ROW_HEIGHT, TABLE_NODE_WIDTH, TableNode } from 'ui-patterns/SchemaTableNode'
import SchemaGraphLegend from './SchemaGraphLegend'
@@ -306,4 +305,4 @@ const SchemaGraph = ({ schema }: { schema: string }) => {
)
}
export default observer(SchemaGraph)
export default SchemaGraph
@@ -2,7 +2,6 @@ import * as Tooltip from '@radix-ui/react-tooltip'
import type { PostgresTable } from '@supabase/postgres-meta'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { noop } from 'lodash'
import { observer } from 'mobx-react-lite'
import { useState } from 'react'
import {
Button,
@@ -245,4 +244,4 @@ const ColumnList = ({
)
}
export default observer(ColumnList)
export default ColumnList
@@ -1,7 +1,7 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { noop, partition } from 'lodash'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { useState } from 'react'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
@@ -14,7 +14,6 @@ import { useSchemasQuery } from 'data/database/schemas-query'
import { useTablesQuery } from 'data/tables/tables-query'
import { useCheckPermissions } from 'hooks'
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
import { useRouter } from 'next/router'
import { useTableEditorStateSnapshot } from 'state/table-editor'
import {
Button,
@@ -361,4 +360,4 @@ const TableList = ({
)
}
export default observer(TableList)
export default TableList
@@ -1,30 +1,29 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { useParams } from 'common'
import { isEmpty } from 'lodash'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useState } from 'react'
import toast from 'react-hot-toast'
import { Button, Form, IconArrowLeft, IconEdit, IconExternalLink, IconTrash, Input } from 'ui'
import { useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import {
FormActions,
FormPanel,
FormsContainer,
FormSection,
FormSectionContent,
FormSectionLabel,
FormsContainer,
} from 'components/ui/Forms'
import { invalidateSchemasQuery } from 'data/database/schemas-query'
import { useFDWCreateMutation } from 'data/fdw/fdw-create-mutation'
import { useCheckPermissions } from 'hooks'
import { Button, Form, IconArrowLeft, IconEdit, IconExternalLink, IconTrash, Input } from 'ui'
import InputField from './InputField'
import WrapperTableEditor from './WrapperTableEditor'
import { WRAPPERS } from './Wrappers.constants'
import { makeValidateRequired } from './Wrappers.utils'
import WrapperTableEditor from './WrapperTableEditor'
const CreateWrapper = () => {
const formId = 'create-wrapper-form'
@@ -286,4 +285,4 @@ const CreateWrapper = () => {
)
}
export default observer(CreateWrapper)
export default CreateWrapper
@@ -1,13 +1,12 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { useParams } from 'common'
import { isEmpty } from 'lodash'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import toast from 'react-hot-toast'
import { useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import {
FormActions,
@@ -411,4 +410,4 @@ const EditWrapper = () => {
)
}
export default observer(EditWrapper)
export default EditWrapper
@@ -1,13 +1,12 @@
import { groupBy } from 'lodash'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { useState } from 'react'
import { Button, IconExternalLink } from 'ui'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query'
import { FDW, useFDWsQuery } from 'data/fdw/fdws-query'
import { Button, IconExternalLink } from 'ui'
import DeleteWrapperModal from './DeleteWrapperModal'
import WrapperRow from './WrapperRow'
import { WRAPPERS } from './Wrappers.constants'
@@ -117,4 +116,4 @@ const Wrappers = () => {
)
}
export default observer(Wrappers)
export default Wrappers
@@ -1,18 +1,17 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { observer } from 'mobx-react-lite'
import { useTheme } from 'next-themes'
import Link from 'next/link'
import { useState } from 'react'
import toast from 'react-hot-toast'
import { Button, IconExternalLink } from 'ui'
import { useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import { useDatabaseExtensionEnableMutation } from 'data/database-extensions/database-extension-enable-mutation'
import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query'
import { useCheckPermissions } from 'hooks'
import { BASE_PATH } from 'lib/constants'
import { Button, IconExternalLink } from 'ui'
const WrappersDisabledState = () => {
const { ref } = useParams()
@@ -176,4 +175,4 @@ const WrappersDisabledState = () => {
)
}
export default observer(WrappersDisabledState)
export default WrappersDisabledState
@@ -1,9 +1,11 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { observer } from 'mobx-react-lite'
import Image from 'next/legacy/image'
import Link from 'next/link'
import { Fragment } from 'react'
import { useParams } from 'common'
import { useCheckPermissions } from 'hooks'
import {
Button,
DropdownMenu,
@@ -13,9 +15,6 @@ import {
DropdownMenuTrigger,
IconPlus,
} from 'ui'
import { useParams } from 'common/hooks'
import { useCheckPermissions } from 'hooks'
import { WRAPPERS } from './Wrappers.constants'
interface WrapperDropdownProps {
@@ -85,4 +84,4 @@ const WrapperDropdown = ({ buttonText = 'Add wrapper', align = 'end' }: WrapperD
)
}
export default observer(WrapperDropdown)
export default WrapperDropdown
@@ -1,16 +1,15 @@
import { observer } from 'mobx-react-lite'
import { IconAlertCircle } from 'ui'
import dayjs from 'dayjs'
import { NewProjectPanel } from 'components/interfaces/Home'
import { ProjectUsageLoadingState } from 'components/layouts/ProjectLayout/LoadingState'
import InformationBox from 'components/ui/InformationBox'
import { useProjectLogRequestsCountQuery } from 'data/analytics/project-log-requests-count-query'
import { useProjectLogStatsQuery } from 'data/analytics/project-log-stats-query'
import ProjectUsage from './ProjectUsage'
import { useSelectedProject } from 'hooks'
import dayjs from 'dayjs'
import { IconAlertCircle } from 'ui'
import ProjectUsage from './ProjectUsage'
const ProjectUsageSection = observer(() => {
const ProjectUsageSection = () => {
const project = useSelectedProject()
const {
@@ -54,5 +53,6 @@ const ProjectUsageSection = observer(() => {
)}
</>
)
})
}
export default ProjectUsageSection
@@ -17,7 +17,7 @@ import { useOrgPlansQuery } from 'data/subscriptions/org-plans-query'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation'
import type { OrgPlan, SubscriptionTier } from 'data/subscriptions/types'
import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks'
import { useCheckPermissions, useSelectedOrganization } from 'hooks'
import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants'
import { formatCurrency } from 'lib/helpers'
import Telemetry from 'lib/telemetry'
@@ -1,11 +1,10 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { useParams } from 'common'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { useEffect, useState } from 'react'
import toast from 'react-hot-toast'
import { useParams } from 'common'
import NoProjectsOnPaidOrgInfo from 'components/interfaces/Billing/NoProjectsOnPaidOrgInfo'
import { ScaffoldContainerLegacy } from 'components/layouts/Scaffold'
import {
@@ -23,8 +22,8 @@ import { Collapsible, Form, IconChevronRight, Input, Toggle, cn } from 'ui'
import OrganizationDeletePanel from './OrganizationDeletePanel'
const GeneralSettings = () => {
const queryClient = useQueryClient()
const { slug } = useParams()
const queryClient = useQueryClient()
const [open, setOpen] = useState(false)
const selectedOrganization = useSelectedOrganization()
const { name, opt_in_tags } = selectedOrganization ?? {}
@@ -199,4 +198,4 @@ const GeneralSettings = () => {
)
}
export default observer(GeneralSettings)
export default GeneralSettings
@@ -1,10 +1,9 @@
import { observer } from 'mobx-react-lite'
import { Alert } from 'ui'
import Panel from 'components/ui/Panel'
import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_ } from 'ui'
import { CriticalIcon } from 'ui-patterns/Icons/StatusIcons'
import DeleteOrganizationButton from './DeleteOrganizationButton'
const OrganizationDeletePanel = observer(() => {
const OrganizationDeletePanel = () => {
return (
<Panel
title={
@@ -14,24 +13,19 @@ const OrganizationDeletePanel = observer(() => {
}
>
<Panel.Content>
<Alert
withIcon
variant="danger"
// @ts-ignore
title={
<span className="text-red-900">
Deleting this organization will also remove its projects
</span>
}
>
<p className="text-red-900">
<Alert_Shadcn_ variant="destructive">
<CriticalIcon />
<AlertTitle_Shadcn_>
Deleting this organization will also remove its projects
</AlertTitle_Shadcn_>
<AlertDescription_Shadcn_>
Make sure you have made a backup if you want to keep your data
</p>
</AlertDescription_Shadcn_>
<DeleteOrganizationButton />
</Alert>
</Alert_Shadcn_>
</Panel.Content>
</Panel>
)
})
}
export default OrganizationDeletePanel
@@ -1,6 +1,5 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { observer } from 'mobx-react-lite'
import { useState } from 'react'
import toast from 'react-hot-toast'
@@ -208,4 +207,4 @@ const MemberActions = ({ member, roles }: MemberActionsProps) => {
)
}
export default observer(MemberActions)
export default MemberActions
@@ -1,5 +1,4 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import { observer } from 'mobx-react-lite'
import Image from 'next/legacy/image'
import { Fragment, useState } from 'react'
import toast from 'react-hot-toast'
@@ -408,4 +407,4 @@ const MembersView = ({ searchString }: MembersViewProps) => {
)
}
export default observer(MembersView)
export default MembersView
@@ -18,13 +18,7 @@ import { useExecuteSqlMutation } from 'data/sql/execute-sql-mutation'
import { useFormatQueryMutation } from 'data/sql/format-sql-query'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { isError } from 'data/utils/error-check'
import {
useFlag,
useLocalStorageQuery,
useSelectedOrganization,
useSelectedProject,
useStore,
} from 'hooks'
import { useFlag, useLocalStorageQuery, useSelectedOrganization, useSelectedProject } from 'hooks'
import { BASE_PATH, IS_PLATFORM, LOCAL_STORAGE_KEYS, OPT_IN_TAGS } from 'lib/constants'
import { uuidv4 } from 'lib/helpers'
import { useProfile } from 'lib/profile'
@@ -89,7 +83,6 @@ export function useSqlEditor() {
}
const SQLEditor = () => {
const { ui } = useStore()
const { ref, id: urlId } = useParams()
const router = useRouter()
const telemetryProps = useTelemetryProps()
@@ -398,7 +391,7 @@ const SQLEditor = () => {
toast.error(`Failed to create new query: ${error.message}`)
}
},
[profile?.id, project?.id, ref, router, snap, ui]
[profile?.id, project?.id, ref, router, snap]
)
const updateEditorWithCheckForDiff = ({
@@ -1,10 +1,9 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams, useTelemetryProps } from 'common'
import { partition } from 'lodash'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import toast from 'react-hot-toast'
import { useParams, useTelemetryProps } from 'common'
import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries'
import type { SqlSnippet } from 'data/content/sql-snippets-query'
import { useCheckPermissions, useSelectedProject } from 'hooks'
@@ -15,7 +14,7 @@ import { useSqlEditorStateSnapshot } from 'state/sql-editor'
import { createSqlSnippetSkeleton } from '../SQLEditor.utils'
import SQLCard from './SQLCard'
const SQLQuickstarts = observer(() => {
const SQLQuickstarts = () => {
const { ref } = useParams()
const router = useRouter()
const { profile } = useProfile()
@@ -90,6 +89,6 @@ const SQLQuickstarts = observer(() => {
</div>
</div>
)
})
}
export default SQLQuickstarts
@@ -1,14 +1,13 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { partition } from 'lodash'
import { observer } from 'mobx-react-lite'
import toast from 'react-hot-toast'
import { useTelemetryProps } from 'common'
import { useRouter } from 'next/router'
import toast from 'react-hot-toast'
import { useTelemetryProps } from 'common'
import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import type { SqlSnippet } from 'data/content/sql-snippets-query'
import { useCheckPermissions, useStore } from 'hooks'
import { useCheckPermissions } from 'hooks'
import { uuidv4 } from 'lib/helpers'
import { useProfile } from 'lib/profile'
import Telemetry from 'lib/telemetry'
@@ -16,7 +15,7 @@ import { useSqlEditorStateSnapshot } from 'state/sql-editor'
import { createSqlSnippetSkeleton } from '../SQLEditor.utils'
import SQLCard from './SQLCard'
const SQLTemplates = observer(() => {
const SQLTemplates = () => {
const router = useRouter()
const { profile } = useProfile()
const { project } = useProjectContext()
@@ -89,6 +88,6 @@ const SQLTemplates = observer(() => {
</div>
</div>
)
})
}
export default SQLTemplates
@@ -1,6 +1,5 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { indexOf } from 'lodash'
import { observer } from 'mobx-react-lite'
import { useEffect } from 'react'
import toast from 'react-hot-toast'
@@ -188,4 +187,4 @@ const PostgrestConfig = () => {
)
}
export default observer(PostgrestConfig)
export default PostgrestConfig
@@ -1,7 +1,13 @@
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { useState } from 'react'
import toast from 'react-hot-toast'
import Panel from 'components/ui/Panel'
import { useProjectApiQuery } from 'data/config/project-api-query'
import { useCheckCNAMERecordMutation } from 'data/custom-domains/check-cname-mutation'
import { useCustomDomainActivateMutation } from 'data/custom-domains/custom-domains-activate-mutation'
import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation'
import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query'
import {
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
@@ -13,13 +19,6 @@ import {
} from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import Panel from 'components/ui/Panel'
import { useProjectApiQuery } from 'data/config/project-api-query'
import { useCheckCNAMERecordMutation } from 'data/custom-domains/check-cname-mutation'
import { useCustomDomainActivateMutation } from 'data/custom-domains/custom-domains-activate-mutation'
import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation'
import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query'
export type CustomDomainActivateProps = {
projectRef?: string
customDomain: CustomDomainResponse
@@ -167,4 +166,4 @@ const CustomDomainActivate = ({ projectRef, customDomain }: CustomDomainActivate
)
}
export default observer(CustomDomainActivate)
export default CustomDomainActivate
@@ -1,13 +1,12 @@
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { useState } from 'react'
import toast from 'react-hot-toast'
import { Button, IconExternalLink, IconTrash } from 'ui'
import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog'
import Panel from 'components/ui/Panel'
import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation'
import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query'
import { Button, IconExternalLink, IconTrash } from 'ui'
import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog'
export type CustomDomainDeleteProps = {
projectRef?: string
@@ -88,4 +87,4 @@ const CustomDomainDelete = ({ projectRef, customDomain }: CustomDomainDeleteProp
)
}
export default observer(CustomDomainDelete)
export default CustomDomainDelete
@@ -1,8 +1,12 @@
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { useState } from 'react'
import Panel from 'components/ui/Panel'
import type { ProjectApiResponse } from 'data/config/project-api-query'
import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation'
import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query'
import { useCustomDomainReverifyMutation } from 'data/custom-domains/custom-domains-reverify-mutation'
import {
Alert,
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
Alert_Shadcn_,
@@ -12,12 +16,7 @@ import {
IconHelpCircle,
IconRefreshCw,
} from 'ui'
import Panel from 'components/ui/Panel'
import type { ProjectApiResponse } from 'data/config/project-api-query'
import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation'
import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query'
import { useCustomDomainReverifyMutation } from 'data/custom-domains/custom-domains-reverify-mutation'
import { WarningIcon } from 'ui-patterns/Icons/StatusIcons'
import DNSRecord from './DNSRecord'
export type CustomDomainVerifyProps = {
@@ -120,21 +119,27 @@ const CustomDomainVerify = ({ projectRef, customDomain, settings }: CustomDomain
</div>
{hasCAAErrors && (
<Alert
withIcon
variant="warning"
title="Certificate Authority Authentication (CAA) error"
>
Please add a CAA record allowing "digicert.com" to issue certificates for{' '}
<code className="text-xs">{customDomain.hostname}</code>. For example:{' '}
<code className="text-xs">0 issue "digicert.com"</code>
</Alert>
<Alert_Shadcn_>
<WarningIcon />
<AlertTitle_Shadcn_>
Certificate Authority Authentication (CAA) error
</AlertTitle_Shadcn_>
<AlertDescription_Shadcn_>
Please add a CAA record allowing "digicert.com" to issue certificates for{' '}
<code className="text-xs">{customDomain.hostname}</code>. For example:{' '}
<code className="text-xs">0 issue "digicert.com"</code>
</AlertDescription_Shadcn_>
</Alert_Shadcn_>
)}
{customDomain.ssl.status === 'validation_timed_out' ? (
<Alert withIcon variant="warning" title="Validation timed out">
Please click "Verify" again to retry the validation of the records
</Alert>
<Alert_Shadcn_>
<WarningIcon />
<AlertTitle_Shadcn_>Validation timed out</AlertTitle_Shadcn_>
<AlertDescription_Shadcn_>
Please click "Verify" again to retry the validation of the records
</AlertDescription_Shadcn_>
</Alert_Shadcn_>
) : (
<div className="space-y-2">
<div className="flex gap-4">
@@ -242,4 +247,4 @@ const CustomDomainVerify = ({ projectRef, customDomain, settings }: CustomDomain
)
}
export default observer(CustomDomainVerify)
export default CustomDomainVerify
@@ -1,10 +1,8 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { Button, Form, IconExternalLink, Input } from 'ui'
import * as yup from 'yup'
import { useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import {
FormActions,
@@ -17,6 +15,7 @@ import { useProjectApiQuery } from 'data/config/project-api-query'
import { useCheckCNAMERecordMutation } from 'data/custom-domains/check-cname-mutation'
import { useCustomDomainCreateMutation } from 'data/custom-domains/custom-domains-create-mutation'
import { useCheckPermissions } from 'hooks'
import { Button, Form, IconExternalLink, Input } from 'ui'
const schema = yup.object({
domain: yup.string().required('A value for your custom domain is required'),
@@ -131,4 +130,4 @@ const CustomDomainsConfigureHostname = () => {
)
}
export default observer(CustomDomainsConfigureHostname)
export default CustomDomainsConfigureHostname
@@ -1,7 +1,6 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { useState } from 'react'
import toast from 'react-hot-toast'
@@ -175,4 +174,4 @@ const RestartServerButton = () => {
)
}
export default observer(RestartServerButton)
export default RestartServerButton
@@ -2,7 +2,6 @@ import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import dayjs from 'dayjs'
import { sortBy } from 'lodash'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { Fragment, useEffect, useState } from 'react'
import toast from 'react-hot-toast'
@@ -383,4 +382,4 @@ const EncryptionKeysManagement = () => {
)
}
export default observer(EncryptionKeysManagement)
export default EncryptionKeysManagement
@@ -1,17 +1,16 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { sortBy } from 'lodash'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { Fragment, useEffect, useState } from 'react'
import { Button, IconExternalLink, IconLoader, IconSearch, IconX, Input, Listbox } from 'ui'
import { useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import Divider from 'components/ui/Divider'
import { useVaultSecretsQuery } from 'data/vault/vault-secrets-query'
import { useCheckPermissions } from 'hooks'
import type { VaultSecret } from 'types'
import { Button, IconExternalLink, IconLoader, IconSearch, IconX, Input, Listbox } from 'ui'
import AddNewSecretModal from './AddNewSecretModal'
import DeleteSecretModal from './DeleteSecretModal'
import EditSecretModal from './EditSecretModal'
@@ -217,4 +216,4 @@ const SecretsManagement = () => {
)
}
export default observer(SecretsManagement)
export default SecretsManagement
@@ -1,6 +1,5 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { observer } from 'mobx-react-lite'
import { useTheme } from 'next-themes'
import Link from 'next/link'
import { useState } from 'react'
@@ -161,4 +160,4 @@ const VaultToggle = () => {
)
}
export default observer(VaultToggle)
export default VaultToggle
@@ -6,10 +6,11 @@ import { toast } from 'react-hot-toast'
import { Modal } from 'ui'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { ToastLoader } from 'components/ui/ToastLoader'
import { useDatabasePublicationCreateMutation } from 'data/database-publications/database-publications-create-mutation'
import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query'
import { useDatabasePublicationUpdateMutation } from 'data/database-publications/database-publications-update-mutation'
import type { Constraint } from 'data/database/constraints-query'
import type { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query'
import { entityTypeKeys } from 'data/entity-types/keys'
import { sqlKeys } from 'data/sql/keys'
@@ -17,10 +18,11 @@ import { useTableRowCreateMutation } from 'data/table-rows/table-row-create-muta
import { useTableRowUpdateMutation } from 'data/table-rows/table-row-update-mutation'
import { tableKeys } from 'data/tables/keys'
import { getTables } from 'data/tables/tables-query'
import { useStore, useUrlState } from 'hooks'
import { useUrlState } from 'hooks'
import { useGetImpersonatedRole } from 'state/role-impersonation-state'
import { useTableEditorStateSnapshot } from 'state/table-editor'
import type { Dictionary } from 'types'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { ColumnEditor, RowEditor, SpreadsheetImport, TableEditor } from '.'
import type { ForeignKey } from './ForeignKeySelector/ForeignKeySelector.types'
import ForeignRowSelector from './RowEditor/ForeignRowSelector/ForeignRowSelector'
@@ -38,7 +40,6 @@ import {
updateTable,
} from './SidePanelEditor.utils'
import type { ImportContent } from './TableEditor/TableEditor.types'
import type { Constraint } from 'data/database/constraints-query'
export interface SidePanelEditorProps {
editable?: boolean
@@ -59,7 +60,6 @@ const SidePanelEditor = ({
const snap = useTableEditorStateSnapshot()
const [_, setParams] = useUrlState({ arrayKeys: ['filter', 'sort'] })
const { ui } = useStore()
const queryClient = useQueryClient()
const { project } = useProjectContext()
@@ -508,12 +508,13 @@ const SidePanelEditor = ({
selectedTable,
selectedHeaders,
(progress: number) => {
ui.setNotification({
id: toastId,
progress,
category: 'loading',
message: `Adding ${rowCount.toLocaleString()} rows to ${selectedTable.name}`,
})
toast.loading(
<ToastLoader
progress={progress}
message={`Adding ${rowCount.toLocaleString()} rows to ${selectedTable.name}`}
/>,
{ id: toastId }
)
}
)
if (res.error) {
@@ -529,14 +530,15 @@ const SidePanelEditor = ({
importContent.rows,
selectedHeaders,
(progress: number) => {
ui.setNotification({
id: toastId,
progress,
category: 'loading',
message: `Adding ${importContent.rows.length.toLocaleString()} rows to ${
selectedTable.name
}`,
})
toast.loading(
<ToastLoader
progress={progress}
message={`Adding ${importContent.rows.length.toLocaleString()} rows to ${
selectedTable.name
}`}
/>,
{ id: toastId }
)
}
)
if (res.error) {
@@ -1,10 +1,11 @@
import Editor from '@monaco-editor/react'
import { useTheme } from 'next-themes'
import { useParams } from 'common'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { useMemo, useRef } from 'react'
import { format } from 'sql-formatter'
import { useParams } from 'common'
import Footer from 'components/grid/components/footer/Footer'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useTableDefinitionQuery } from 'data/database/table-definition-query'
@@ -12,9 +13,7 @@ import { useViewDefinitionQuery } from 'data/database/view-definition-query'
import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants'
import useEntityType from 'hooks/misc/useEntityType'
import { timeout } from 'lib/helpers'
import Link from 'next/link'
import { Button } from 'ui'
import Footer from 'components/grid/components/footer/Footer'
export interface TableDefinitionProps {
id?: number
@@ -148,4 +147,4 @@ const TableDefinition = ({ id }: TableDefinitionProps) => {
)
}
export default observer(TableDefinition)
export default TableDefinition
@@ -1,12 +1,11 @@
import type { PostgresColumn, PostgresRelationship, PostgresTable } from '@supabase/postgres-meta'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { QueryKey, useQueryClient } from '@tanstack/react-query'
import { useParams } from 'common'
import { find, isUndefined } from 'lodash'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import toast from 'react-hot-toast'
import { useParams } from 'common'
import { parseSupaTable, SupabaseGrid, SupaTable } from 'components/grid'
import { ERROR_PRIMARY_KEY_NOTFOUND } from 'components/grid/constants'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
@@ -311,4 +310,4 @@ const TableGridEditor = ({
)
}
export default observer(TableGridEditor)
export default TableGridEditor
@@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { PropsWithChildren } from 'react'
@@ -46,4 +45,4 @@ const DatabaseLayout = ({ children }: PropsWithChildren<DatabaseLayoutProps>) =>
)
}
export default withAuth(observer(DatabaseLayout))
export default withAuth(DatabaseLayout)
@@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { ReactElement } from 'react'
@@ -67,4 +66,4 @@ function DocsLayout({ title, children }: { title: string; children: ReactElement
)
}
export default withAuth(observer(DocsLayout))
export default withAuth(DocsLayout)
@@ -1,16 +1,15 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import type { PropsWithChildren } from 'react'
import { Button, IconCode, IconExternalLink } from 'ui'
import { useParams } from 'common'
import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import APIDocsButton from 'components/ui/APIDocsButton'
import NoPermission from 'components/ui/NoPermission'
import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query'
import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query'
import { useCheckPermissions, withAuth } from 'hooks'
import { Button, IconCode, IconExternalLink } from 'ui'
import FunctionsNav from '../interfaces/Functions/FunctionsNav'
import { ProjectLayout } from './'
@@ -152,4 +151,4 @@ const FunctionsLayout = ({ title, children }: PropsWithChildren<FunctionsLayoutP
)
}
export default withAuth(observer(FunctionsLayout))
export default withAuth(FunctionsLayout)
@@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import { Fragment } from 'react'
interface BreadcrumbsViewProps {
@@ -44,4 +43,4 @@ const BreadcrumbsView = ({ defaultValue: breadcrumbs }: BreadcrumbsViewProps) =>
)
}
export default observer(BreadcrumbsView)
export default BreadcrumbsView
@@ -1,11 +1,10 @@
import { observer } from 'mobx-react-lite'
import Link from 'next/link'
import { PropsWithChildren } from 'react'
import { IconChevronRight } from 'ui'
import { withAuth } from 'hooks'
import { BASE_PATH } from 'lib/constants'
import type { Organization, Project } from 'types'
import { IconChevronRight } from 'ui'
import { FeedbackDropdown } from './ProjectLayout/LayoutHeader/FeedbackDropdown'
import HelpPopover from './ProjectLayout/LayoutHeader/HelpPopover'
@@ -31,9 +30,9 @@ const WizardLayout = ({
)
}
export default withAuth(observer(WizardLayout))
export default withAuth(WizardLayout)
export const WizardLayoutWithoutAuth = observer(WizardLayout)
export const WizardLayoutWithoutAuth = WizardLayout
const Header = ({ organization, project }: WizardLayoutProps) => {
let stepNumber = organization ? 1 : project ? 2 : 0
+27
View File
@@ -0,0 +1,27 @@
// [Joshen] Just FYI eventually we're going to move to use toasts
// from the UI library, but this is a transition to move everything to
// react-hot-toast while we're trying to deprecate mobx entirely
import SparkBar from './SparkBar'
interface ToastLoaderProps {
progress: number
message: string
description?: string
}
export const ToastLoader = ({ progress, message, description }: ToastLoaderProps) => {
return (
<div className="flex flex-col space-y-2" style={{ minWidth: '220px' }}>
<SparkBar
value={progress}
max={100}
type="horizontal"
barClass="bg-brand"
labelBottom={message}
labelTop={`${progress.toFixed(2)}%`}
/>
{description !== undefined && <p className="text-xs text-foreground-light">{description}</p>}
</div>
)
}
+1 -2
View File
@@ -2,10 +2,9 @@ export * from './deprecated'
export * from './misc/useCheckPermissions'
export * from './misc/useImmutableValue'
export * from './misc/useIsFeatureEnabled'
export * from './misc/useLatest'
export * from './misc/useLocalStorage'
export * from './misc/useSelectedOrganization'
export * from './misc/useSelectedProject'
export * from './misc/useStore'
export * from './misc/withAuth'
export * from './misc/useLatest'
export * from './ui'
-68
View File
@@ -1,68 +0,0 @@
import { autorun } from 'mobx'
import { createContext, PropsWithChildren, useContext, useEffect } from 'react'
import toast from 'react-hot-toast'
import SparkBar from 'components/ui/SparkBar'
import { IUiStore } from 'stores/UiStore'
const StoreContext = createContext<{ ui: IUiStore }>(undefined!)
/**
* @deprecated use the toast.success/loading/error functions, imported from 'react-hot-toast'
*/
export function useStore() {
const context = useContext(StoreContext)
if (context === undefined) {
throw new Error('useStore must be used within StoreProvider')
}
// returning in this way so that it's backwards compatible.
return context
}
interface StoreProvider {
rootStore: { ui: IUiStore }
}
export const StoreProvider = ({ children, rootStore }: PropsWithChildren<StoreProvider>) => {
const { ui } = rootStore
useEffect(() => {
autorun(() => {
if (ui.notification) {
const { id, category, error, message, description, progress, duration } = ui.notification
const toastDuration = duration || 4000
switch (category) {
case 'info':
return toast(message, { id, duration: toastDuration })
case 'success':
return toast.success(message, { id, duration: toastDuration })
case 'error':
console.error('Error:', { error, message })
return toast.error(message, { id, duration: duration || Infinity })
case 'loading':
if (progress !== undefined) {
return toast.loading(
<div className="flex flex-col space-y-2" style={{ minWidth: '220px' }}>
<SparkBar
value={progress}
max={100}
type="horizontal"
barClass="bg-brand"
labelBottom={message}
labelTop={`${progress.toFixed(2)}%`}
/>
{description !== undefined && (
<p className="text-xs text-foreground-light">{description}</p>
)}
</div>,
{ id }
)
} else {
return toast.loading(message, { id })
}
}
}
})
}, [])
return <StoreContext.Provider value={rootStore}>{children}</StoreContext.Provider>
}
@@ -1,5 +1,4 @@
// @ts-nocheck
import { createClient } from '@supabase/supabase-js'
import { BlobReader, BlobWriter, ZipWriter } from '@zip.js/zip.js'
import { chunk, compact, find, findIndex, has, isEqual, some, uniq, uniqBy } from 'lodash'
@@ -13,7 +12,7 @@ import {
STORAGE_SORT_BY,
STORAGE_VIEWS,
} from 'components/to-be-cleaned/Storage/Storage.constants'
import { useStore } from 'hooks'
import { ToastLoader } from 'components/ui/ToastLoader'
import { delete_, post } from 'lib/common/fetch'
import { API_URL, IS_PLATFORM } from 'lib/constants'
import { PROJECT_ENDPOINT_PROTOCOL } from 'pages/api/constants'
@@ -59,9 +58,6 @@ class StorageExplorerStore {
sortBy: { column: this.sortBy, order: this.sortByOrder },
}
/* UI store */
ui = null
/* Supabase client */
supabaseClient = null
/* [Joshen] Move towards using API */
@@ -79,8 +75,6 @@ class StorageExplorerStore {
constructor(projectRef) {
makeAutoObservable(this, { supabaseClient: false })
this.projectRef = projectRef
// eslint-disable-next-line react-hooks/rules-of-hooks
this.ui = useStore().ui
// ignore when in a non-browser environment
if (typeof window !== 'undefined') {
@@ -509,14 +503,15 @@ class StorageExplorerStore {
.map((folder) => folder.name)
.join('/')
const toastId = this.ui.setNotification({
category: 'loading',
message: `Uploading ${formattedFilesToUpload.length} file${
formattedFilesToUpload.length > 1 ? 's' : ''
}...`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: 0,
})
const toastId = toast.loading(
<ToastLoader
progress={0}
message={`Uploading ${formattedFilesToUpload.length} file${
formattedFilesToUpload.length > 1 ? 's' : ''
}...`}
description={STORAGE_PROGRESS_INFO_TEXT}
/>
)
// Upload files in batches
const promises = formattedFilesToUpload.map((file) => {
@@ -582,15 +577,16 @@ class StorageExplorerStore {
await batchedPromises.reduce(async (previousPromise, nextBatch) => {
await previousPromise
await Promise.allSettled(nextBatch.map((batch) => batch()))
this.ui.setNotification({
id: toastId,
category: 'loading',
message: `Uploading ${formattedFilesToUpload.length} file${
formattedFilesToUpload.length > 1 ? 's' : ''
}...`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: this.uploadProgress * 100,
})
toast.loading(
<ToastLoader
progress={this.uploadProgress * 100}
message={`Uploading ${formattedFilesToUpload.length} file${
formattedFilesToUpload.length > 1 ? 's' : ''
}...`}
description={STORAGE_PROGRESS_INFO_TEXT}
/>,
{ id: toastId }
)
}, Promise.resolve())
if (numberOfFilesUploadedSuccess > 0) {
@@ -738,12 +734,13 @@ class StorageExplorerStore {
this.clearSelectedItems()
const toastId = this.ui.setNotification({
category: 'loading',
message: `Deleting ${prefixes.length} file(s)...`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: 0,
})
const toastId = toast.loading(
<ToastLoader
progress={0}
message={`Deleting ${prefixes.length} file(s)...`}
description={STORAGE_PROGRESS_INFO_TEXT}
/>
)
// batch BATCH_SIZE prefixes per request
const batches = chunk(prefixes, BATCH_SIZE).map((batch) => () => {
@@ -757,13 +754,14 @@ class StorageExplorerStore {
await chunk(batches, BATCH_SIZE).reduce(async (previousPromise, nextBatch) => {
await previousPromise
await Promise.all(nextBatch.map((batch) => batch()))
this.ui.setNotification({
id: toastId,
category: 'loading',
message: `Deleting ${prefixes.length} file(s)...`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: progress * 100,
})
toast.loading(
<ToastLoader
progress={progress * 100}
message={`Deleting ${prefixes.length} file(s)...`}
description={STORAGE_PROGRESS_INFO_TEXT}
/>,
{ id: toastId }
)
}, Promise.resolve())
// Clear file preview cache if deleted files exist in cache
@@ -798,13 +796,14 @@ class StorageExplorerStore {
const files = await this.getAllItemsAlongFolder(folder)
this.ui.setNotification({
id: toastId,
category: 'loading',
message: `Downloading ${files.length} files...`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: 0,
})
toast.loading(
<ToastLoader
progress={0}
message={`Downloading ${files.length} file${files.length > 1 ? 's' : ''}...`}
desription={STORAGE_PROGRESS_INFO_TEXT}
/>,
{ id: toastId }
)
const promises = files.map((file) => {
const fileMimeType = file.metadata?.mimetype ?? null
@@ -835,13 +834,14 @@ class StorageExplorerStore {
const downloadedFiles = await batchedPromises.reduce(async (previousPromise, nextBatch) => {
const previousResults = await previousPromise
const batchResults = await Promise.allSettled(nextBatch.map((batch) => batch()))
this.ui.setNotification({
id: toastId,
category: 'loading',
message: `Downloading ${files.length} file${files.length > 1 ? 's' : ''}...`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: progress * 100,
})
toast.loading(
<ToastLoader
progress={progress * 100}
message={`Downloading ${files.length} file${files.length > 1 ? 's' : ''}...`}
desription={STORAGE_PROGRESS_INFO_TEXT}
/>,
{ id: toastId }
)
return (previousResults ?? []).concat(batchResults.map((x) => x.value).filter(Boolean))
}, Promise.resolve())
@@ -890,7 +890,9 @@ class StorageExplorerStore {
let progress = 0
const returnBlob = true
const showIndividualToast = false
const toastId = toast.loading(`Downloading ${files.length} files...`)
const toastId = toast.loading(
`Downloading ${files.length} file${files.length > 1 ? 's' : ''}...`
)
const promises = formattedFilesWithPrefix.map((file) => {
return () => {
@@ -906,13 +908,14 @@ class StorageExplorerStore {
const downloadedFiles = await batchedPromises.reduce(async (previousPromise, nextBatch) => {
const previousResults = await previousPromise
const batchResults = await Promise.allSettled(nextBatch.map((batch) => batch()))
this.ui.setNotification({
id: toastId,
category: 'loading',
message: `Downloading ${files.length} file${files.length > 1 ? 's' : ''}...`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: progress * 100,
})
toast.loading(
<ToastLoader
progress={progress * 100}
message={`Downloading ${files.length} file${files.length > 1 ? 's' : ''}...`}
description={STORAGE_PROGRESS_INFO_TEXT}
/>,
{ id: toastId }
)
return (previousResults ?? []).concat(batchResults.map((x) => x.value).filter(Boolean))
}, Promise.resolve())
@@ -1208,12 +1211,13 @@ class StorageExplorerStore {
return this.updateRowStatus(originalName, STORAGE_ROW_STATUS.READY, columnIndex)
}
const toastId = this.ui.setNotification({
category: 'loading',
message: `Renaming folder to ${newName}`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: 0,
})
const toastId = toast.loading(
<ToastLoader
progress={0}
message={`Renaming folder to ${newName}`}
description={STORAGE_PROGRESS_INFO_TEXT}
/>
)
/**
* Catch any folder names that contain slash or backslash
@@ -1268,13 +1272,14 @@ class StorageExplorerStore {
await batchedPromises.reduce(async (previousPromise, nextBatch) => {
await previousPromise
await Promise.all(nextBatch.map((batch) => batch()))
this.ui.setNotification({
id: toastId,
category: 'loading',
message: `Renaming folder to ${newName}`,
description: STORAGE_PROGRESS_INFO_TEXT,
progress: progress * 100,
})
toast.loader(
<ToastLoader
progress={progress * 100}
message={`Renaming folder to ${newName}`}
description={STORAGE_PROGRESS_INFO_TEXT}
/>,
{ id: toastId }
)
}, Promise.resolve())
if (!hasErrors) {
+2 -7
View File
@@ -9,9 +9,7 @@
```tsx
import { NextPage } from 'next'
import { observer } from 'mobx-react-lite'
import { useStore, withAuth } from 'hooks'
import { withAuth } from 'hooks'
// Import the corresponding layout based on the page
import { Layout } from 'components/layouts'
@@ -25,9 +23,6 @@ import { ... } from 'components/ui/xxx'
// Name your page accordingly
const Page: NextPage = () => {
// Access the store via the useStore hook
const { meta } = useStore()
return (
<Layout>
<div>Page content</div>
@@ -35,5 +30,5 @@ const Page: NextPage = () => {
)
}
export default withAuth(observer(Page))
export default withAuth(Page)
```
+33 -39
View File
@@ -46,12 +46,10 @@ import FeaturePreviewModal from 'components/interfaces/App/FeaturePreview/Featur
import FlagProvider from 'components/ui/Flag/FlagProvider'
import PageTelemetry from 'components/ui/PageTelemetry'
import { useRootQueryClient } from 'data/query-client'
import { StoreProvider } from 'hooks'
import { AuthProvider } from 'lib/auth'
import { BASE_PATH, IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
import { ProfileProvider } from 'lib/profile'
import { useAppStateSnapshot } from 'state/app-state'
import UiStore from 'stores/UiStore'
import HCaptchaLoadedStore from 'stores/hcaptcha-loaded-store'
import { AppPropsWithLayout } from 'types'
@@ -81,9 +79,7 @@ loader.config({
function CustomApp({ Component, pageProps }: AppPropsWithLayout) {
const snap = useAppStateSnapshot()
const queryClient = useRootQueryClient()
const consentToastId = useRef<string>()
const [rootStore] = useState(() => ({ ui: new UiStore() }))
// [Joshen] Some issues with using createBrowserSupabaseClient
const [supabase] = useState(() =>
@@ -146,43 +142,41 @@ function CustomApp({ Component, pageProps }: AppPropsWithLayout) {
return (
<QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}>
<StoreProvider rootStore={rootStore}>
<AuthContainer>
<ProfileProvider>
<FlagProvider>
<Head>
<title>Supabase</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</Head>
<Favicons />
<AuthContainer>
<ProfileProvider>
<FlagProvider>
<Head>
<title>Supabase</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</Head>
<Favicons />
<PageTelemetry>
<TooltipProvider>
<RouteValidationWrapper>
<ThemeProvider defaultTheme="system" enableSystem disableTransitionOnChange>
<AppBannerContextProvider>
<CommandMenuWrapper>
<AppBannerWrapper>
<FeaturePreviewContextProvider>
{getLayout(<Component {...pageProps} />)}
<FeaturePreviewModal />
</FeaturePreviewContextProvider>
</AppBannerWrapper>
</CommandMenuWrapper>
</AppBannerContextProvider>
</ThemeProvider>
</RouteValidationWrapper>
</TooltipProvider>
</PageTelemetry>
<PageTelemetry>
<TooltipProvider>
<RouteValidationWrapper>
<ThemeProvider defaultTheme="system" enableSystem disableTransitionOnChange>
<AppBannerContextProvider>
<CommandMenuWrapper>
<AppBannerWrapper>
<FeaturePreviewContextProvider>
{getLayout(<Component {...pageProps} />)}
<FeaturePreviewModal />
</FeaturePreviewContextProvider>
</AppBannerWrapper>
</CommandMenuWrapper>
</AppBannerContextProvider>
</ThemeProvider>
</RouteValidationWrapper>
</TooltipProvider>
</PageTelemetry>
<HCaptchaLoadedStore />
<Toaster />
<PortalToast />
{!isTestEnv && <ReactQueryDevtools initialIsOpen={false} position="bottom-right" />}
</FlagProvider>
</ProfileProvider>
</AuthContainer>
</StoreProvider>
<HCaptchaLoadedStore />
<Toaster />
<PortalToast />
{!isTestEnv && <ReactQueryDevtools initialIsOpen={false} position="bottom-right" />}
</FlagProvider>
</ProfileProvider>
</AuthContainer>
</Hydrate>
</QueryClientProvider>
)
@@ -3,15 +3,14 @@ import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { useParams } from 'common/hooks'
import { CreateReportModal } from 'components/interfaces/Reports/Reports.CreateReportModal'
import { ReportsLayout } from 'components/layouts'
import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState'
import { createReport } from 'components/to-be-cleaned/Reports/Reports.utils'
import { Loading } from 'components/ui/Loading'
import { useCheckPermissions, useStore } from 'hooks'
import { useCheckPermissions } from 'hooks'
import { useProfile } from 'lib/profile'
import { useProjectContentStore } from 'stores/projectContentStore'
import type { NextPageWithLayout } from 'types'
import { CreateReportModal } from 'components/interfaces/Reports/Reports.CreateReportModal'
export const UserReportPage: NextPageWithLayout = () => {
const [loading, setLoading] = useState(true)
@@ -20,7 +19,6 @@ export const UserReportPage: NextPageWithLayout = () => {
const { ref } = useParams()
const { profile } = useProfile()
const { ui } = useStore()
const [showCreateReportModal, setShowCreateReportModal] = useState(false)
const contentStore = useProjectContentStore(ref)
+1 -2
View File
@@ -1,6 +1,5 @@
import { useMonaco } from '@monaco-editor/react'
import { useParams } from 'common'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { useEffect, useRef } from 'react'
@@ -158,4 +157,4 @@ const SqlEditor: NextPageWithLayout = () => {
SqlEditor.getLayout = (page) => <SQLEditorLayout title="SQL">{page}</SQLEditorLayout>
export default observer(SqlEditor)
export default SqlEditor
@@ -1,6 +1,5 @@
import { useParams } from 'common'
import { find } from 'lodash'
import { observer } from 'mobx-react-lite'
import { StorageLayout } from 'components/layouts'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
@@ -40,4 +39,4 @@ const PageLayout: NextPageWithLayout = () => {
PageLayout.getLayout = (page) => <StorageLayout title="Buckets">{page}</StorageLayout>
export default observer(PageLayout)
export default PageLayout
@@ -1,5 +1,3 @@
import { observer } from 'mobx-react-lite'
import { StorageLayout } from 'components/layouts'
import type { NextPageWithLayout } from 'types'
@@ -9,4 +7,4 @@ const Storage: NextPageWithLayout = () => {
Storage.getLayout = (page) => <StorageLayout title="Storage">{page}</StorageLayout>
export default observer(Storage)
export default Storage
-23
View File
@@ -1,23 +0,0 @@
# Store
## Store structure
At the root, there are currently 3 top-level stores in use: `app`, `meta` and `ui` (`content` is WIP at the moment). Each of them store the following information:
- `app`: Application level data (Projects and organizations)
- `meta`: Database information (e.g Tables, Columns, Policies)
- `ui`: UI states that are common globally
- `content`: User-specific content (e.g Saved SQL snippets)
## Accessing the store
The `useStore` hook is the entry point to access the store in your pages and components.
```
import { useStore } from 'hooks'
const { app, meta, ui } = useStore()
```
## What is the jsonSchema folder
The files here are used to populate form fields on the dashboard with the `ajv` library. We have in mind to move away from this way of rendering form fields due to its rigid nature but we've yet to decide.
-22
View File
@@ -1,22 +0,0 @@
import { makeAutoObservable } from 'mobx'
import { uuidv4 } from 'lib/helpers'
import type { Notification } from 'types'
export interface IUiStore {
notification?: Notification
setNotification: (notification: Notification) => string
}
export default class UiStore implements IUiStore {
notification?: Notification
constructor() {
makeAutoObservable(this)
}
setNotification(notification: Notification): string {
const id = notification?.id ?? uuidv4()
this.notification = { ...notification, id }
return id
}
}
@@ -1,2 +0,0 @@
export { PROVIDERS_SCHEMAS, PROVIDER_SAML } from './AuthProviders/AuthProvidersFormValidation'
export { TEMPLATES_SCHEMAS } from './AuthProviders/AuthTemplatesValidation'
+5 -12
View File
@@ -1,11 +1,8 @@
import { fireEvent, getByText, screen } from '@testing-library/react'
import { fireEvent, getByText, screen, render as originalRender } from '@testing-library/react'
import React, { useState } from 'react'
import { TooltipProvider } from '@radix-ui/react-tooltip'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render as originalRender } from '@testing-library/react'
import { StoreProvider } from 'hooks'
import UiStore from 'stores/UiStore'
interface SelectorOptions {
container?: HTMLElement
}
@@ -48,8 +45,6 @@ export const clickDropdown = (elem: HTMLElement) => {
* https://testing-library.com/docs/react-testing-library/setup/#custom-render
*/
const ReactQueryTestConfig: React.FC<React.PropsWithChildren> = ({ children }) => {
const [rootStore] = useState(() => ({ ui: new UiStore() }))
const [queryClient] = useState(
() =>
new QueryClient({
@@ -68,11 +63,9 @@ const ReactQueryTestConfig: React.FC<React.PropsWithChildren> = ({ children }) =
)
return (
<StoreProvider rootStore={rootStore}>
<TooltipProvider>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</TooltipProvider>
</StoreProvider>
<TooltipProvider>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</TooltipProvider>
)
}
type renderParams = Parameters<typeof originalRender>