mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
more layout updates
This commit is contained in:
1 parent
48b98e52cd
commit
ec5dfdceca
7 files changed
+133
-111
No files matched your search
@@ -210,7 +210,7 @@ const ProjectLinker = ({
|
||||
</div>
|
||||
<Markdown
|
||||
content={`
|
||||
The following enviroment variables will be added:
|
||||
The following environment variables will be added:
|
||||
|
||||
${ENV_VAR_RAW_KEYS.map((x, idx) => {
|
||||
return `
|
||||
|
||||
@@ -109,19 +109,6 @@ Repository connections for ${title?.toLowerCase()}
|
||||
size="large"
|
||||
overlay={
|
||||
<>
|
||||
<Dropdown.Item
|
||||
icon={
|
||||
<div>
|
||||
<IconRefreshCcw size={14} />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div>Refresh Enviroment Variables</div>
|
||||
<div className="text-scale-900 text-xs">
|
||||
Reapply env vars in vercel.
|
||||
</div>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Separator />
|
||||
<Dropdown.Item
|
||||
icon={<IconTrash size={14} />}
|
||||
onSelect={() =>
|
||||
|
||||
@@ -13,6 +13,7 @@ import PublishAppModal from './PublishAppSidePanel'
|
||||
import { AuthorizedApp, useAuthorizedAppsQuery } from 'data/oauth/authorized-apps-query'
|
||||
import AuthorizedAppRow from './AuthorizedAppRow'
|
||||
import RevokeAppModal from './RevokeAppModal'
|
||||
import { ScaffoldContainerLegacy } from 'components/layouts/Scaffold'
|
||||
|
||||
// [Joshen] Note on nav UX
|
||||
// Kang Ming mentioned that it might be better to split Published Apps and Authorized Apps into 2 separate tabs
|
||||
@@ -51,7 +52,7 @@ const OAuthApps = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="container my-4 max-w-5xl space-y-8">
|
||||
<ScaffoldContainerLegacy>
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
@@ -65,95 +66,93 @@ const OAuthApps = () => {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mt-4">
|
||||
{isLoadingPublishedApps && (
|
||||
<div className="space-y-2">
|
||||
<ShimmeringLoader />
|
||||
<ShimmeringLoader className="w-3/4" />
|
||||
<ShimmeringLoader className="w-1/2" />
|
||||
{isLoadingPublishedApps && (
|
||||
<div className="space-y-2">
|
||||
<ShimmeringLoader />
|
||||
<ShimmeringLoader className="w-3/4" />
|
||||
<ShimmeringLoader className="w-1/2" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isErrorPublishedApps && (
|
||||
<AlertError className="mt-4" subject="Unable to retrieve published OAuth apps" />
|
||||
)}
|
||||
|
||||
{createdApp !== undefined && (
|
||||
<Alert withIcon variant="success" title="Successfully published a new application!">
|
||||
<div className="absolute top-4 right-4">
|
||||
<Button
|
||||
type="text"
|
||||
icon={<IconX size={18} />}
|
||||
className="px-1"
|
||||
onClick={() => setCreatedApp(undefined)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isErrorPublishedApps && (
|
||||
<AlertError subject="Unable to retrieve published OAuth apps" />
|
||||
)}
|
||||
|
||||
{createdApp !== undefined && (
|
||||
<Alert withIcon variant="success" title="Successfully published a new application!">
|
||||
<div className="absolute top-4 right-4">
|
||||
<Button
|
||||
type="text"
|
||||
icon={<IconX size={18} />}
|
||||
className="px-1"
|
||||
onClick={() => setCreatedApp(undefined)}
|
||||
<div className="w-full space-y-4">
|
||||
<p className="text-sm">
|
||||
Ensure that you store the client secret securely - you will not be able to see it
|
||||
again.
|
||||
</p>
|
||||
<div className="space-y-4">
|
||||
<Input
|
||||
copy
|
||||
readOnly
|
||||
size="small"
|
||||
// layout="horizontal"
|
||||
label="Client ID"
|
||||
className="max-w-xl input-mono"
|
||||
value={createdApp.client_id}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<Input
|
||||
copy
|
||||
readOnly
|
||||
size="small"
|
||||
// layout="horizontal"
|
||||
label="Client secret"
|
||||
className="max-w-xl input-mono"
|
||||
value={createdApp.client_secret}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full space-y-4">
|
||||
<p className="text-sm">
|
||||
Ensure that you store the client secret securely - you will not be able to see
|
||||
it again.
|
||||
</p>
|
||||
<div className="space-y-4">
|
||||
<Input
|
||||
copy
|
||||
readOnly
|
||||
size="small"
|
||||
// layout="horizontal"
|
||||
label="Client ID"
|
||||
className="max-w-xl input-mono"
|
||||
value={createdApp.client_id}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<Input
|
||||
copy
|
||||
readOnly
|
||||
size="small"
|
||||
// layout="horizontal"
|
||||
label="Client secret"
|
||||
className="max-w-xl input-mono"
|
||||
value={createdApp.client_secret}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Alert>
|
||||
)}
|
||||
</div>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{isSuccessPublishedApps && (
|
||||
<>
|
||||
{(publishedApps?.length ?? 0) === 0 ? (
|
||||
<div className="bg-scale-100 dark:bg-scale-300 border rounded p-4 flex items-center justify-between">
|
||||
<p className="prose text-sm">You do not have any published applications yet</p>
|
||||
</div>
|
||||
) : (
|
||||
<Table
|
||||
className="mt-4"
|
||||
head={[
|
||||
<Table.th key="icon" className="w-[30px]"></Table.th>,
|
||||
<Table.th key="name">Name</Table.th>,
|
||||
<Table.th key="client-id">Client ID</Table.th>,
|
||||
<Table.th key="client-secret">Client Secret</Table.th>,
|
||||
<Table.th key="client-secret">Created at</Table.th>,
|
||||
<Table.th key="delete-action"></Table.th>,
|
||||
]}
|
||||
body={
|
||||
sortedPublishedApps?.map((app) => (
|
||||
<OAuthAppRow
|
||||
key={app.id}
|
||||
app={app}
|
||||
onSelectEdit={() => {
|
||||
setShowPublishModal(true)
|
||||
setSelectedAppToUpdate(app)
|
||||
}}
|
||||
onSelectDelete={() => setSelectedAppToDelete(app)}
|
||||
/>
|
||||
)) ?? []
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{isSuccessPublishedApps && (
|
||||
<>
|
||||
{(publishedApps?.length ?? 0) === 0 ? (
|
||||
<div className="bg-scale-100 dark:bg-scale-300 border rounded p-4 flex items-center justify-between mt-4">
|
||||
<p className="prose text-sm">You do not have any published applications yet</p>
|
||||
</div>
|
||||
) : (
|
||||
<Table
|
||||
className="mt-4"
|
||||
head={[
|
||||
<Table.th key="icon" className="w-[30px]"></Table.th>,
|
||||
<Table.th key="name">Name</Table.th>,
|
||||
<Table.th key="client-id">Client ID</Table.th>,
|
||||
<Table.th key="client-secret">Client Secret</Table.th>,
|
||||
<Table.th key="client-secret">Created at</Table.th>,
|
||||
<Table.th key="delete-action"></Table.th>,
|
||||
]}
|
||||
body={
|
||||
sortedPublishedApps?.map((app) => (
|
||||
<OAuthAppRow
|
||||
key={app.id}
|
||||
app={app}
|
||||
onSelectEdit={() => {
|
||||
setShowPublishModal(true)
|
||||
setSelectedAppToUpdate(app)
|
||||
}}
|
||||
onSelectDelete={() => setSelectedAppToDelete(app)}
|
||||
/>
|
||||
)) ?? []
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -204,7 +203,7 @@ const OAuthApps = () => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ScaffoldContainerLegacy>
|
||||
|
||||
<PublishAppModal
|
||||
visible={showPublishModal}
|
||||
|
||||
@@ -111,7 +111,7 @@ const MembersView = ({ searchString }: MembersViewProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="rounded">
|
||||
<div className="rounded w-full">
|
||||
<Loading active={!filteredMembers}>
|
||||
<Table
|
||||
head={[
|
||||
|
||||
@@ -14,7 +14,12 @@ import { useProfile } from 'lib/profile'
|
||||
import InviteMemberButton from './InviteMemberButton'
|
||||
import MembersView from './MembersView'
|
||||
import { hasMultipleOwners, useGetRolesManagementPermissions } from './TeamSettings.utils'
|
||||
import { ScaffoldContainerLegacy } from 'components/layouts/Scaffold'
|
||||
import {
|
||||
ScaffoldActionsGroup,
|
||||
ScaffoldContainerLegacy,
|
||||
ScaffoldFilterAndContent,
|
||||
ScaffoldActionsContainer,
|
||||
} from 'components/layouts/Scaffold'
|
||||
|
||||
const TeamSettings = () => {
|
||||
const { ui } = useStore()
|
||||
@@ -72,8 +77,8 @@ const TeamSettings = () => {
|
||||
|
||||
return (
|
||||
<ScaffoldContainerLegacy>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex justify-between">
|
||||
<ScaffoldFilterAndContent>
|
||||
<ScaffoldActionsContainer className="justify-between">
|
||||
<Input
|
||||
icon={<IconSearch size="tiny" />}
|
||||
size="small"
|
||||
@@ -83,7 +88,7 @@ const TeamSettings = () => {
|
||||
id="email"
|
||||
placeholder="Filter members"
|
||||
/>
|
||||
<div className="flex items-center space-x-4">
|
||||
<ScaffoldActionsGroup>
|
||||
{canAddMembers && profile !== undefined && (
|
||||
<div>
|
||||
<InviteMemberButton
|
||||
@@ -125,10 +130,10 @@ const TeamSettings = () => {
|
||||
)}
|
||||
</Tooltip.Root>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ScaffoldActionsGroup>
|
||||
</ScaffoldActionsContainer>
|
||||
<MembersView searchString={searchString} />
|
||||
</div>
|
||||
</ScaffoldFilterAndContent>
|
||||
</ScaffoldContainerLegacy>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -65,6 +65,29 @@ const ScaffoldSectionContent = React.forwardRef<
|
||||
)
|
||||
})
|
||||
|
||||
// Table and filters
|
||||
const ScaffoldFilterAndContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
return <div ref={ref} {...props} className={cn('flex flex-col gap-3 items-center', className)} />
|
||||
})
|
||||
|
||||
// Actions Group
|
||||
const ScaffoldActionsContainer = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
return <div ref={ref} {...props} className={cn('flex w-full items-center', className)} />
|
||||
})
|
||||
|
||||
// Actions Group
|
||||
const ScaffoldActionsGroup = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
||||
({ className, ...props }, ref) => {
|
||||
return <div ref={ref} {...props} className={cn('flex flex-row gap-3', className)} />
|
||||
}
|
||||
)
|
||||
|
||||
// For older layouts
|
||||
const ScaffoldContainerLegacy = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
@@ -74,7 +97,7 @@ const ScaffoldContainerLegacy = React.forwardRef<
|
||||
<div
|
||||
ref={ref}
|
||||
{...props}
|
||||
className={cn(maxWidthClasses, paddingClasses, 'my-8 flex flex-col gap-4', className)}
|
||||
className={cn(maxWidthClasses, paddingClasses, 'my-8 flex flex-col gap-8', className)}
|
||||
/>
|
||||
)
|
||||
})
|
||||
@@ -86,6 +109,9 @@ ScaffoldDivider.displayName = 'ScaffoldDivider'
|
||||
ScaffoldSection.displayName = 'ScaffoldSection'
|
||||
ScaffoldSectionDetail.displayName = 'ScaffoldSectionDetail'
|
||||
ScaffoldSectionContent.displayName = 'ScaffoldSectionContent'
|
||||
ScaffoldFilterAndContent.displayName = 'ScaffoldFilterAndContent'
|
||||
ScaffoldActionsContainer.displayName = 'ScaffoldActionsContainer'
|
||||
ScaffoldActionsGroup.displayName = 'ScaffoldActionsGroup'
|
||||
ScaffoldContainerLegacy.displayName = 'ScaffoldContainerLegacy'
|
||||
|
||||
export {
|
||||
@@ -96,5 +122,8 @@ export {
|
||||
ScaffoldSection,
|
||||
ScaffoldSectionDetail,
|
||||
ScaffoldSectionContent,
|
||||
ScaffoldFilterAndContent,
|
||||
ScaffoldActionsContainer,
|
||||
ScaffoldActionsGroup,
|
||||
ScaffoldContainerLegacy,
|
||||
}
|
||||
@@ -6,11 +6,12 @@ export interface AlertErrorProps {
|
||||
ref?: string
|
||||
subject?: string
|
||||
error?: ResponseError | null
|
||||
className?: string
|
||||
}
|
||||
|
||||
// [Joshen] To standardize the language for all error UIs
|
||||
|
||||
const AlertError = ({ ref, subject, error }: AlertErrorProps) => {
|
||||
const AlertError = ({ ref, subject, error, className }: AlertErrorProps) => {
|
||||
const subjectString = subject?.replace(/ /g, '%20')
|
||||
let href = `/support/new?category=dashboard_bug`
|
||||
|
||||
@@ -21,6 +22,7 @@ const AlertError = ({ ref, subject, error }: AlertErrorProps) => {
|
||||
return (
|
||||
<Alert
|
||||
withIcon
|
||||
className={className}
|
||||
variant="warning"
|
||||
title={subject}
|
||||
actions={[
|
||||
|
||||
Reference in new issue
Block a user