diff --git a/src/components/CodeEditor/CodeEditorHelper.tsx b/src/components/CodeEditor/CodeEditorHelper.tsx index 04326e3c..caf3fbc0 100644 --- a/src/components/CodeEditor/CodeEditorHelper.tsx +++ b/src/components/CodeEditor/CodeEditorHelper.tsx @@ -9,6 +9,9 @@ import { projectScope, projectIdAtom } from "@src/atoms/projectScope"; export interface ICodeEditorHelperProps { docLink: string; + disableDefaultVariables?: boolean; + disableSecretManagerLink?: boolean; + disableCloudManagerLink?: boolean; additionalVariables?: { key: string; description: string; @@ -17,32 +20,37 @@ export interface ICodeEditorHelperProps { export default function CodeEditorHelper({ docLink, + disableDefaultVariables, + disableSecretManagerLink, + disableCloudManagerLink, additionalVariables, }: ICodeEditorHelperProps) { const [projectId] = useAtom(projectIdAtom, projectScope); - const availableVariables = [ - { - key: "db", - description: `db object provides access to firestore database instance of this project. giving you access to any collection or document in this firestore instance`, - }, - { - key: "auth", - description: `auth provides access to a firebase auth instance, can be used to manage auth users or generate tokens.`, - }, - { - key: "storage", - description: `firebase Storage can be accessed through this, storage.bucket() returns default storage bucket of the firebase project.`, - }, - { - key: "rowy", - description: `rowy provides a set of functions that are commonly used, such as easy file uploads & access to GCP Secret Manager`, - }, - { - key: "logging", - description: `logging.log is encouraged to replace console.log`, - }, - ]; + const availableVariables = disableDefaultVariables + ? [] + : [ + { + key: "db", + description: `db object provides access to firestore database instance of this project. giving you access to any collection or document in this firestore instance`, + }, + { + key: "auth", + description: `auth provides access to a firebase auth instance, can be used to manage auth users or generate tokens.`, + }, + { + key: "storage", + description: `firebase Storage can be accessed through this, storage.bucket() returns default storage bucket of the firebase project.`, + }, + { + key: "rowy", + description: `rowy provides a set of functions that are commonly used, such as easy file uploads & access to GCP Secret Manager`, + }, + { + key: "logging", + description: `logging.log is encouraged to replace console.log`, + }, + ]; return ( - - - - - + {!disableSecretManagerLink && ( + + + + + + )} - - - - - + {!disableCloudManagerLink && ( + + + + + + )} { - ${column.config?.defaultValue.script} - }`; + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + ${column.config?.defaultValue.script} + // 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 default value code here - // for example: - // generate random hex color - // const color = "#" + Math.floor(Math.random() * 16777215).toString(16); - // return color; - // checkout the documentation for more info: https://docs.rowy.io/how-to/default-values#dynamic - }`; + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // 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 +}`; } return ( diff --git a/src/components/TableModals/ExtensionsModal/utils.ts b/src/components/TableModals/ExtensionsModal/utils.ts index 50daaf90..6fe636cf 100644 --- a/src/components/TableModals/ExtensionsModal/utils.ts +++ b/src/components/TableModals/ExtensionsModal/utils.ts @@ -62,50 +62,53 @@ export const triggerTypes: ExtensionTrigger[] = ["create", "update", "delete"]; const extensionBodyTemplate = { task: `const extensionBody: TaskBody = async({row, db, change, ref, logging}) => { - // task extensions are very flexible you can do anything from updating other documents in your database, to making an api request to 3rd party service. + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY - // example: - // we can post notification to different discord channels based on row data + // Task Extension is very flexible, you can do anything. + // From updating other documents in your database, to making an api request to 3rd party service. + // Example: post notification to different discord channels based on row data /* const topic = row.topic; const channel = await db.collection('discordChannels').doc(topic).get(); const channelUrl = await channel.get("channelUrl"); const content = "Hello discord channel"; - return fetch("https://discord.com/api/webhooks/"+channelUrl, { - { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - content - }) - }).then(async resp => { - const result = await resp.json() - if (resp.ok) console.info(result) - else console.error(result) + return fetch("https://discord.com/api/webhooks/"+channelUrl, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + content }) + }).then(async resp => { + const result = await resp.json() + if (resp.ok) console.info(result) + else console.error(result) + }) */ + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, docSync: `const extensionBody: DocSyncBody = async({row, db, change, ref, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY return ({ fieldsToSync: [], // a list of string of column names row: row, // object of data to sync, usually the row itself targetPath: "", // fill in the path here }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, historySnapshot: `const extensionBody: HistorySnapshotBody = async({row, db, change, ref, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY return ({ trackedFields: [], // a list of string of column names collectionId: "historySnapshots", // optionally change the sub-collection id of where the history snapshots are stored }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, algoliaIndex: `const extensionBody: AlgoliaIndexBody = async({row, db, change, ref, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY return ({ fieldsToSync: [], // a list of string of column names @@ -113,9 +116,10 @@ const extensionBodyTemplate = { index: "", // algolia index to sync to objectID: ref.id, // algolia object ID, ref.id is one possible choice }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, meiliIndex: `const extensionBody: MeiliIndexBody = async({row, db, change, ref, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY return({ fieldsToSync: [], // a list of string of column names @@ -123,9 +127,10 @@ const extensionBodyTemplate = { index: "", // algolia index to sync to objectID: ref.id, // algolia object ID, ref.id is one possible choice }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, bigqueryIndex: `const extensionBody: BigqueryIndexBody = async({row, db, change, ref, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY return ({ fieldsToSync: [], // a list of string of column names @@ -133,9 +138,10 @@ const extensionBodyTemplate = { index: "", // algolia index to sync to objectID: ref.id, // algolia object ID, ref.id is one possible choice }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, slackMessage: `const extensionBody: SlackMessageBody = async({row, db, change, ref, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY return ({ channels: [], // a list of slack channel IDs in string @@ -143,18 +149,19 @@ const extensionBodyTemplate = { text: "", // the text parameter to pass in to slack api attachments: [], // the attachments parameter to pass in to slack api }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, sendgridEmail: `const extensionBody: SendgridEmailBody = async({row, db, change, ref, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY return ({ from: "Name", // send from field personalizations: [ - { - to: [{ name: "", email: "" }], // recipient - dynamic_template_data: { - }, // template parameters - }, + { + to: [{ name: "", email: "" }], // recipient + dynamic_template_data: { + }, // template parameters + }, ], template_id: "", // sendgrid template ID categories: [], // helper info to categorise sendgrid emails @@ -163,9 +170,10 @@ const extensionBodyTemplate = { // add any other custom args you want to pass to sendgrid events here }, }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, apiCall: `const extensionBody: ApiCallBody = async({row, db, change, ref, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY return ({ body: "", @@ -173,56 +181,56 @@ const extensionBodyTemplate = { method: "", callback: ()=>{}, }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, twilioMessage: `const extensionBody: TwilioMessageBody = async({row, db, change, ref, logging}) => { - /** - * - * Setup twilio secret key: https://docs.rowy.io/extensions/twilio-message#secret-manager-setup - * - * You can add any code logic here to be able to customize your message - * or dynamically get the from or to numbers - * - **/ + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + // Setup twilio secret key: https://docs.rowy.io/extensions/twilio-message#secret-manager-setup + // Add any code here to customize your message or dynamically get the from/to numbers return ({ from: "", // from phone number registered on twilio to: "", // recipient phone number - eg: row. body: "Hi there!" // message text }) + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, pushNotification: `const extensionBody: PushNotificationBody = async({row, db, change, ref, logging}) => { - // you can FCM token from the row or from the user document in the database + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // You can use FCM token from the row or from the user document in the database // const FCMtoken = row.FCMtoken - // or push through topic + // Or push through topic const topicName = 'industry-tech'; - // you can return single or array of notification payloads - return [{ - notification: { - title: 'Hello!', - }, - android: { + // You can return single or array of notification payloads + return [{ notification: { - imageUrl: 'https://thiscatdoesnotexist.com/' - } - }, - apns: { - payload: { - aps: { - 'mutable-content': 1 + title: 'Hello!', + }, + android: { + notification: { + imageUrl: 'https://thiscatdoesnotexist.com/' } }, - fcm_options: { - image: 'https://thiscatdoesnotexist.com/' - } - }, - webpush: { - headers: { - image: 'https://thiscatdoesnotexist.com/' - } - }, - // topic: topicName, // add topic send to subscribers - // token: FCMtoken // add FCM token to send to specific user -}] + apns: { + payload: { + aps: { + 'mutable-content': 1 + } + }, + fcm_options: { + image: 'https://thiscatdoesnotexist.com/' + } + }, + webpush: { + headers: { + image: 'https://thiscatdoesnotexist.com/' + } + }, + // topic: topicName, // add topic send to subscribers + // token: FCMtoken // add FCM token to send to specific user + }] + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, }; @@ -239,8 +247,10 @@ export function emptyExtensionObject( requiredFields: [], trackedFields: [], conditions: `const condition: Condition = async({row, change, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + return true; + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, lastEditor: user, }; diff --git a/src/components/TableModals/WebhooksModal/AddWebhookButton.tsx b/src/components/TableModals/WebhooksModal/AddWebhookButton.tsx index 0d8a63d5..64c2f15d 100644 --- a/src/components/TableModals/WebhooksModal/AddWebhookButton.tsx +++ b/src/components/TableModals/WebhooksModal/AddWebhookButton.tsx @@ -48,7 +48,7 @@ export default function AddWebhookButton({ }} {...props} > - Add webhook… + Add Webhook… `const basicParser: Parser = async({req, db, ref, logging}) => { - // request is the request object from the webhook - // db is the database object - // ref is the reference to collection of the table - // the returned object will be added as a new row to the table - // eg: adding the webhook body as row - const {body} = req; - ${ - table.audit !== false - ? ` - // auditField - const ${ - table.auditFieldCreatedBy ?? "_createdBy" - } = await rowy.metadata.serviceAccountUser() - return { - ...body, - ${table.auditFieldCreatedBy ?? "_createdBy"} - } - ` - : ` - return body; - ` - } - }`, + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // Optionally return an object to be added as a new row to the table + // Example: add the webhook body as row + const {body} = req; + ${ + table.audit !== false + ? `const ${ + table.auditFieldCreatedBy ?? "_createdBy" + } = await rowy.metadata.serviceAccountUser() + return { + ...body, + ${table.auditFieldCreatedBy ?? "_createdBy"} + }` + : `return body;` + } + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +}`, }, condition: { additionalVariables, @@ -95,9 +90,11 @@ export const webhookBasic = { template: ( table: TableSettings ) => `const condition: Condition = async({ref, req, db, logging}) => { - // feel free to add your own code logic here - return true; - }`, + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + return true; + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +}`, }, auth: ( webhookObject: IWebhook, diff --git a/src/components/TableModals/WebhooksModal/Schemas/sendgrid.tsx b/src/components/TableModals/WebhooksModal/Schemas/sendgrid.tsx index b251697f..bafa321a 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/sendgrid.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/sendgrid.tsx @@ -14,21 +14,25 @@ export const webhookSendgrid = { template: ( table: TableSettings ) => `const sendgridParser: Parser = async ({ req, db, ref, logging }) => { - const { body } = req - const eventHandler = async (sgEvent) => { - // Event handlers can be modiefed to preform different actions based on the sendgrid event - // List of events & docs : https://docs.sendgrid.com/for-developers/tracking-events/event#events - const { event, docPath } = sgEvent - // event param is provided by default - // however docPath or other custom parameter needs be passed in the custom_args variable in Sengrid Extension - return db.doc(docPath).update({ sgStatus: event }) - } - // - if (Array.isArray(body)) { - // when multiple events are passed in one call - await Promise.allSettled(body.map(eventHandler)) - } else eventHandler(body) - };`, + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + const { body } = req + const eventHandler = async (sgEvent) => { + // Event handlers can be modiefed to preform different actions based on the sendgrid event + // List of events & docs : https://docs.sendgrid.com/for-developers/tracking-events/event#events + const { event, docPath } = sgEvent + // Event param is provided by default + // However docPath or other custom parameter needs be passed in the custom_args variable in Sengrid Extension + return db.doc(docPath).update({ sgStatus: event }) + } + if (Array.isArray(body)) { + // Multiple events are passed in one call + await Promise.allSettled(body.map(eventHandler)) + } else { + eventHandler(body) + } + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +};`, }, condition: { additionalVariables: null, @@ -36,9 +40,11 @@ export const webhookSendgrid = { template: ( table: TableSettings ) => `const condition: Condition = async({ref, req, db, logging}) => { - // feel free to add your own code logic here - return true; - }`, + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + return true; + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +}`, }, auth: ( webhookObject: IWebhook, diff --git a/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx b/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx index acfb2dfe..e77e1df7 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx @@ -18,15 +18,18 @@ export const webhookStripe = { template: ( table: TableSettings ) => `const sendgridParser: Parser = async ({ req, db, ref, logging }) => { - const event = req.body - switch (event.type) { - case "payment_intent.succeeded": - break; - case "payment_intent.payment_failed": - break; - default: - // all other types - } + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + const event = req.body + switch (event.type) { + case "payment_intent.succeeded": + break; + case "payment_intent.payment_failed": + break; + default: + // All other types + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +} };`, }, condition: { @@ -35,8 +38,10 @@ export const webhookStripe = { template: ( table: TableSettings ) => `const condition: Condition = async({ref, req, db, logging}) => { - // feel free to add your own code logic here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + return true; + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY }`, }, auth: ( diff --git a/src/components/TableModals/WebhooksModal/Schemas/typeform.tsx b/src/components/TableModals/WebhooksModal/Schemas/typeform.tsx index 9c509efd..bf42b781 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/typeform.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/typeform.tsx @@ -14,59 +14,57 @@ export const webhookTypeform = { template: ( table: TableSettings ) => `const typeformParser: Parser = async({req, db, ref, logging}) =>{ - // this reduces the form submission into a single object of key value pairs - // eg: {name: "John", age: 20} - // ⚠️ ensure that you have assigned ref values of the fields - // set the ref value to field key you would like to sync to - // docs: https://help.typeform.com/hc/en-us/articles/360050447552-Block-reference-format-restrictions - const {submitted_at,hidden,answers} = req.body.form_response - const submission = ({ - _createdAt: submitted_at, - ...hidden, - ...answers.reduce((accRow, currAnswer) => { - switch (currAnswer.type) { - case "date": - return { - ...accRow, - [currAnswer.field.ref]: new Date(currAnswer[currAnswer.type]), - }; - case "choice": - return { - ...accRow, - [currAnswer.field.ref]: currAnswer[currAnswer.type].label, - }; - case "choices": - return { - ...accRow, - [currAnswer.field.ref]: currAnswer[currAnswer.type].labels, - }; - case "file_url": - default: - return { - ...accRow, - [currAnswer.field.ref]: currAnswer[currAnswer.type], - }; - } - }, {}), - }) - - ${ - table.audit !== false - ? ` - // auditField - const ${ - table.auditFieldCreatedBy ?? "_createdBy" - } = await rowy.metadata.serviceAccountUser() - return { - ...submission, - ${table.auditFieldCreatedBy ?? "_createdBy"} - } - ` - : ` - return submission - ` - } - };`, + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // This reduces the form submission into a single object of key value pairs + // Example: {name: "John", age: 20} + // ⚠️ Ensure that you have assigned ref values of the fields + // Set the ref value to field key you would like to sync to + // Docs: https://help.typeform.com/hc/en-us/articles/360050447552-Block-reference-format-restrictions + const {submitted_at,hidden,answers} = req.body.form_response + const submission = ({ + _createdAt: submitted_at, + ...hidden, + ...answers.reduce((accRow, currAnswer) => { + switch (currAnswer.type) { + case "date": + return { + ...accRow, + [currAnswer.field.ref]: new Date(currAnswer[currAnswer.type]), + }; + case "choice": + return { + ...accRow, + [currAnswer.field.ref]: currAnswer[currAnswer.type].label, + }; + case "choices": + return { + ...accRow, + [currAnswer.field.ref]: currAnswer[currAnswer.type].labels, + }; + case "file_url": + default: + return { + ...accRow, + [currAnswer.field.ref]: currAnswer[currAnswer.type], + }; + } + }, {}), + }) + + ${ + table.audit !== false + ? `const ${ + table.auditFieldCreatedBy ?? "_createdBy" + } = await rowy.metadata.serviceAccountUser() + return { + ...submission, + ${table.auditFieldCreatedBy ?? "_createdBy"} + }` + : `return submission;` + } + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +};`, }, condition: { additionalVariables: null, @@ -74,9 +72,11 @@ export const webhookTypeform = { template: ( table: TableSettings ) => `const condition: Condition = async({ref, req, db, logging}) => { - // feel free to add your own code logic here - return true; - }`, + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + return true; + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +}`, }, auth: ( webhookObject: IWebhook, diff --git a/src/components/TableModals/WebhooksModal/Schemas/webform.tsx b/src/components/TableModals/WebhooksModal/Schemas/webform.tsx index 7bed061d..abad9c29 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/webform.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/webform.tsx @@ -15,30 +15,24 @@ export const webhook = { template: ( table: TableSettings ) => `const formParser: Parser = async({req, db, ref, logging}) => { - // request is the request object from the webhook - // db is the database object - // ref is the reference to collection of the table - // the returned object will be added as a new row to the table - // eg: adding the webhook body as row - const {body} = req; - ${ - table.audit !== false - ? ` - // auditField - const ${ - table.auditFieldCreatedBy ?? "_createdBy" - } = await rowy.metadata.serviceAccountUser() - return { - ...body, - ${table.auditFieldCreatedBy ?? "_createdBy"} - } - ` - : ` - return body; - ` - } - - }`, + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // Optionally return an object to be added as a new row to the table + // Example: add the webhook body as row + const {body} = req; + ${ + table.audit !== false + ? `const ${ + table.auditFieldCreatedBy ?? "_createdBy" + } = await rowy.metadata.serviceAccountUser() + return { + ...body, + ${table.auditFieldCreatedBy ?? "_createdBy"} + }` + : `return body;` + } + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +}`, }, condition: { additionalVariables: null, @@ -46,9 +40,11 @@ export const webhook = { template: ( table: TableSettings ) => `const condition: Condition = async({ref, req, db, logging}) => { - // feel free to add your own code logic here - return true; - }`, + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + return true; + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +}`, }, auth: ( webhookObject: IWebhook, diff --git a/src/components/TableModals/WebhooksModal/WebhookModal.tsx b/src/components/TableModals/WebhooksModal/WebhookModal.tsx index 8575c0b5..01c2f290 100644 --- a/src/components/TableModals/WebhooksModal/WebhookModal.tsx +++ b/src/components/TableModals/WebhooksModal/WebhookModal.tsx @@ -86,7 +86,7 @@ export default function WebhookModal({ disableBackdropClick disableEscapeKeyDown fullWidth - title={`${mode === "add" ? "Add" : "Update"} webhook: ${ + title={`${mode === "add" ? "Add" : "Update"} Webhook: ${ webhookNames[webhookObject.type] }`} sx={{ diff --git a/src/components/TableModals/WebhooksModal/utils.tsx b/src/components/TableModals/WebhooksModal/utils.tsx index c4292604..e16ca1d9 100644 --- a/src/components/TableModals/WebhooksModal/utils.tsx +++ b/src/components/TableModals/WebhooksModal/utils.tsx @@ -72,7 +72,7 @@ export const webhookNames: Record = { // twitter: "Twitter", stripe: "Stripe", basic: "Basic", - webform: "Web form", + webform: "Web Form", }; export interface IWebhookEditor { diff --git a/src/components/fields/Action/templates.ts b/src/components/fields/Action/templates.ts index 04b3ab23..9d8779c8 100644 --- a/src/components/fields/Action/templates.ts +++ b/src/components/fields/Action/templates.ts @@ -1,54 +1,59 @@ export const RUN_ACTION_TEMPLATE = `const action:Action = async ({row,ref,db,storage,auth,actionParams,user,logging}) => { - // Write your action code here - // for 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', - // } - // } - // checkout the documentation for more info: https://docs.rowy.io/field-types/action#script - }`; + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // 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 UNDO_ACTION_TEMPLATE = `const action : Action = async ({row,ref,db,storage,auth,actionParams,user,logging}) => { - // Write your undo code here - // for 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', - // } - // } - }`; + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // 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', + } + } + */ + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY +}`; diff --git a/src/components/fields/Connector/utils.ts b/src/components/fields/Connector/utils.ts index 88959895..a9668ccb 100644 --- a/src/components/fields/Connector/utils.ts +++ b/src/components/fields/Connector/utils.ts @@ -12,8 +12,10 @@ export const replacer = (data: any) => (m: string, key: string) => { }; export const baseFunction = `const connectorFn: Connector = async ({query, row, user, logging}) => { - // TODO: Implement your service function here + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + return []; + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY };`; export const getLabel = (config: any, row: TableRow) => { diff --git a/src/components/fields/Derivative/Settings.tsx b/src/components/fields/Derivative/Settings.tsx index 7fe36869..14cbd393 100644 --- a/src/components/fields/Derivative/Settings.tsx +++ b/src/components/fields/Derivative/Settings.tsx @@ -66,15 +66,19 @@ export default function Settings({ ? config.derivativeFn : config?.script ? `const derivative:Derivative = async ({row,ref,db,storage,auth,logging})=>{ - ${config.script.replace(/utilFns.getSecret/g, "rowy.secrets.get")} - }` + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + ${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 derivative code here - // for example: - // const sum = row.a + row.b; - // return sum; - // checkout the documentation for more info: https://docs.rowy.io/field-types/derivative - }`; + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // 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 +}`; return ( <> diff --git a/src/components/fields/Formula/Settings.tsx b/src/components/fields/Formula/Settings.tsx index ad0eb16f..360c5981 100644 --- a/src/components/fields/Formula/Settings.tsx +++ b/src/components/fields/Formula/Settings.tsx @@ -22,6 +22,8 @@ import { getFieldProp } from ".."; /* eslint-disable import/no-webpack-loader-syntax */ import formulaDefs from "!!raw-loader!./formula.d.ts"; +import { WIKI_LINKS } from "@src/constants/externalLinks"; +import CodeEditorHelper from "@src/components/CodeEditor/CodeEditorHelper"; const CodeEditor = lazy( () => @@ -97,28 +99,18 @@ export default function Settings({ Formula script
- - - Available: - - - - - row - - - - + }> { - // Write your formula code here - // for example: + // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY + + // Example: // return row.a + row.b; - // checkout the documentation for more info: https://docs.rowy.io/field-types/formula + // WRITE YOUR CODE ONLY ABOVE THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY } `;