diff --git a/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx b/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx
new file mode 100644
index 00000000000..f0a12c1ee54
--- /dev/null
+++ b/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx
@@ -0,0 +1,71 @@
+import Table from 'components/to-be-cleaned/Table'
+import { OAuthApp } from 'data/oauth/oauth-apps-query'
+import dayjs from 'dayjs'
+import { copyToClipboard } from 'lib/helpers'
+import { useState } from 'react'
+import {
+ Button,
+ Dropdown,
+ IconCheck,
+ IconClipboard,
+ IconEdit,
+ IconMoreVertical,
+ IconTrash,
+} from 'ui'
+
+export interface OAuthAppRowProps {
+ app: OAuthApp
+ onSelectEdit: () => void
+ onSelectDelete: () => void
+}
+
+const OAuthAppRow = ({ app, onSelectEdit, onSelectDelete }: OAuthAppRowProps) => {
+ const [isCopied, setIsCopied] = useState(false)
+
+ return (
+
+ {app.name}
+
+ {app.client_id}
+ :
+ }
+ className="ml-2 px-1"
+ onClick={() => {
+ copyToClipboard(app.client_id)
+ setIsCopied(true)
+ setTimeout(() => {
+ setIsCopied(false)
+ }, 3000)
+ }}
+ />
+
+
+ {app.client_secret_alias}...
+
+ {dayjs(app.created_at).format('DD/MM/YYYY, HH:mm:ss')}
+
+ } onClick={() => onSelectEdit()}>
+ Edit app
+ ,
+ ,
+ } onClick={() => onSelectDelete()}>
+ Delete app
+ ,
+ ]}
+ >
+ } className="px-1" />
+
+
+
+ )
+}
+
+export default OAuthAppRow
diff --git a/studio/components/interfaces/Organization/OAuthApps/OAuthApps.tsx b/studio/components/interfaces/Organization/OAuthApps/OAuthApps.tsx
index 81c711cba3e..cc0673a62c8 100644
--- a/studio/components/interfaces/Organization/OAuthApps/OAuthApps.tsx
+++ b/studio/components/interfaces/Organization/OAuthApps/OAuthApps.tsx
@@ -2,16 +2,20 @@ import { useParams } from 'common'
import Table from 'components/to-be-cleaned/Table'
import { OAuthApp, useOAuthAppsQuery } from 'data/oauth/oauth-apps-query'
import { useState } from 'react'
-import { Button, IconEdit, IconTrash } from 'ui'
+import { Alert, Button, IconClipboard, IconEdit, IconTrash, IconX, Input } from 'ui'
import PublishAppModal from './PublishAppModal'
import DeleteAppModal from './DeleteAppModal'
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import AlertError from 'components/ui/AlertError'
+import { copyToClipboard } from 'lib/helpers'
+import OAuthAppRow from './OAuthAppRow'
+import { OAuthAppCreateResponse } from 'data/oauth/oauth-app-create-mutation'
// [Joshen] Just FYI need to relook at the copy writing at the end
const OAuthApps = () => {
const { slug } = useParams()
+ const [createdApp, setCreatedApp] = useState()
const [showPublishModal, setShowPublishModal] = useState(false)
const [selectedAppToUpdate, setSelectedAppToUpdate] = useState()
const [selectedAppToDelete, setSelectedAppToDelete] = useState()
@@ -58,6 +62,47 @@ const OAuthApps = () => {
{isError && }
+ {createdApp !== undefined && (
+
+
+ }
+ className="px-1"
+ onClick={() => setCreatedApp(undefined)}
+ />
+
+
+
+ )}
+
{isSuccess && (
<>
{(publishedApps?.length ?? 0) === 0 ? (
@@ -71,36 +116,20 @@ const OAuthApps = () => {
Name,
Client ID,
Client Secret,
+ Created at,
,
]}
body={
sortedPublishedApps?.map((app) => (
-
- {app.name}
- {app.client_id}
- {app.client_secret_alias}
-
-
- }
- className="px-1"
- onClick={() => {
- setShowPublishModal(true)
- setSelectedAppToUpdate(app)
- }}
- />
- }
- className="px-1"
- onClick={() => setSelectedAppToDelete(app)}
- />
-
-
-
+ {
+ setShowPublishModal(true)
+ setSelectedAppToUpdate(app)
+ }}
+ onSelectDelete={() => setSelectedAppToDelete(app)}
+ />
)) ?? []
}
/>
@@ -151,6 +180,7 @@ const OAuthApps = () => {
setSelectedAppToUpdate(undefined)
setShowPublishModal(false)
}}
+ onCreateSuccess={setCreatedApp}
/>
void
+ onCreateSuccess: (app: OAuthAppCreateResponse) => void
}
-const PublishAppModal = ({ visible, selectedApp, onClose }: PublishAppModalProps) => {
+const PublishAppModal = ({
+ visible,
+ selectedApp,
+ onClose,
+ onCreateSuccess,
+}: PublishAppModalProps) => {
const { ui } = useStore()
const { slug } = useParams()
const uploadButtonRef = useRef()
@@ -96,12 +105,19 @@ const PublishAppModal = ({ visible, selectedApp, onClose }: PublishAppModalProps
if (selectedApp === undefined) {
// Create application
try {
- await createOAuthApp({ slug, name, website, redirect_uris, icon: uploadedIconUrl })
+ const res = await createOAuthApp({
+ slug,
+ name,
+ website,
+ redirect_uris,
+ icon: uploadedIconUrl,
+ })
ui.setNotification({
category: 'success',
message: `Successfully created OAuth app "${name}"!`,
})
onClose()
+ onCreateSuccess(res)
} catch (error: any) {
setSubmitting(false)
ui.setNotification({
@@ -163,7 +179,11 @@ const PublishAppModal = ({ visible, selectedApp, onClose }: PublishAppModalProps