mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
midway
This commit is contained in:
1 parent
f6653cf093
commit
aafcb96910
4 files changed
+183
-126
No files matched your search
@@ -2,7 +2,7 @@ import { useParams } from 'common'
|
||||
import { useOAuthAppDeleteMutation } from 'data/oauth/oauth-app-delete-mutation'
|
||||
import { OAuthApp } from 'data/oauth/oauth-apps-query'
|
||||
import { useStore } from 'hooks'
|
||||
import { Alert, Modal } from 'ui'
|
||||
import { Alert, IconAlertOctagon, IconLock, IconShieldOff, Modal } from 'ui'
|
||||
|
||||
export interface DeleteAppModalProps {
|
||||
selectedApp?: OAuthApp
|
||||
@@ -46,9 +46,34 @@ const DeleteAppModal = ({ selectedApp, onClose }: DeleteAppModalProps) => {
|
||||
<Modal.Content>
|
||||
<div className="py-4">
|
||||
<Alert withIcon variant="warning" title="This action cannot be undone">
|
||||
Any applications which have been authorized through this app will no longer have access
|
||||
to your organization's settings and projects.
|
||||
You will no longer have access to any applications that were authorized through this app
|
||||
</Alert>
|
||||
<ul className="mt-4 space-y-5">
|
||||
<li className="flex gap-3 text-sm">
|
||||
<div>
|
||||
<IconAlertOctagon />
|
||||
</div>
|
||||
<span>
|
||||
You will no longer have access to any applications that were authorized through this
|
||||
app
|
||||
</span>
|
||||
</li>
|
||||
|
||||
<li className="flex gap-3 text-sm">
|
||||
<IconLock w={14} className="flex-shrink-0" />
|
||||
<div>
|
||||
<strong>Before you remove this app, consider:</strong>
|
||||
<ul className="space-y-2 mt-2">
|
||||
<li className="list-disc ml-4">
|
||||
Any authorized apps that were granted access to your organization
|
||||
</li>
|
||||
<li className="list-disc ml-4">
|
||||
Anyone will be able to modify, add or delete any row in this table.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</Modal>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { OAuthApp, useOAuthAppsQuery } from 'data/oauth/oauth-apps-query'
|
||||
import { Alert, Button, IconX, Input } from 'ui'
|
||||
import DeleteAppModal from './DeleteAppModal'
|
||||
import OAuthAppRow from './OAuthAppRow'
|
||||
import PublishAppModal from './PublishAppModal'
|
||||
import PublishAppModal from './PublishAppSidePanel'
|
||||
import { AuthorizedApp, useAuthorizedAppsQuery } from 'data/oauth/authorized-apps-query'
|
||||
import AuthorizedAppRow from './AuthorizedAppRow'
|
||||
import RevokeAppModal from './RevokeAppModal'
|
||||
|
||||
+127
-121
@@ -10,7 +10,7 @@ import { useOAuthAppUpdateMutation } from 'data/oauth/oauth-app-update-mutation'
|
||||
import { OAuthApp } from 'data/oauth/oauth-apps-query'
|
||||
import { useStore } from 'hooks'
|
||||
import { isValidHttpUrl, uuidv4 } from 'lib/helpers'
|
||||
import { Badge, Button, Dropdown, Form, IconEdit, IconUpload, Input, Modal } from 'ui'
|
||||
import { Badge, Button, Dropdown, Form, IconEdit, IconUpload, Input, Modal, SidePanel } from 'ui'
|
||||
import { uploadAttachment } from 'lib/upload'
|
||||
import AuthorizeRequesterDetails from './AuthorizeRequesterDetails'
|
||||
|
||||
@@ -157,8 +157,9 @@ const PublishAppModal = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
<SidePanel
|
||||
hideFooter
|
||||
size="large"
|
||||
visible={visible}
|
||||
header={
|
||||
selectedApp !== undefined ? 'Update OAuth application' : 'Publish a new OAuth application'
|
||||
@@ -167,6 +168,7 @@ const PublishAppModal = ({
|
||||
>
|
||||
<Form
|
||||
validateOnBlur
|
||||
className="h-full"
|
||||
initialValues={{ name: '', website: '' }}
|
||||
validate={validate}
|
||||
onSubmit={onSubmit}
|
||||
@@ -193,130 +195,134 @@ const PublishAppModal = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<Modal.Content>
|
||||
<div className="py-4 flex items-start justify-between gap-10">
|
||||
<div className="space-y-4 w-full">
|
||||
<Input
|
||||
id="name"
|
||||
label="Application name"
|
||||
descriptionText={selectedApp?.id && `ID: ${selectedApp.id}`}
|
||||
/>
|
||||
<Input
|
||||
id="website"
|
||||
label="Website URL"
|
||||
placeholder="https://my-website.com"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
{iconUrl !== undefined ? (
|
||||
<div
|
||||
className={clsx(
|
||||
'shadow transition group relative',
|
||||
'bg-center bg-cover bg-no-repeat',
|
||||
'mt-4 mr-4 space-y-2 rounded-full h-[120px] w-[120px] flex flex-col items-center justify-center'
|
||||
)}
|
||||
style={{
|
||||
backgroundImage: iconUrl ? `url("${iconUrl}")` : 'none',
|
||||
}}
|
||||
>
|
||||
<div className="absolute bottom-1 right-1">
|
||||
<Dropdown
|
||||
size="tiny"
|
||||
align="end"
|
||||
side="bottom"
|
||||
overlay={[
|
||||
<Dropdown.Item
|
||||
key="upload"
|
||||
onClick={() => {
|
||||
if (uploadButtonRef.current)
|
||||
(uploadButtonRef.current as any).click()
|
||||
}}
|
||||
>
|
||||
Upload image
|
||||
</Dropdown.Item>,
|
||||
<Dropdown.Item
|
||||
key="remove"
|
||||
onClick={() => {
|
||||
setIconFile(undefined)
|
||||
setIconUrl(undefined)
|
||||
}}
|
||||
>
|
||||
Remove image
|
||||
</Dropdown.Item>,
|
||||
]}
|
||||
>
|
||||
<Button type="default" icon={<IconEdit />} className="px-1" />
|
||||
</Dropdown>
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="flex-grow">
|
||||
<SidePanel.Content>
|
||||
<div className="py-4 flex items-start justify-between gap-10">
|
||||
<div className="space-y-4 w-full">
|
||||
<Input
|
||||
id="name"
|
||||
label="Application name"
|
||||
descriptionText={selectedApp?.id && `ID: ${selectedApp.id}`}
|
||||
/>
|
||||
<Input
|
||||
id="website"
|
||||
label="Website URL"
|
||||
placeholder="https://my-website.com"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
{iconUrl !== undefined ? (
|
||||
<div
|
||||
className={clsx(
|
||||
'shadow transition group relative',
|
||||
'bg-center bg-cover bg-no-repeat',
|
||||
'mt-4 mr-4 space-y-2 rounded-full h-[120px] w-[120px] flex flex-col items-center justify-center'
|
||||
)}
|
||||
style={{
|
||||
backgroundImage: iconUrl ? `url("${iconUrl}")` : 'none',
|
||||
}}
|
||||
>
|
||||
<div className="absolute bottom-1 right-1">
|
||||
<Dropdown
|
||||
size="tiny"
|
||||
align="end"
|
||||
side="bottom"
|
||||
overlay={[
|
||||
<Dropdown.Item
|
||||
key="upload"
|
||||
onClick={() => {
|
||||
if (uploadButtonRef.current)
|
||||
(uploadButtonRef.current as any).click()
|
||||
}}
|
||||
>
|
||||
Upload image
|
||||
</Dropdown.Item>,
|
||||
<Dropdown.Item
|
||||
key="remove"
|
||||
onClick={() => {
|
||||
setIconFile(undefined)
|
||||
setIconUrl(undefined)
|
||||
}}
|
||||
>
|
||||
Remove image
|
||||
</Dropdown.Item>,
|
||||
]}
|
||||
>
|
||||
<Button type="default" icon={<IconEdit />} className="px-1" />
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={clsx(
|
||||
'border border-scale-700 transition opacity-75 hover:opacity-100',
|
||||
'mt-4 mr-4 space-y-2 rounded-full h-[120px] w-[120px] flex flex-col items-center justify-center cursor-pointer'
|
||||
)}
|
||||
onClick={() => {
|
||||
if (uploadButtonRef.current) (uploadButtonRef.current as any).click()
|
||||
}}
|
||||
>
|
||||
<IconUpload size={18} strokeWidth={1.5} className="text-scale-1200" />
|
||||
<p className="text-xs text-scale-1100">Upload logo</p>
|
||||
</div>
|
||||
)}
|
||||
<input
|
||||
multiple
|
||||
type="file"
|
||||
ref={uploadButtonRef}
|
||||
className="hidden"
|
||||
accept="image/png, image/jpeg"
|
||||
onChange={onFileUpload}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={clsx(
|
||||
'border border-scale-700 transition opacity-75 hover:opacity-100',
|
||||
'mt-4 mr-4 space-y-2 rounded-full h-[120px] w-[120px] flex flex-col items-center justify-center cursor-pointer'
|
||||
)}
|
||||
onClick={() => {
|
||||
if (uploadButtonRef.current)
|
||||
(uploadButtonRef.current as any).click()
|
||||
}}
|
||||
>
|
||||
<IconUpload size={18} strokeWidth={1.5} className="text-scale-1200" />
|
||||
<p className="text-xs text-scale-1100">Upload logo</p>
|
||||
</div>
|
||||
)}
|
||||
<input
|
||||
multiple
|
||||
type="file"
|
||||
ref={uploadButtonRef}
|
||||
className="hidden"
|
||||
accept="image/png, image/jpeg"
|
||||
onChange={onFileUpload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</SidePanel.Content>
|
||||
|
||||
<Modal.Separator />
|
||||
<SidePanel.Separator />
|
||||
|
||||
<Modal.Content>
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<div>
|
||||
<p className="prose text-sm">Authorization callback URLs</p>
|
||||
<p className="text-sm text-scale-1000">
|
||||
All URLs must use HTTPS, except for localhost
|
||||
</p>
|
||||
<SidePanel.Content className="py-4">
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<div>
|
||||
<p className="prose text-sm">Authorization callback URLs</p>
|
||||
<p className="text-sm text-scale-1000">
|
||||
All URLs must use HTTPS, except for localhost
|
||||
</p>
|
||||
</div>
|
||||
<Button onClick={() => setUrls(urls.concat({ id: uuidv4(), value: '' }))}>
|
||||
Add URL
|
||||
</Button>
|
||||
</div>
|
||||
<Button onClick={() => setUrls(urls.concat({ id: uuidv4(), value: '' }))}>
|
||||
Add URL
|
||||
</Button>
|
||||
</div>
|
||||
<div className="space-y-2 pb-2">
|
||||
{urls.map((url) => (
|
||||
<Input
|
||||
key={url.id}
|
||||
value={url.value}
|
||||
onChange={(event) => onUpdateUrl(url.id, event.target.value)}
|
||||
placeholder="e.g https://my-website.com"
|
||||
actions={[
|
||||
urls.length > 1 ? (
|
||||
<Button
|
||||
key="remove-url"
|
||||
type="default"
|
||||
onClick={() => removeUrl(url.id)}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
) : null,
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
{errors.urls && <p className="text-red-900 text-sm">{errors.urls}</p>}
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<div className="space-y-2 pb-2">
|
||||
{urls.map((url) => (
|
||||
<Input
|
||||
key={url.id}
|
||||
value={url.value}
|
||||
onChange={(event) => onUpdateUrl(url.id, event.target.value)}
|
||||
placeholder="e.g https://my-website.com"
|
||||
actions={[
|
||||
urls.length > 1 ? (
|
||||
<Button
|
||||
key="remove-url"
|
||||
type="default"
|
||||
onClick={() => removeUrl(url.id)}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
) : null,
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
{errors.urls && <p className="text-red-900 text-sm">{errors.urls}</p>}
|
||||
</div>
|
||||
</SidePanel.Content>
|
||||
<SidePanel.Separator />
|
||||
</div>
|
||||
|
||||
<Modal.Separator />
|
||||
<SidePanel.Separator />
|
||||
|
||||
<Modal.Content>
|
||||
<SidePanel.Content>
|
||||
<div className="pt-2 pb-3 flex items-center justify-between">
|
||||
<Button
|
||||
type="default"
|
||||
@@ -334,7 +340,7 @@ const PublishAppModal = ({
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</SidePanel.Content>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
@@ -383,7 +389,7 @@ const PublishAppModal = ({
|
||||
)
|
||||
}}
|
||||
</Form>
|
||||
</Modal>
|
||||
</SidePanel>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { useParams } from 'common'
|
||||
import { useAuthorizedAppRevokeMutation } from 'data/oauth/authorized-app-revoke-mutation'
|
||||
import { AuthorizedApp } from 'data/oauth/authorized-apps-query'
|
||||
import { useStore } from 'hooks'
|
||||
import { Alert, Modal } from 'ui'
|
||||
import { Alert, IconAlertOctagon, IconLock, Modal } from 'ui'
|
||||
|
||||
export interface RevokeAppModalProps {
|
||||
selectedApp?: AuthorizedApp
|
||||
@@ -50,6 +50,32 @@ const RevokeAppModal = ({ selectedApp, onClose }: RevokeAppModalProps) => {
|
||||
This application will no longer have access to your organization's settings and
|
||||
projects.
|
||||
</Alert>
|
||||
<ul className="mt-4 space-y-5">
|
||||
<li className="flex gap-3 text-sm">
|
||||
<div>
|
||||
<IconAlertOctagon />
|
||||
</div>
|
||||
<span>
|
||||
This application will no longer have access to your organization's settings and
|
||||
projects.
|
||||
</span>
|
||||
</li>
|
||||
|
||||
<li className="flex gap-3 text-sm">
|
||||
<IconLock w={14} className="flex-shrink-0" />
|
||||
<div>
|
||||
<strong>Before you remove this app, consider:</strong>
|
||||
<ul className="space-y-2 mt-2">
|
||||
<li className="list-disc ml-4">
|
||||
Any applications which you may still require access
|
||||
</li>
|
||||
<li className="list-disc ml-4">
|
||||
Anyone will be able to modify, add or delete any row in this table.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</Modal>
|
||||
|
||||
Reference in new issue
Block a user