From 5bf33f097c8f4998ca80e8eab2ec5e9f4d0da688 Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Mon, 10 Apr 2023 15:18:34 +0800 Subject: [PATCH] optimise endpoint call for listSecrets --- src/atoms/projectScope/project.ts | 13 +++ .../CodeEditor/useMonacoCustomizations.ts | 47 ++++----- .../WebhooksModal/Schemas/basic.tsx | 11 +-- .../WebhooksModal/Schemas/firebaseAuth.tsx | 11 +-- .../WebhooksModal/Schemas/sendgrid.tsx | 11 +-- .../WebhooksModal/Schemas/stripe.tsx | 99 ++++++++++++------- .../WebhooksModal/Schemas/typeform.tsx | 11 +-- .../WebhooksModal/Schemas/webform.tsx | 11 +-- .../TableModals/WebhooksModal/Step1Auth.tsx | 35 +------ .../TableModals/WebhooksModal/utils.tsx | 6 -- .../useTableFunctions.ts | 41 ++++++++ 11 files changed, 147 insertions(+), 149 deletions(-) diff --git a/src/atoms/projectScope/project.ts b/src/atoms/projectScope/project.ts index 222ee942..0cd213fb 100644 --- a/src/atoms/projectScope/project.ts +++ b/src/atoms/projectScope/project.ts @@ -133,3 +133,16 @@ export const FunctionsIndexAtom = atom([]); export const updateFunctionAtom = atom< UpdateCollectionDocFunction | undefined >(undefined); + +export interface ISecretNames { + loading: boolean; + secretNames: null | string[]; +} + +export const secretNamesAtom = atom({ + loading: true, + secretNames: null, +}); +export const updateSecretNamesAtom = atom< + ((clearSecretNames?: boolean) => Promise) | undefined +>(undefined); diff --git a/src/components/CodeEditor/useMonacoCustomizations.ts b/src/components/CodeEditor/useMonacoCustomizations.ts index d145d72e..012bf4c9 100644 --- a/src/components/CodeEditor/useMonacoCustomizations.ts +++ b/src/components/CodeEditor/useMonacoCustomizations.ts @@ -19,8 +19,7 @@ import firebaseStorageDefs from "!!raw-loader!./firebaseStorage.d.ts"; import utilsDefs from "!!raw-loader!./utils.d.ts"; import rowyUtilsDefs from "!!raw-loader!./rowy.d.ts"; import extensionsDefs from "!!raw-loader!./extensions.d.ts"; -import { runRoutes } from "@src/constants/runRoutes"; -import { rowyRunAtom, projectScope } from "@src/atoms/projectScope"; +import { projectScope, secretNamesAtom } from "@src/atoms/projectScope"; import { getFieldProp } from "@src/components/fields"; export interface IUseMonacoCustomizationsProps { @@ -53,8 +52,8 @@ export default function useMonacoCustomizations({ const theme = useTheme(); const monaco = useMonaco(); const [tableRows] = useAtom(tableRowsAtom, tableScope); - const [rowyRun] = useAtom(rowyRunAtom, projectScope); const [tableColumnsOrdered] = useAtom(tableColumnsOrderedAtom, tableScope); + const [secretNames] = useAtom(secretNamesAtom, projectScope); useEffect(() => { return () => { @@ -206,26 +205,6 @@ export default function useMonacoCustomizations({ //} }; - const setSecrets = async () => { - // set secret options - try { - const listSecrets = await rowyRun({ - route: runRoutes.listSecrets, - }); - const secretsDef = `type SecretNames = ${listSecrets - .map((secret: string) => `"${secret}"`) - .join(" | ")} - enum secrets { - ${listSecrets - .map((secret: string) => `${secret} = "${secret}"`) - .join("\n")} - } - `; - monaco?.languages.typescript.javascriptDefaults.addExtraLib(secretsDef); - } catch (error) { - console.error("Could not set secret definitions: ", error); - } - }; //TODO: types const setBaseDefinitions = () => { const rowDefinition = @@ -275,14 +254,24 @@ export default function useMonacoCustomizations({ } catch (error) { console.error("Could not set basic", error); } - // set available secrets from secretManager - try { - setSecrets(); - } catch (error) { - console.error("Could not set secrets: ", error); - } }, [monaco, tableColumnsOrdered]); + useEffect(() => { + if (!monaco) return; + if (secretNames.loading) return; + if (!secretNames.secretNames) return; + const secretsDef = `type SecretNames = ${secretNames.secretNames + .map((secret: string) => `"${secret}"`) + .join(" | ")} + enum secrets { + ${secretNames.secretNames + .map((secret: string) => `${secret} = "${secret}"`) + .join("\n")} + } + `; + monaco?.languages.typescript.javascriptDefaults.addExtraLib(secretsDef); + }, [monaco, secretNames]); + let boxSx: SystemStyleObject = { minWidth: 400, minHeight, diff --git a/src/components/TableModals/WebhooksModal/Schemas/basic.tsx b/src/components/TableModals/WebhooksModal/Schemas/basic.tsx index dfb3e90f..1ee073db 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/basic.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/basic.tsx @@ -1,10 +1,7 @@ import { Typography } from "@mui/material"; import WarningIcon from "@mui/icons-material/WarningAmber"; import { TableSettings } from "@src/types/table"; -import { - IWebhook, - ISecret, -} from "@src/components/TableModals/WebhooksModal/utils"; +import { IWebhook } from "@src/components/TableModals/WebhooksModal/utils"; const requestType = [ "declare type WebHookRequest {", @@ -101,11 +98,7 @@ export const webhookBasic = { // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, }, - auth: ( - webhookObject: IWebhook, - setWebhookObject: (w: IWebhook) => void, - secrets: ISecret - ) => { + Auth: (webhookObject: IWebhook, setWebhookObject: (w: IWebhook) => void) => { return ( diff --git a/src/components/TableModals/WebhooksModal/Schemas/firebaseAuth.tsx b/src/components/TableModals/WebhooksModal/Schemas/firebaseAuth.tsx index 21d2d3fd..217eb095 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/firebaseAuth.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/firebaseAuth.tsx @@ -1,10 +1,7 @@ import { Typography, Link, TextField } from "@mui/material"; import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; import { TableSettings } from "@src/types/table"; -import { - IWebhook, - ISecret, -} from "@src/components/TableModals/WebhooksModal/utils"; +import { IWebhook } from "@src/components/TableModals/WebhooksModal/utils"; export const webhookFirebaseAuth = { name: "firebaseAuth", @@ -41,11 +38,7 @@ export const webhookFirebaseAuth = { // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, }, - auth: ( - webhookObject: IWebhook, - setWebhookObject: (w: IWebhook) => void, - secrets: ISecret - ) => { + Auth: (webhookObject: IWebhook, setWebhookObject: (w: IWebhook) => void) => { return ( <> diff --git a/src/components/TableModals/WebhooksModal/Schemas/sendgrid.tsx b/src/components/TableModals/WebhooksModal/Schemas/sendgrid.tsx index ea24dabe..e23bef18 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/sendgrid.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/sendgrid.tsx @@ -1,10 +1,7 @@ import { Typography, Link, TextField } from "@mui/material"; import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; import { TableSettings } from "@src/types/table"; -import { - IWebhook, - ISecret, -} from "@src/components/TableModals/WebhooksModal/utils"; +import { IWebhook } from "@src/components/TableModals/WebhooksModal/utils"; export const webhookSendgrid = { name: "SendGrid", @@ -51,11 +48,7 @@ export const webhookSendgrid = { // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, }, - auth: ( - webhookObject: IWebhook, - setWebhookObject: (w: IWebhook) => void, - secrets: ISecret - ) => { + Auth: (webhookObject: IWebhook, setWebhookObject: (w: IWebhook) => void) => { return ( <> diff --git a/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx b/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx index bbf8c5a5..9c34383f 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx @@ -1,14 +1,18 @@ -import { Typography, Link, TextField, Alert } from "@mui/material"; +import { useAtom } from "jotai"; +import { Typography, Link, TextField, Alert, Box } from "@mui/material"; import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; import { TableSettings } from "@src/types/table"; +import { IWebhook } from "@src/components/TableModals/WebhooksModal/utils"; import { - IWebhook, - ISecret, -} from "@src/components/TableModals/WebhooksModal/utils"; + projectScope, + secretNamesAtom, + updateSecretNamesAtom, +} from "@src/atoms/projectScope"; import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@mui/material/MenuItem"; import FormControl from "@mui/material/FormControl"; import Select from "@mui/material/Select"; +import LoadingButton from "@mui/lab/LoadingButton"; export const webhookStripe = { name: "Stripe", @@ -49,11 +53,10 @@ export const webhookStripe = { // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, }, - auth: ( - webhookObject: IWebhook, - setWebhookObject: (w: IWebhook) => void, - secrets: ISecret - ) => { + Auth: (webhookObject: IWebhook, setWebhookObject: (w: IWebhook) => void) => { + const [secretNames] = useAtom(secretNamesAtom, projectScope); + const [updateSecretNames] = useAtom(updateSecretNamesAtom, projectScope); + return ( <> @@ -77,8 +80,9 @@ export const webhookStripe = { {webhookObject.auth.secretKey && - !secrets.loading && - !secrets.keys.includes(webhookObject.auth.secretKey) && ( + !secretNames.loading && + secretNames.secretNames && + !secretNames.secretNames.includes(webhookObject.auth.secretKey) && ( Your previously selected key{" "} {webhookObject.auth.secretKey} does not exist in @@ -86,34 +90,55 @@ export const webhookStripe = { )} - - Secret key - { + setWebhookObject({ + ...webhookObject, + auth: { ...webhookObject.auth, secretKey: e.target.value }, + }); }} > - Add a key in Secret Manager - - - + {secretNames.secretNames?.map((secret) => { + return {secret}; + })} + { + const secretManagerLink = `https://console.cloud.google.com/security/secret-manager/create`; + window?.open?.(secretManagerLink, "_blank")?.focus(); + }} + > + Add a key in Secret Manager + + + + { + updateSecretNames?.(); + }} + > + Refresh + + void, - secrets: ISecret - ) => { + Auth: (webhookObject: IWebhook, setWebhookObject: (w: IWebhook) => void) => { return ( <> diff --git a/src/components/TableModals/WebhooksModal/Schemas/webform.tsx b/src/components/TableModals/WebhooksModal/Schemas/webform.tsx index bcc1b028..848bad07 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/webform.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/webform.tsx @@ -1,10 +1,7 @@ import { Typography, Link, TextField } from "@mui/material"; import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; import { TableSettings } from "@src/types/table"; -import { - IWebhook, - ISecret, -} from "@src/components/TableModals/WebhooksModal/utils"; +import { IWebhook } from "@src/components/TableModals/WebhooksModal/utils"; export const webhook = { name: "Web Form", @@ -51,11 +48,7 @@ export const webhook = { // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, }, - auth: ( - webhookObject: IWebhook, - setWebhookObject: (w: IWebhook) => void, - secrets: ISecret - ) => { + Auth: (webhookObject: IWebhook, setWebhookObject: (w: IWebhook) => void) => { return ( <> diff --git a/src/components/TableModals/WebhooksModal/Step1Auth.tsx b/src/components/TableModals/WebhooksModal/Step1Auth.tsx index 59bafba9..94f4f2eb 100644 --- a/src/components/TableModals/WebhooksModal/Step1Auth.tsx +++ b/src/components/TableModals/WebhooksModal/Step1Auth.tsx @@ -1,41 +1,13 @@ -import { useAtom } from "jotai"; -import { useEffect, useState } from "react"; import { IWebhookModalStepProps } from "./WebhookModal"; import { FormControlLabel, Checkbox, Typography } from "@mui/material"; -import { - projectIdAtom, - projectScope, - rowyRunAtom, -} from "@src/atoms/projectScope"; -import { runRoutes } from "@src/constants/runRoutes"; -import { webhookSchemas, ISecret } from "./utils"; +import { webhookSchemas } from "./utils"; export default function Step1Endpoint({ webhookObject, setWebhookObject, }: IWebhookModalStepProps) { - const [rowyRun] = useAtom(rowyRunAtom, projectScope); - const [projectId] = useAtom(projectIdAtom, projectScope); - const [secrets, setSecrets] = useState({ - loading: true, - keys: [], - projectId, - }); - - useEffect(() => { - rowyRun({ - route: runRoutes.listSecrets, - }).then((secrets) => { - setSecrets({ - loading: false, - keys: secrets as string[], - projectId, - }); - }); - }, []); - return ( <> @@ -63,10 +35,9 @@ export default function Step1Endpoint({ /> {webhookObject.auth?.enabled && - webhookSchemas[webhookObject.type].auth( + webhookSchemas[webhookObject.type].Auth( webhookObject, - setWebhookObject, - secrets + setWebhookObject )} {} diff --git a/src/components/TableModals/WebhooksModal/utils.tsx b/src/components/TableModals/WebhooksModal/utils.tsx index e43c747b..f8f85ff4 100644 --- a/src/components/TableModals/WebhooksModal/utils.tsx +++ b/src/components/TableModals/WebhooksModal/utils.tsx @@ -119,12 +119,6 @@ export interface IWebhook { auth?: any; } -export interface ISecret { - loading: boolean; - keys: string[]; - projectId: string; -} - export const webhookSchemas = { basic, typeform, diff --git a/src/sources/ProjectSourceFirebase/useTableFunctions.ts b/src/sources/ProjectSourceFirebase/useTableFunctions.ts index cceaca98..a1af1169 100644 --- a/src/sources/ProjectSourceFirebase/useTableFunctions.ts +++ b/src/sources/ProjectSourceFirebase/useTableFunctions.ts @@ -22,6 +22,10 @@ import { AdditionalTableSettings, MinimumTableSettings, currentUserAtom, + updateSecretNamesAtom, + projectIdAtom, + rowyRunAtom, + secretNamesAtom, } from "@src/atoms/projectScope"; import { firebaseDbAtom } from "./init"; @@ -34,10 +38,15 @@ import { rowyUser } from "@src/utils/table"; import { TableSettings, TableSchema, SubTablesSchema } from "@src/types/table"; import { FieldType } from "@src/constants/fields"; import { getFieldProp } from "@src/components/fields"; +import { runRoutes } from "@src/constants/runRoutes"; export function useTableFunctions() { const [firebaseDb] = useAtom(firebaseDbAtom, projectScope); const [currentUser] = useAtom(currentUserAtom, projectScope); + const [projectId] = useAtom(projectIdAtom, projectScope); + const [rowyRun] = useAtom(rowyRunAtom, projectScope); + const [secretNames, setSecretNames] = useAtom(secretNamesAtom, projectScope); + const [updateSecretNames] = useAtom(updateSecretNamesAtom, projectScope); // Create a function to get the latest tables from project settings, // so we don’t create new functions when tables change @@ -330,4 +339,36 @@ export function useTableFunctions() { return tableSchema as TableSchema; }); }, [firebaseDb, readTables, setGetTableSchema]); + + // Set the deleteTable function + const setUpdateSecretNames = useSetAtom(updateSecretNamesAtom, projectScope); + useEffect(() => { + if (!projectId || !rowyRun || !secretNamesAtom) return; + setUpdateSecretNames(() => async (clearSecretNames?: boolean) => { + setSecretNames({ + loading: true, + secretNames: clearSecretNames ? null : secretNames.secretNames, + }); + rowyRun({ + route: runRoutes.listSecrets, + }) + .then((secrets: string[]) => { + setSecretNames({ + loading: false, + secretNames: secrets, + }); + }) + .catch((e) => { + setSecretNames({ + loading: false, + secretNames: clearSecretNames ? null : secretNames.secretNames, + }); + }); + }); + }, [projectId, rowyRun, setUpdateSecretNames]); + useEffect(() => { + if (updateSecretNames) { + updateSecretNames(true); + } + }, [updateSecretNames]); }