Merge branch 'develop' of https://github.com/rowyio/rowy into develop

This commit is contained in:
shamsmosowi
2023-04-20 10:46:25 +02:00
22 changed files with 260 additions and 243 deletions

View File

@@ -13,12 +13,12 @@ Low-code for Firebase and Google Cloud.
<div align="center">
[![Discord](https://img.shields.io/discord/853498675484819476?color=%234200FF&label=Chat%20with%20us&logo=discord&logoColor=%23FFFFFF&style=for-the-badge)](https://discord.gg/fjBugmvzZP)
[![Rowy Discord](https://dcbadge.vercel.app/api/server/fjBugmvzZP)](https://discord.gg/fjBugmvzZP)
<p align="center">
<a href="http://www.rowy.io"><b>Website</b></a> •
<a href="http://docs.rowy.io"><b>Documentation</b></a> •
<a href="https://discord.gg/fjBugmvzZP"><b>Discord</b></a> •
<a href="https://discord.gg/fjBugmvzZP"><b>Chat with us</b></a> •
<a href="https://twitter.com/rowyio"><b>Twitter</b></a>
</p>
@@ -27,11 +27,12 @@ Low-code for Firebase and Google Cloud.
</div>
## Live Demo
## Live Demo 🛝
💥 Check out the [live demo](https://demo.rowy.io/) of Rowy 💥
💥 Explore Rowy on [live demo playground](https://demo.rowy.io/) 💥
## Features ✨
## Features
<!-- <table>
<tr>
@@ -39,7 +40,7 @@ Low-code for Firebase and Google Cloud.
<a href="#">Database</a>
</th>
<th>
<a href="#">Code</a>
<a href="#">Automation</a>
</th>
</tr>
<tr>

View File

@@ -133,3 +133,16 @@ export const FunctionsIndexAtom = atom<FunctionSettings[]>([]);
export const updateFunctionAtom = atom<
UpdateCollectionDocFunction<FunctionSettings> | undefined
>(undefined);
export interface ISecretNames {
loading: boolean;
secretNames: null | string[];
}
export const secretNamesAtom = atom<ISecretNames>({
loading: true,
secretNames: null,
});
export const updateSecretNamesAtom = atom<
((clearSecretNames?: boolean) => Promise<void>) | undefined
>(undefined);

View File

@@ -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<Theme> = {
minWidth: 400,
minHeight,

View File

@@ -61,15 +61,19 @@ function CodeEditor({ type, column, handleChange }: ICodeEditorProps) {
// WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
}`;
} else {
dynamicValueFn = `const dynamicValueFn: DefaultValue = async ({row,ref,db,storage,auth,logging})=>{
// WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
logging.log("dynamicValueFn started")
dynamicValueFn = `// Import any NPM package needed
// import _ from "lodash";
const defaultValue: DefaultValue = async ({ row, ref, db, storage, auth, logging }) => {
logging.log("dynamicValueFn started");
// Example: generate random hex color
// const color = "#" + Math.floor(Math.random() * 16777215).toString(16);
// return color;
// WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
}`;
};
export default defaultValue;
`;
}
return (

View File

@@ -80,6 +80,9 @@ export default function GetStartedChecklist({
marginRight: `max(env(safe-area-inset-right), 8px)`,
width: 360,
},
".MuiStepLabel-iconContainer.Mui-active svg": {
transform: "rotate(0deg) !important",
},
},
]}
>

View File

@@ -94,7 +94,7 @@ export function useMenuAction(
try {
text = await navigator.clipboard.readText();
} catch (e) {
enqueueSnackbar(`Read clilboard permission denied.`, {
enqueueSnackbar(`Read clipboard permission denied.`, {
variant: "error",
});
return;

View File

@@ -67,7 +67,7 @@ export const fieldParser = (fieldType: FieldType) => {
case FieldType.dateTime:
return (v: string) => {
const date = parseISO(v);
return isValidDate(date) ? date.getTime() : null;
return isValidDate(date) ? new Date(date) : null;
};
default:
return (v: any) => v;

View File

@@ -8,7 +8,7 @@ import { tableScope, updateFieldAtom } from "@src/atoms/tableScope";
import { TableRowRef } from "@src/types/table";
import SnackbarProgress from "@src/components/SnackbarProgress";
const MAX_CONCURRENT_TASKS = 10;
const MAX_CONCURRENT_TASKS = 1000;
type UploadParamTypes = {
docRef: TableRowRef;

View File

@@ -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 (
<Typography color="text.disabled">
<WarningIcon aria-label="Warning" style={{ verticalAlign: "bottom" }} />

View File

@@ -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 (
<>
<Typography variant="inherit" paragraph>

View File

@@ -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 (
<>
<Typography gutterBottom>

View File

@@ -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 (
<>
<Typography gutterBottom>
@@ -77,8 +80,9 @@ export const webhookStripe = {
</Typography>
{webhookObject.auth.secretKey &&
!secrets.loading &&
!secrets.keys.includes(webhookObject.auth.secretKey) && (
!secretNames.loading &&
secretNames.secretNames &&
!secretNames.secretNames.includes(webhookObject.auth.secretKey) && (
<Alert severity="error" sx={{ height: "auto!important" }}>
Your previously selected key{" "}
<code>{webhookObject.auth.secretKey}</code> does not exist in
@@ -86,34 +90,55 @@ export const webhookStripe = {
</Alert>
)}
<FormControl fullWidth margin={"normal"}>
<InputLabel id="stripe-secret-key">Secret key</InputLabel>
<Select
labelId="stripe-secret-key"
id="stripe-secret-key"
label="Secret key"
variant="filled"
value={webhookObject.auth.secretKey}
onChange={(e) => {
setWebhookObject({
...webhookObject,
auth: { ...webhookObject.auth, secretKey: e.target.value },
});
}}
>
{secrets.keys.map((secret) => {
return <MenuItem value={secret}>{secret}</MenuItem>;
})}
<MenuItem
onClick={() => {
const secretManagerLink = `https://console.cloud.google.com/security/secret-manager/create?project=${secrets.projectId}`;
window?.open?.(secretManagerLink, "_blank")?.focus();
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
marginY: 1,
}}
>
<FormControl fullWidth>
<InputLabel id="stripe-secret-key">Secret key</InputLabel>
<Select
labelId="stripe-secret-key"
id="stripe-secret-key"
label="Secret key"
variant="filled"
value={webhookObject.auth.secretKey}
onChange={(e) => {
setWebhookObject({
...webhookObject,
auth: { ...webhookObject.auth, secretKey: e.target.value },
});
}}
>
Add a key in Secret Manager
</MenuItem>
</Select>
</FormControl>
{secretNames.secretNames?.map((secret) => {
return <MenuItem value={secret}>{secret}</MenuItem>;
})}
<MenuItem
onClick={() => {
const secretManagerLink = `https://console.cloud.google.com/security/secret-manager/create`;
window?.open?.(secretManagerLink, "_blank")?.focus();
}}
>
Add a key in Secret Manager
</MenuItem>
</Select>
</FormControl>
<LoadingButton
sx={{
height: "100%",
marginLeft: 1,
}}
loading={secretNames.loading}
onClick={() => {
updateSecretNames?.();
}}
>
Refresh
</LoadingButton>
</Box>
<TextField
id="stripe-signing-secret"
label="Signing key"

View File

@@ -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 webhookTypeform = {
name: "Typeform",
@@ -83,11 +80,7 @@ export const webhookTypeform = {
// 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 (
<>
<Typography gutterBottom>

View File

@@ -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 (
<>
<Typography gutterBottom>

View File

@@ -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<ISecret>({
loading: true,
keys: [],
projectId,
});
useEffect(() => {
rowyRun({
route: runRoutes.listSecrets,
}).then((secrets) => {
setSecrets({
loading: false,
keys: secrets as string[],
projectId,
});
});
}, []);
return (
<>
<Typography variant="inherit" paragraph>
@@ -63,10 +35,9 @@ export default function Step1Endpoint({
/>
{webhookObject.auth?.enabled &&
webhookSchemas[webhookObject.type].auth(
webhookSchemas[webhookObject.type].Auth(
webhookObject,
setWebhookObject,
secrets
setWebhookObject
)}
{}
</>

View File

@@ -119,12 +119,6 @@ export interface IWebhook {
auth?: any;
}
export interface ISecret {
loading: boolean;
keys: string[];
projectId: string;
}
export const webhookSchemas = {
basic,
typeform,

View File

@@ -12,16 +12,21 @@ export interface ITableNameProps extends IShortTextComponentProps {
export default function TableName({ watchedField, ...props }: ITableNameProps) {
const {
field: { onChange },
field: { onChange, value },
useFormMethods: { control },
disabled,
} = props;
const watchedValue = useWatch({ control, name: watchedField } as any);
useEffect(() => {
if (!disabled && typeof watchedValue === "string" && !!watchedValue)
onChange(startCase(watchedValue));
}, [watchedValue, disabled]);
if (!disabled) {
if (typeof value === "string" && value.trim() !== "") {
onChange(value);
} else if (typeof watchedValue === "string" && !!watchedValue) {
onChange(startCase(watchedValue));
}
}
}, [watchedValue, disabled, onChange, value]);
return <ShortTextComponent {...props} />;
}

View File

@@ -1,67 +1,69 @@
export const RUN_ACTION_TEMPLATE = `const action:Action = async ({row,ref,db,storage,auth,actionParams,user,logging}) => {
// WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
logging.log("action started")
// Import any NPM package needed
// const lodash = require('lodash');
// Example:
/*
const authToken = await rowy.secrets.get("service")
try {
const resp = await fetch('https://example.com/api/v1/users/'+ref.id,{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': authToken
},
body: JSON.stringify(row)
})
return {
success: true,
message: 'User updated successfully on example service',
status: "upto date"
}
} catch (error) {
return {
success: false,
message: 'User update failed on example service',
}
}
*/
// WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
}`;
export const RUN_ACTION_TEMPLATE = `// Import any NPM package needed
// import _ from "lodash";
const action: Action = async ({ row, ref, db, storage, auth, actionParams, user, logging }) => {
logging.log("action started");
export const UNDO_ACTION_TEMPLATE = `const action : Action = async ({row,ref,db,storage,auth,actionParams,user,logging}) => {
// WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
logging.log("action started")
// Import any NPM package needed
// const lodash = require('lodash');
// Example:
/*
const authToken = await rowy.secrets.get("service")
// Example:
const authToken = await rowy.secrets.get("service");
try {
const resp = await fetch('https://example.com/api/v1/users/'+ref.id,{
method: 'DELETE',
const resp = await fetch("https://example.com/api/v1/users/" + ref.id, {
method: "PUT",
headers: {
'Content-Type': 'application/json',
'Authorization': authToken
"Content-Type": "application/json",
Authorization: authToken,
},
body: JSON.stringify(row)
})
body: JSON.stringify(row),
});
return {
success: true,
message: 'User deleted successfully on example service',
status: null
}
message: "User updated successfully on example service",
status: "upto date",
};
} catch (error) {
return {
success: false,
message: 'User delete failed on example service',
}
message: "User update failed on example service",
};
}
*/
// WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
}`;
};
export default action;
`;
export const UNDO_ACTION_TEMPLATE = `// Import any NPM package needed
// import _ from "lodash";
const action: Action = async ({ row, ref, db, storage, auth, actionParams, user, logging }) => {
logging.log("action started");
/*
// Example:
const authToken = await rowy.secrets.get("service");
try {
const resp = await fetch("https://example.com/api/v1/users/" + ref.id, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Authorization: authToken,
},
body: JSON.stringify(row),
});
return {
success: true,
message: "User deleted successfully on example service",
status: null,
};
} catch (error) {
return {
success: false,
message: "User delete failed on example service",
};
}
*/
};
export default action;
`;

View File

@@ -108,7 +108,7 @@ export default function PopupContents({
onChange={(e) => setQuery(e.target.value)}
fullWidth
variant="filled"
label="Search items"
// label="Search items"
hiddenLabel
placeholder="Search items"
InputProps={{

View File

@@ -11,16 +11,19 @@ export const replacer = (data: any) => (m: string, key: string) => {
return get(data, objKey, defaultValue);
};
export const baseFunction = `const connectorFn: Connector = async ({query, row, user, logging}) => {
// WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
logging.log("connectorFn started")
// Import any NPM package needed
// const lodash = require('lodash');
return [];
// WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
};`;
export const baseFunction = `// Import any NPM package needed
// import _ from "lodash";
const connector: Connector = async ({ query, row, user, logging }) => {
logging.log("connector started");
// return [
// { id: "a", name: "Apple" },
// { id: "b", name: "Banana" },
// ];
};
export default connector;
`;
export const getLabel = (config: any, row: TableRow) => {
if (!config.labelFormatter) {

View File

@@ -75,18 +75,19 @@ export default function Settings({
${config.script.replace(/utilFns.getSecret/g, "rowy.secrets.get")}
// WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
}`
: `const derivative:Derivative = async ({row,ref,db,storage,auth,logging})=>{
// WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
logging.log("derivative started")
// Import any NPM package needed
// const lodash = require('lodash');
: `// Import any NPM package needed
// import _ from "lodash";
const derivative: Derivative = async ({ row, ref, db, storage, auth, logging }) => {
logging.log("derivative started");
// Example:
// const sum = row.a + row.b;
// return sum;
// WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY
}`;
};
export default derivative;
`;
return (
<>

View File

@@ -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 dont 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]);
}