diff --git a/app/src/pages/dataset/DatasetCodeDropdown.tsx b/app/src/pages/dataset/DatasetCodeDropdown.tsx index c9669163d3..6148057739 100644 --- a/app/src/pages/dataset/DatasetCodeDropdown.tsx +++ b/app/src/pages/dataset/DatasetCodeDropdown.tsx @@ -65,7 +65,12 @@ export function DatasetCodeDropdown() { >
- + diff --git a/app/src/pages/settings/APIKeysCard.tsx b/app/src/pages/settings/APIKeysCard.tsx new file mode 100644 index 0000000000..f630af2eca --- /dev/null +++ b/app/src/pages/settings/APIKeysCard.tsx @@ -0,0 +1,110 @@ +import React, { ReactNode, Suspense, useState } from "react"; +import { graphql, useLazyLoadQuery } from "react-relay"; +import { css } from "@emotion/react"; + +import { + Alert, + Button, + Dialog, + DialogContainer, + Flex, + Icon, + Icons, + TabbedCard, + TabPane, + Tabs, + TextField, +} from "@arizeai/components"; + +import { CopyToClipboardButton, Loading } from "@phoenix/components"; + +import { APIKeysCardQuery } from "./__generated__/APIKeysCardQuery.graphql"; +import { CreateSystemAPIKeyDialog } from "./CreateSystemAPIKeyDialog"; +import { SystemAPIKeysTable } from "./SystemAPIKeysTable"; + +function APIKeysCardContent() { + const query = useLazyLoadQuery( + graphql` + query APIKeysCardQuery { + ...SystemAPIKeysTableFragment + } + `, + {} + ); + + return ( + + + + + +

Coming Soon

+
+
+ ); +} + +export function APIKeysCard() { + const [dialog, setDialog] = useState(null); + const showOneTimeAPIKeyDialog = (jwt: string) => { + setDialog(); + }; + const showCreateSystemAPIKeyDialog = () => { + setDialog( + + ); + }; + return ( +
+ } />} + onClick={showCreateSystemAPIKeyDialog} + > + System Key + + } + > + }> + + + + setDialog(null)}> + {dialog} + +
+ ); +} + +/** + * Displays the key one time for the user to copy. + */ +function OneTimeAPIKeyDialog(props: { jwt: string }) { + const { jwt } = props; + return ( + + + You have successfully created a new API key. The API key will only be + displayed once below. Please copy and save it in a secure location. + +
+ + + + +
+
+ ); +} diff --git a/app/src/pages/settings/CreateSystemAPIKeyDialog.tsx b/app/src/pages/settings/CreateSystemAPIKeyDialog.tsx new file mode 100644 index 0000000000..b4c05df104 --- /dev/null +++ b/app/src/pages/settings/CreateSystemAPIKeyDialog.tsx @@ -0,0 +1,149 @@ +import React, { useCallback, useState } from "react"; +import { Controller, useForm } from "react-hook-form"; +import { useMutation } from "react-relay"; +import { Form } from "react-router-dom"; +import { graphql } from "relay-runtime"; + +import { + Alert, + Button, + Dialog, + Flex, + TextArea, + TextField, + View, +} from "@arizeai/components"; + +import { CreateSystemAPIKeyDialogMutation } from "./__generated__/CreateSystemAPIKeyDialogMutation.graphql"; + +export type SystemKeyFormParams = { + name: string; + description: string | null; +}; + +/** + * A dialog that allows admin users to create a system API key. + * TODO: Add expiry date field + */ +export function CreateSystemAPIKeyDialog(props: { + onSystemKeyCreated: (jwt: string) => void; +}) { + const { onSystemKeyCreated } = props; + const [error, setError] = useState(null); + const { + control, + handleSubmit, + formState: { isDirty, isValid }, + } = useForm({ + defaultValues: { + name: "System", + description: "", + }, + }); + + const [commit, isCommitting] = useMutation( + graphql` + mutation CreateSystemAPIKeyDialogMutation( + $name: String! + $description: String = null + ) { + createSystemApiKey(input: { name: $name, description: $description }) { + jwt + query { + ...SystemAPIKeysTableFragment + } + } + } + ` + ); + + const onSubmit = useCallback( + (data: SystemKeyFormParams) => { + setError(null); + commit({ + variables: data, + onCompleted: (response) => { + onSystemKeyCreated(response.createSystemApiKey.jwt); + }, + onError: (error) => { + setError(error.message); + }, + }); + }, + [commit, onSystemKeyCreated] + ); + + return ( + + {error && ( + + {error} + + )} + + + ( + + )} + /> + ( +