diff --git a/bun.lock b/bun.lock
index 38e62bb042b..594c1d23871 100644
--- a/bun.lock
+++ b/bun.lock
@@ -481,7 +481,7 @@
},
"packages/pieces/community/ai": {
"name": "@activepieces/piece-ai",
- "version": "0.3.9",
+ "version": "0.4.0",
"dependencies": {
"@activepieces/pieces-common": "0.12.3",
"@activepieces/pieces-framework": "0.26.2",
@@ -6243,7 +6243,7 @@
},
"packages/pieces/community/slack": {
"name": "@activepieces/piece-slack",
- "version": "0.16.5",
+ "version": "0.17.0",
"dependencies": {
"@activepieces/pieces-common": "workspace:*",
"@activepieces/pieces-framework": "workspace:*",
diff --git a/docs/admin-guide/guides/sso.mdx b/docs/admin-guide/guides/sso.mdx
index de35f945ac1..07eeaf6a6f3 100644
--- a/docs/admin-guide/guides/sso.mdx
+++ b/docs/admin-guide/guides/sso.mdx
@@ -131,6 +131,47 @@ Activepieces supports multiple SSO providers to integrate with your existing ide
+### SAML with Microsoft Entra ID (Azure AD)
+
+
+
+ Go to the [Azure Portal](https://portal.azure.com/) → **Microsoft Entra ID** → **Enterprise applications** → **New application** → **Create your own application**.
+
+ Name it (e.g., "Activepieces") and select **Integrate any other application you don't find in the gallery (Non-gallery)**.
+
+
+ Open the application → **Single sign-on** → select **SAML**.
+
+
+ Edit **Basic SAML Configuration**:
+ - **Identifier (Entity ID)**: `Activepieces`
+ - **Reply URL (Assertion Consumer Service URL)**: paste the SSO URL from the Activepieces configuration screen
+
+
+ Edit **Attributes & Claims** and add these additional claims (leave **Namespace** empty):
+
+ | Claim name | Source attribute |
+ |------------|------------------|
+ | `firstName` | `user.givenname` |
+ | `lastName` | `user.surname` |
+ | `email` | `user.mail` |
+
+
+ In the **SAML Certificates** section, copy the **App Federation Metadata Url**.
+
+ You can paste this URL directly into the **IdP Metadata** field in Activepieces — Activepieces will fetch the metadata XML automatically. Alternatively, open the URL in a browser, save the XML, and paste its contents.
+
+
+ Download the **Certificate (Base64)** from the **SAML Certificates** section. Open the file and copy its contents (including the `-----BEGIN CERTIFICATE-----` / `-----END CERTIFICATE-----` markers) into the **Signing Key** field in Activepieces.
+
+
+ Go to **Users and groups** in the application and assign the users or groups that should be allowed to sign in.
+
+
+ Click **Save** in Activepieces to complete the setup.
+
+
+
### SAML with JumpCloud
@@ -208,6 +249,7 @@ Activepieces supports multiple SSO providers to integrate with your existing ide
- Confirm the IdP metadata is complete and correctly formatted
+ - If you pasted a metadata URL, make sure it is publicly reachable (Activepieces fetches it server-side)
- Verify the signing certificate is properly formatted with BEGIN/END markers
- Ensure all required attributes (firstName, lastName, email) are mapped
diff --git a/packages/pieces/community/ai/package.json b/packages/pieces/community/ai/package.json
index 846a9931609..c9bc5904a91 100644
--- a/packages/pieces/community/ai/package.json
+++ b/packages/pieces/community/ai/package.json
@@ -1,6 +1,6 @@
{
"name": "@activepieces/piece-ai",
- "version": "0.3.9",
+ "version": "0.4.0",
"type": "commonjs",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
diff --git a/packages/pieces/community/ai/src/i18n/translation.json b/packages/pieces/community/ai/src/i18n/translation.json
index fcffb0506d8..932ecadfbff 100644
--- a/packages/pieces/community/ai/src/i18n/translation.json
+++ b/packages/pieces/community/ai/src/i18n/translation.json
@@ -21,6 +21,9 @@
"Web Search Options": "Web Search Options",
"Text": "Text",
"Advanced Options": "Advanced Options",
+ "Input Images": "Input Images",
+ "Image File": "Image File",
+ "Provide images for editing, variation, or merging. Support depends on the selected model.": "Provide images for editing, variation, or merging. Support depends on the selected model.",
"Text to Classify": "Text to Classify",
"Categories": "Categories",
"Files": "Files",
diff --git a/packages/pieces/community/ai/src/lib/actions/image/generate-image.ts b/packages/pieces/community/ai/src/lib/actions/image/generate-image.ts
index 070959a9759..ec975a4afc8 100644
--- a/packages/pieces/community/ai/src/lib/actions/image/generate-image.ts
+++ b/packages/pieces/community/ai/src/lib/actions/image/generate-image.ts
@@ -32,6 +32,18 @@ export const generateImageAction = createAction({
displayName: 'Prompt',
required: true,
}),
+ inputImages: Property.Array({
+ displayName: 'Input Images',
+ description:
+ 'Provide images for editing, variation, or merging. Support depends on the selected model.',
+ required: false,
+ properties: {
+ file: Property.File({
+ displayName: 'Image File',
+ required: true,
+ }),
+ },
+ }),
advancedOptions: Property.DynamicProperties({
displayName: 'Advanced Options',
required: false,
@@ -120,25 +132,6 @@ export const generateImageAction = createAction({
return options;
}
- if (
- providerId === AIProviderName.GOOGLE &&
- modelId === 'gemini-2.5-flash-image-preview'
- ) {
- options = {
- image: Property.Array({
- displayName: 'Images',
- required: false,
- properties: {
- file: Property.File({
- displayName: 'Image File',
- required: true,
- }),
- },
- description: 'The image(s) you want to edit/merge',
- }),
- };
- }
-
return options;
},
}),
@@ -147,12 +140,18 @@ export const generateImageAction = createAction({
const provider = context.propsValue.provider;
const modelId = context.propsValue.model;
+ const inputImages = collectInputImages({
+ inputImages: context.propsValue.inputImages,
+ advancedOptions: context.propsValue.advancedOptions,
+ });
+
const image = await getGeneratedImage({
provider: provider as AIProviderName,
modelId,
engineToken: context.server.token,
apiUrl: context.server.apiUrl,
prompt: context.propsValue.prompt,
+ inputImages,
projectId: context.project.id,
flowId: context.flows.current.id,
runId: context.run.id,
@@ -171,12 +170,44 @@ export const generateImageAction = createAction({
},
});
+const collectInputImages = ({
+ inputImages,
+ advancedOptions,
+}: {
+ inputImages?: unknown;
+ advancedOptions?: DynamicPropsValue;
+}): ApFile[] => {
+ const fromTopLevel = extractImageFiles(inputImages);
+ if (fromTopLevel.length > 0) {
+ return fromTopLevel;
+ }
+ return extractImageFiles(advancedOptions?.['image']);
+};
+
+const extractImageFiles = (value: unknown): ApFile[] => {
+ if (!Array.isArray(value)) {
+ return [];
+ }
+ return value.flatMap((entry) => {
+ if (
+ entry &&
+ typeof entry === 'object' &&
+ 'file' in entry &&
+ entry.file
+ ) {
+ return [entry.file as ApFile];
+ }
+ return [];
+ });
+};
+
const getGeneratedImage = async ({
provider,
modelId,
engineToken,
apiUrl,
prompt,
+ inputImages,
projectId,
flowId,
runId,
@@ -187,6 +218,7 @@ const getGeneratedImage = async ({
engineToken: string;
apiUrl: string;
prompt: string;
+ inputImages: ApFile[];
projectId: string;
flowId: string;
runId: string;
@@ -206,49 +238,78 @@ const getGeneratedImage = async ({
const { provider: effectiveProvider } = getEffectiveProviderAndModel({ provider, model: modelId });
const resolvedProvider = (effectiveProvider ?? provider) as AIProviderName;
- switch (resolvedProvider) {
- case AIProviderName.GOOGLE:
- case AIProviderName.ACTIVEPIECES:
- case AIProviderName.OPENROUTER:
- case AIProviderName.CLOUDFLARE_GATEWAY:
- return generateImageUsingGenerateText({
- model: model as unknown as LanguageModel,
- prompt,
- advancedOptions,
- });
- default: {
- const { image } = await generateImage({
- model,
- prompt,
- providerOptions: {
- [resolvedProvider]: { ...advancedOptions },
- },
- });
- return image
- };
+ const hasInputImages = inputImages.length > 0;
+
+ return withImageInputErrorContext({ modelId, hasInputImages }, async () => {
+ switch (resolvedProvider) {
+ case AIProviderName.GOOGLE:
+ case AIProviderName.ACTIVEPIECES:
+ case AIProviderName.OPENROUTER:
+ case AIProviderName.CLOUDFLARE_GATEWAY:
+ return generateImageUsingGenerateText({
+ model: model as unknown as LanguageModel,
+ prompt,
+ inputImages,
+ });
+ default: {
+ const sanitizedAdvancedOptions = stripLegacyImageField(advancedOptions);
+ const sdkImages = inputImages.map((file) =>
+ Buffer.from(file.base64, 'base64'),
+ );
+ const { image } = await generateImage({
+ model,
+ prompt: hasInputImages
+ ? { text: prompt, images: sdkImages }
+ : prompt,
+ providerOptions: {
+ [resolvedProvider]: { ...sanitizedAdvancedOptions },
+ },
+ });
+ return image;
+ }
+ }
+ });
+};
+
+const withImageInputErrorContext = async (
+ { modelId, hasInputImages }: { modelId: string; hasInputImages: boolean },
+ run: () => Promise,
+): Promise => {
+ try {
+ return await run();
+ } catch (error) {
+ if (!hasInputImages) {
+ throw error;
+ }
+ const original = error instanceof Error ? error.message : String(error);
+ throw new Error(
+ `Image generation failed for model "${modelId}". ` +
+ `This model may not support input images. Try a model that supports image editing — ` +
+ `for example gpt-image-1, dall-e-2, or a Gemini Nano Banana model — or remove the input images. ` +
+ `Original error: ${original}`,
+ );
}
};
const generateImageUsingGenerateText = async ({
model,
prompt,
- advancedOptions,
+ inputImages,
}: {
model: LanguageModel;
prompt: string;
- advancedOptions?: DynamicPropsValue;
+ inputImages: ApFile[];
}): Promise => {
- const images =
- (advancedOptions?.['image'] as Array<{ file: ApFile }> | undefined) ?? [];
-
- const imageFiles = images.map((image) => {
- const fileType = image.file.extension
- ? mime.lookup(image.file.extension)
- : 'image/jpeg';
+ const imageFiles = inputImages.map((file) => {
+ const detected = file.extension ? mime.lookup(file.extension) : false;
+ const fileType =
+ detected && ALLOWED_IMAGE_MIME_TYPES.has(detected)
+ ? detected
+ : 'image/jpeg';
return {
type: 'image',
- image: `data:${fileType || 'image/jpeg'};base64,${image.file.base64}`,
+ image: `data:${fileType};base64,${file.base64}`,
};
});
@@ -271,6 +332,24 @@ const generateImageUsingGenerateText = async ({
return result.files[0];
};
+const stripLegacyImageField = (
+ advancedOptions: DynamicPropsValue | undefined,
+): DynamicPropsValue | undefined => {
+ if (isNil(advancedOptions)) {
+ return advancedOptions;
+ }
+ const { image: _legacy, ...rest } = advancedOptions as Record;
+ return rest as DynamicPropsValue;
+};
+
+const ALLOWED_IMAGE_MIME_TYPES: ReadonlySet = new Set([
+ 'image/jpeg',
+ 'image/png',
+ 'image/gif',
+ 'image/webp',
+ 'image/avif',
+]);
+
const assertImageGenerationSuccess = (
result: GenerateTextResult
): void => {
diff --git a/packages/pieces/community/baserow/package.json b/packages/pieces/community/baserow/package.json
index eee1fe5db90..fa77fc0a115 100644
--- a/packages/pieces/community/baserow/package.json
+++ b/packages/pieces/community/baserow/package.json
@@ -1,6 +1,6 @@
{
"name": "@activepieces/piece-baserow",
- "version": "0.7.0",
+ "version": "0.8.0",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"scripts": {
diff --git a/packages/pieces/community/baserow/src/i18n/ca.json b/packages/pieces/community/baserow/src/i18n/ca.json
index 842eca099a7..bfbfeb419a9 100644
--- a/packages/pieces/community/baserow/src/i18n/ca.json
+++ b/packages/pieces/community/baserow/src/i18n/ca.json
@@ -3,7 +3,6 @@
"Open-source online database tool, alternative to Airtable": "Open-source online database tool, alternative to Airtable",
"API URL": "API URL",
"Database Token": "Database Token",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
"Create Row": "Create Row",
"Delete Row": "Delete Row",
"Get Row": "Get Row",
@@ -111,5 +110,15 @@
"OR": "OR",
"Filters": "Filters",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead."
+ "Row Event": "Row Event",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.",
+ "Create missing select options": "Create missing select options",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/de.json b/packages/pieces/community/baserow/src/i18n/de.json
index 7e9a84e426f..43d59960c20 100644
--- a/packages/pieces/community/baserow/src/i18n/de.json
+++ b/packages/pieces/community/baserow/src/i18n/de.json
@@ -3,10 +3,8 @@
"API URL": "API URL",
"Database Token": "Datenbank-Token",
"Email & Password (JWT)": "E-Mail & Passwort (JWT)",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authentifizieren Sie sich mit Ihrer Baserow E-Mail und Ihrem Passwort. Dieser Modus aktiviert automatische Webhook Registrierung für Trigger — keine manuelle Einrichtung erforderlich.\n\n**Hinweis:** Zwei-Faktor-Authentifizierung (2FA) wird nicht unterstützt. Wenn Ihr Baserow-Konto 2FA aktiviert ist, verwenden Sie stattdessen die Datenbank-Token-Authentifizierung.",
"Email": "E-Mail",
"Password": "Kennwort",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Melden Sie sich bei Ihrem Baserow Konto an.\n 2. Klicken Sie auf Ihr Profilbild (oben links) und navigieren Sie zu **Einstellungen->Datenbank-Tokens**.\n 3. Neues Token mit jedem Namen und entsprechendem Arbeitsbereich erstellen.\n 4. Nach der Token-Erstellung, klicken Sie auf **:** rechts neben dem Token-Namen und kopieren Sie Datenbank-Token.\n 5. Geben Sie Ihre Baserow API URL ein. Wenn Sie baserow.io verwenden, können Sie die Standard-URL verlassen.",
"Create Row": "Zeile erstellen",
"Delete Row": "Zeile löschen",
"Get Row": "Zeile holen",
@@ -82,9 +80,9 @@
"Triggers when a new row is created in a Baserow table.": "Wird ausgelöst, wenn eine neue Zeile in einer Baserow-Tabelle erstellt wird.",
"Triggers when an existing row is updated in a Baserow table.": "Wird ausgelöst, wenn ein bestehender Datensatz in einer Baserow-Tabelle aktualisiert wird.",
"Triggers when a row is deleted from a Baserow table.": "Wird ausgelöst, wenn ein Datensatz aus einer Baserow-Tabelle gelöscht wird.",
- "Rows Created (Batch)": "Zeilen erstellt (Batch)",
- "Rows Updated (Batch)": "Zeilen aktualisiert (Batch)",
- "Rows Deleted (Batch)": "Zeilen gelöscht (Batch)",
+ "Rows Created (Batch)": "Zeilen erstellt (Stapel)",
+ "Rows Updated (Batch)": "Zeilen aktualisiert (Stapel)",
+ "Rows Deleted (Batch)": "Zeilen gelöscht (Stapel)",
"Triggers when new rows are created in a Baserow table. Returns all rows from the event as a single batch.": "Löst aus, wenn neue Datensätze in einer Baserow-Tabelle erstellt werden. Gibt alle Datensätze des Ereignisses als einen Batch zurück.",
"Triggers when existing rows are updated in a Baserow table. Returns all rows from the event as a single batch.": "Löst aus, wenn vorhandene Datensätze in einer Baserow-Tabelle aktualisiert werden. Gibt alle Datensätze des Ereignisses als einen Batch zurück.",
"Triggers when rows are deleted from a Baserow table. Returns all deleted row IDs from the event as a single batch.": "Löst aus, wenn Datensätze aus einer Baserow-Tabelle gelöscht werden. Gibt alle gelöschten Datensatz-IDs des Ereignisses als einen Stapel zurück.",
@@ -105,5 +103,16 @@
"OR": "ODER",
"Filters": "Filter",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "Liste der Filter. Jeder Filter ist ein Objekt mit \"field\" (Feld ID als Nummer), \"type\" (Operator) und \"value\" (Filterwert).",
- "Markdown": "Markdown"
+ "Markdown": "Markdown",
+ "Row Event": "Zeilenereignis",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Wird ausgelöst, wenn eine Zeile in einer Baserow-Tabelle erstellt, aktualisiert oder gelöscht wird. Um nur auf einen Ereignistyp zu reagieren, verwenden Sie die dedizierten Trigger Zeile erstellt, Zeile aktualisiert oder Zeile gelöscht.",
+ "Create missing select options": "Fehlende Auswahloptionen erstellen",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "Wenn aktiviert, werden Einfach-/Mehrfachauswahlwerte, die im Feld noch nicht vorhanden sind, vor dem Erstellen der Zeile hinzugefügt. Vorhandene Optionen bleiben erhalten.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "Wenn aktiviert, werden Einfach-/Mehrfachauswahlwerte, die im Feld noch nicht vorhanden sind, vor dem Aktualisieren der Zeile hinzugefügt. Vorhandene Optionen bleiben erhalten.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/es.json b/packages/pieces/community/baserow/src/i18n/es.json
index 9a132b63394..2154a7a2806 100644
--- a/packages/pieces/community/baserow/src/i18n/es.json
+++ b/packages/pieces/community/baserow/src/i18n/es.json
@@ -3,10 +3,8 @@
"API URL": "API URL",
"Database Token": "Token de base de datos",
"Email & Password (JWT)": "Email y contraseña (JWT)",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.",
"Email": "E-mail",
"Password": "Contraseña",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
"Create Row": "Crear fila",
"Delete Row": "Eliminar fila",
"Get Row": "Obtener fila",
@@ -82,9 +80,9 @@
"Triggers when a new row is created in a Baserow table.": "Se activa cuando se crea una nueva fila en una tabla Baserow.",
"Triggers when an existing row is updated in a Baserow table.": "Se activa cuando se actualiza una fila existente en una tabla Baserow.",
"Triggers when a row is deleted from a Baserow table.": "Se activa cuando una fila es borrada de una tabla Baserow.",
- "Rows Created (Batch)": "Filas creadas (Batch)",
- "Rows Updated (Batch)": "Filas actualizadas (atch)",
- "Rows Deleted (Batch)": "Filas eliminadas (atch)",
+ "Rows Created (Batch)": "Filas creadas (lote)",
+ "Rows Updated (Batch)": "Filas actualizadas (lote)",
+ "Rows Deleted (Batch)": "Filas eliminadas (lote)",
"Triggers when new rows are created in a Baserow table. Returns all rows from the event as a single batch.": "Dispara cuando se crean nuevas filas en una tabla Baserow. Devuelve todas las filas del evento como un único lote.",
"Triggers when existing rows are updated in a Baserow table. Returns all rows from the event as a single batch.": "Dispara cuando los registros existentes se actualizan en una tabla Baserow. Devuelve todas las filas del evento como un único lote.",
"Triggers when rows are deleted from a Baserow table. Returns all deleted row IDs from the event as a single batch.": "Dispara cuando las filas son eliminadas de una tabla Baserow. Devuelve todos los identificadores de fila borrados del evento como un único lote.",
@@ -105,5 +103,16 @@
"OR": "O",
"Filters": "Filtros",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "Lista de filtros. Cada filtro es un objeto con \"campo\" (ID de campo como número), \"tipo\" (operador), y \"valor\" (valor de filtro).",
- "Markdown": "Markdown"
+ "Markdown": "Markdown",
+ "Row Event": "Evento de fila",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Se activa cuando una fila se crea, actualiza o elimina en una tabla Baserow. Para reaccionar solo a un tipo de evento, utilice los disparadores dedicados Fila creada, Fila actualizada o Fila eliminada.",
+ "Create missing select options": "Crear opciones de selección que faltan",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "Cuando está habilitado, los valores de selección única/múltiple que aún no existen en el campo se agregarán antes de crear la fila. Las opciones existentes se conservan.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "Cuando está habilitado, los valores de selección única/múltiple que aún no existen en el campo se agregarán antes de actualizar la fila. Las opciones existentes se conservan.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/fr.json b/packages/pieces/community/baserow/src/i18n/fr.json
index 9e6d289d3ed..a62c09befe6 100644
--- a/packages/pieces/community/baserow/src/i18n/fr.json
+++ b/packages/pieces/community/baserow/src/i18n/fr.json
@@ -3,10 +3,8 @@
"API URL": "API URL",
"Database Token": "Jeton de la base de données",
"Email & Password (JWT)": "E-mail et mot de passe (JWT)",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authentifiez-vous avec votre email Baserow et votre mot de passe. Ce mode active l'enregistrement automatique du webhook pour les déclencheurs - pas besoin de configuration manuelle.\n\n**Note:** L'authentification à deux facteurs (2FA) n'est pas prise en charge. Si votre compte Baserow a 2FA activé, utilisez l'authentification de la base de données à la place.",
"Email": "Courriel",
- "Password": "Password",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
+ "Password": "Mot de passe",
"Create Row": "Créer une ligne",
"Delete Row": "Supprimer la ligne",
"Get Row": "Obtenir la ligne",
@@ -25,6 +23,9 @@
"Clears fields in a row. Empty values will clear the corresponding fields.": "Efface les champs dans une ligne. Les valeurs vides effaceront les champs correspondants.",
"Calculates an aggregation (sum, average, min, max, count, etc.) over all values of a field in a table.": "Calcule une agrégation (somme, moyenne, min, max, compteur, etc.) sur toutes les valeurs d'un champ dans un tableau.",
"Make a custom API call to a specific endpoint": "Passez un appel API personnalisé à un point de terminaison spécifique",
+ "Create missing select options": "Créer les options de sélection manquantes",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "Lorsque activé, les valeurs de sélection unique/multiple qui n'existent pas encore dans le champ seront ajoutées avant la création de la ligne. Les options existantes sont préservées.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "Lorsque activé, les valeurs de sélection unique/multiple qui n'existent pas encore dans le champ seront ajoutées avant la mise à jour de la ligne. Les options existantes sont préservées.",
"Table": "Tableau",
"Table Fields": "Champs de la table",
"Row": "Ligne",
@@ -79,17 +80,19 @@
"Row Created": "Ligne créée",
"Row Updated": "Ligne mise à jour",
"Row Deleted": "Ligne supprimée",
+ "Row Event": "Événement sur une ligne",
"Triggers when a new row is created in a Baserow table.": "Déclenche quand une nouvelle ligne est créée dans une table Baserow.",
"Triggers when an existing row is updated in a Baserow table.": "Déclenche lorsqu'une ligne existante est mise à jour dans une table Baserow.",
"Triggers when a row is deleted from a Baserow table.": "Déclenche lorsqu'une ligne est supprimée d'une table Baserow.",
- "Rows Created (Batch)": "Lignes créées (Batch)",
- "Rows Updated (Batch)": "Lignes mises à jour (Batch)",
- "Rows Deleted (Batch)": "Lignes supprimées (Batch)",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Déclenche lorsqu'une ligne est créée, mise à jour ou supprimée dans une table Baserow. Pour ne réagir qu'à un seul type d'événement, utilisez les déclencheurs dédiés Ligne créée, Ligne mise à jour ou Ligne supprimée.",
+ "Rows Created (Batch)": "Lignes créées par lot",
+ "Rows Updated (Batch)": "Lignes mises à jour par lot",
+ "Rows Deleted (Batch)": "Lignes supprimées par lot",
"Triggers when new rows are created in a Baserow table. Returns all rows from the event as a single batch.": "Déclenche lorsque de nouvelles lignes sont créées dans une table Baserow. Renvoie toutes les lignes de l'événement en un seul lot.",
"Triggers when existing rows are updated in a Baserow table. Returns all rows from the event as a single batch.": "Déclenche lorsque les lignes existantes sont mises à jour dans une table Baserow. Renvoie toutes les lignes de l'événement en un seul lot.",
"Triggers when rows are deleted from a Baserow table. Returns all deleted row IDs from the event as a single batch.": "Déclenche lorsque les lignes sont supprimées d'une table Baserow. Renvoie tous les identifiants de ligne supprimés de l'événement en un seul lot.",
"Batch Create Rows": "Créer des lignes par lot",
- "Batch Update Rows": "Lignes de mise à jour par lot",
+ "Batch Update Rows": "Mettre à jour des lignes par lot",
"Batch Delete Rows": "Supprimer des lignes par lot",
"Creates multiple rows in a single request. Accepts up to 200 rows.": "Crée plusieurs lignes dans une seule requête. Accepte jusqu'à 200 lignes.",
"Updates multiple rows in a single request. Each row must include an \"id\" field. Accepts up to 200 rows.": "Met à jour plusieurs lignes dans une seule requête. Chaque ligne doit inclure un champ \"id\". Accepte jusqu'à 200 lignes.",
@@ -105,5 +108,11 @@
"OR": "OU",
"Filters": "Filtres",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "Liste des filtres. Chaque filtre est un objet avec \"field\" (ID du champ comme nombre), \"type\" (opérateur) et \"value\" (valeur du filtre).",
- "Markdown": "Markdown"
+ "Markdown": "Markdown",
+ "Authentication": "Authentification",
+ "Authentication Method": "Méthode d'authentification",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choisissez comment vous authentifier auprès de Baserow :\n\n**Jeton de base de données** — recommandé. Permissions CRUD par table, compatible avec les comptes 2FA. Les déclencheurs nécessitent une configuration manuelle des webhooks.\n 1. Connectez-vous à votre compte Baserow.\n 2. Cliquez sur votre photo de profil (en haut à gauche) et allez dans **Paramètres → Jetons de base de données**.\n 3. Créez un nouveau jeton, puis cliquez sur **:** à côté de son nom pour le copier.\n 4. Collez-le dans **Jeton de base de données** ci-dessous. Laissez **Courriel** et **Mot de passe** vides.\n\n**E-mail et mot de passe (JWT)** — accès au workspace entier, active l'enregistrement automatique des webhooks pour les déclencheurs. Incompatible avec les comptes ayant la 2FA activée.\n 1. Remplissez **Courriel** et **Mot de passe** avec vos identifiants Baserow. Laissez **Jeton de base de données** vide.\n\nDans les deux modes, renseignez **API URL** avec l'URL de votre instance Baserow (par défaut : `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Le jeton de base de données est recommandé. Utilisez E-mail et mot de passe (JWT) uniquement si vous avez besoin de l'enregistrement automatique des webhooks pour les déclencheurs.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Requis si la méthode d'authentification est **Jeton de base de données**. Laissez vide pour JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Requis si la méthode d'authentification est **E-mail et mot de passe (JWT)**. Laissez vide pour Jeton de base de données."
}
diff --git a/packages/pieces/community/baserow/src/i18n/hi.json b/packages/pieces/community/baserow/src/i18n/hi.json
index 842eca099a7..bfbfeb419a9 100644
--- a/packages/pieces/community/baserow/src/i18n/hi.json
+++ b/packages/pieces/community/baserow/src/i18n/hi.json
@@ -3,7 +3,6 @@
"Open-source online database tool, alternative to Airtable": "Open-source online database tool, alternative to Airtable",
"API URL": "API URL",
"Database Token": "Database Token",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
"Create Row": "Create Row",
"Delete Row": "Delete Row",
"Get Row": "Get Row",
@@ -111,5 +110,15 @@
"OR": "OR",
"Filters": "Filters",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead."
+ "Row Event": "Row Event",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.",
+ "Create missing select options": "Create missing select options",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/id.json b/packages/pieces/community/baserow/src/i18n/id.json
index 842eca099a7..bfbfeb419a9 100644
--- a/packages/pieces/community/baserow/src/i18n/id.json
+++ b/packages/pieces/community/baserow/src/i18n/id.json
@@ -3,7 +3,6 @@
"Open-source online database tool, alternative to Airtable": "Open-source online database tool, alternative to Airtable",
"API URL": "API URL",
"Database Token": "Database Token",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
"Create Row": "Create Row",
"Delete Row": "Delete Row",
"Get Row": "Get Row",
@@ -111,5 +110,15 @@
"OR": "OR",
"Filters": "Filters",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead."
+ "Row Event": "Row Event",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.",
+ "Create missing select options": "Create missing select options",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/ja.json b/packages/pieces/community/baserow/src/i18n/ja.json
index 2e383be7a41..69c52fc323c 100644
--- a/packages/pieces/community/baserow/src/i18n/ja.json
+++ b/packages/pieces/community/baserow/src/i18n/ja.json
@@ -3,10 +3,8 @@
"API URL": "API URL",
"Database Token": "データベーストークン",
"Email & Password (JWT)": "メール&パスワード (JWT)",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Baselow メールアドレスとパスワードで認証します。このモードでは、トリガーの自動Webhook登録が可能になります。手動での設定は不要です。\n\n**注意:** 2要素認証(2FA)はサポートされていません。Baserowアカウントが2FAを有効にしている場合は、代わりにデータベーストークン認証を使用してください。",
"Email": "Eメールアドレス",
"Password": "Password",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
"Create Row": "行を作成",
"Delete Row": "行を削除",
"Get Row": "行を取得",
@@ -82,9 +80,9 @@
"Triggers when a new row is created in a Baserow table.": "Baserow テーブルに新しい行が作成されたときにトリガーします。",
"Triggers when an existing row is updated in a Baserow table.": "Baserow テーブルで既存の行が更新されたときにトリガーされます。",
"Triggers when a row is deleted from a Baserow table.": "Baserow テーブルから行が削除されたときにトリガーします。",
- "Rows Created (Batch)": "行が作成されました (Batch)",
- "Rows Updated (Batch)": "行が更新されました(Batch)",
- "Rows Deleted (Batch)": "行を削除しました(Batch)",
+ "Rows Created (Batch)": "行が作成されました (一括)",
+ "Rows Updated (Batch)": "行が更新されました (一括)",
+ "Rows Deleted (Batch)": "行を削除しました (一括)",
"Triggers when new rows are created in a Baserow table. Returns all rows from the event as a single batch.": "Baserow テーブルに新しい行が作成されたときにトリガーされます。イベントからすべての行を単一のバッチで返します。",
"Triggers when existing rows are updated in a Baserow table. Returns all rows from the event as a single batch.": "Baserow テーブルで既存の行が更新されたときにトリガーされます。イベントからすべての行を単一のバッチで返します。",
"Triggers when rows are deleted from a Baserow table. Returns all deleted row IDs from the event as a single batch.": "Baserow テーブルから行が削除されたときにトリガーされます。イベントから削除されたすべての行 ID を単一のバッチとして返します。",
@@ -105,5 +103,16 @@
"OR": "OR",
"Filters": "絞り込み",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "フィルタの一覧です。各フィルタは、\"フィールド\" (数値としてのフィールド ID )、\"タイプ\" (演算子)、\"値\" (フィルタ値)を持つオブジェクトです。",
- "Markdown": "Markdown"
+ "Markdown": "Markdown",
+ "Row Event": "行イベント",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Baserow テーブルで行が作成、更新、または削除されたときにトリガーされます。1つのイベントタイプのみに反応するには、専用の「行の作成」、「行の更新」、または「行を削除しました」トリガーを使用してください。",
+ "Create missing select options": "不足している選択オプションを作成",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "有効にすると、フィールドにまだ存在しない単一/複数選択の値が、行の作成前に追加されます。既存のオプションは保持されます。",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "有効にすると、フィールドにまだ存在しない単一/複数選択の値が、行の更新前に追加されます。既存のオプションは保持されます。",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/nl.json b/packages/pieces/community/baserow/src/i18n/nl.json
index 6c9e1bde330..7f884690968 100644
--- a/packages/pieces/community/baserow/src/i18n/nl.json
+++ b/packages/pieces/community/baserow/src/i18n/nl.json
@@ -3,10 +3,8 @@
"API URL": "API URL",
"Database Token": "Database token",
"Email & Password (JWT)": "E-mail & wachtwoord (JWT)",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authenticeer met uw Baserow e-mail en wachtwoord. Deze modus activeert automatische webhook registratie voor triggers - geen handmatige installatie nodig.\n\n**Opmerking:** Tweestapsverificatie (2FA) wordt niet ondersteund. Als uw Baserow account 2FA heeft ingeschakeld, gebruik dan in plaats daarvan de Database Token verificatie.",
"Email": "E-mail",
"Password": "Wachtwoord",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in op uw Baserow account.\n 2. Klik op uw profiel-picle-(linksboven) en navigeer naar **Instellingen->Database token**.\n 3. Maak een nieuw token aan met een willekeurige naam en werkruimte.\n 4. Na het aanmaken van token klikt u op **:** rechts naast de token naam en kopieer de database token.\n 5. Voer uw Baserow API URL in. Als u baserow.io gebruikt, kunt u de standaard URL verlaten.",
"Create Row": "Rij maken",
"Delete Row": "Verwijder rij",
"Get Row": "Verkrijg rij",
@@ -105,5 +103,16 @@
"OR": "OF",
"Filters": "Filters",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "Lijst van filters. Elk filter is een object met \"veld\" (veldnummer als nummer), \"type\" (operator) en \"waarde\" (filter waarde).",
- "Markdown": "Markdown"
+ "Markdown": "Markdown",
+ "Row Event": "Rij gebeurtenis",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Wordt uitgevoerd wanneer een rij wordt aangemaakt, bijgewerkt of verwijderd in een Baserow tabel. Om alleen op één type gebeurtenis te reageren, gebruikt u de specifieke triggers Rij aangemaakt, Rij bijgewerkt of Rij verwijderd.",
+ "Create missing select options": "Ontbrekende selectie-opties aanmaken",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "Wanneer ingeschakeld, worden enkelvoudige/meervoudige selectiewaarden die nog niet in het veld bestaan, toegevoegd voordat de rij wordt aangemaakt. Bestaande opties blijven behouden.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "Wanneer ingeschakeld, worden enkelvoudige/meervoudige selectiewaarden die nog niet in het veld bestaan, toegevoegd voordat de rij wordt bijgewerkt. Bestaande opties blijven behouden.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/pt.json b/packages/pieces/community/baserow/src/i18n/pt.json
index 62bb7c70032..856ff382f3c 100644
--- a/packages/pieces/community/baserow/src/i18n/pt.json
+++ b/packages/pieces/community/baserow/src/i18n/pt.json
@@ -3,10 +3,8 @@
"API URL": "API URL",
"Database Token": "Token do banco",
"Email & Password (JWT)": "E-mail e Senha (JWT)",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Autenticar com seu e-mail e senha baserov. Este modo permite o registro automático do webhook para gatilhos — nenhuma configuração manual necessária.\n\n**Nota:** A autenticação de dois fatores (2FA) não é suportada. Se sua conta Baserow tiver o 2FA ativado, use a autenticação de token de banco de dados em vez disso.",
"Email": "e-mail",
"Password": "Senha",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Acesse sua conta Baserow.\n 2. Clique em seu perfil-pic(top-left) e navegue para **Settings->Database tokens**.\n 3. Crie um novo token com qualquer nome e espaço de trabalho apropriado.\n 4. Após a criação do token, clique em **:** direito ao nome do token e copiar token do banco de dados.\n 5. Digite seu URL da API baserow . Se você estiver usando baserow.io, você pode deixar o padrão.",
"Create Row": "Criar Linha",
"Delete Row": "Excluir linha",
"Get Row": "Obter Linha",
@@ -105,5 +103,16 @@
"OR": "OU",
"Filters": "Filtros",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "Lista de filtros. Cada filtro é um objeto com \"campo\" (ID do campo como número), \"tipo\" (operador) e \"valor\" (valor do filtro).",
- "Markdown": "Markdown"
+ "Markdown": "Markdown",
+ "Row Event": "Evento de linha",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Aciona quando uma linha é criada, atualizada ou excluída em uma tabela Baserow. Para reagir apenas a um tipo de evento, use os gatilhos dedicados Linha Criada, Linha Atualizada ou Linha Excluída.",
+ "Create missing select options": "Criar opções de seleção ausentes",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "Quando ativado, os valores de seleção única/múltipla que ainda não existem no campo serão adicionados antes de criar a linha. As opções existentes são preservadas.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "Quando ativado, os valores de seleção única/múltipla que ainda não existem no campo serão adicionados antes de atualizar a linha. As opções existentes são preservadas.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/ru.json b/packages/pieces/community/baserow/src/i18n/ru.json
index 5198c173826..d868e1dc845 100644
--- a/packages/pieces/community/baserow/src/i18n/ru.json
+++ b/packages/pieces/community/baserow/src/i18n/ru.json
@@ -3,7 +3,6 @@
"Open-source online database tool, alternative to Airtable": "Инструмент с открытым исходным кодом для онлайн баз данных, альтернатива Airtable",
"API URL": "API URL",
"Database Token": "Токен базы данных",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Войдите в учетную запись Базерова.\n 2. Нажмите на изображение сверху слева и перейдите в **Настройки->Токен базы данных**.\n 3. Создайте новый токен с любым именем и подходящей рабочей областью.\n 4. После создания токена, нажмите на **:** прямо рядом с именем токена и скопируйте токен базы данных.\n 5. Введите ваш Baserow API URL. Если вы используете baserow.io, вы можете оставить его по умолчанию.",
"Create Row": "Создать строку",
"Delete Row": "Удалить строку",
"Get Row": "Получить строку",
@@ -111,5 +110,15 @@
"OR": "OR",
"Filters": "Filters",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead."
+ "Row Event": "Row Event",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.",
+ "Create missing select options": "Create missing select options",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/translation.json b/packages/pieces/community/baserow/src/i18n/translation.json
index ada5fcffff3..15971468de7 100644
--- a/packages/pieces/community/baserow/src/i18n/translation.json
+++ b/packages/pieces/community/baserow/src/i18n/translation.json
@@ -2,7 +2,9 @@
"Open-source online database tool, alternative to Airtable": "Open-source online database tool, alternative to Airtable",
"API URL": "API URL",
"Database Token": "Database Token",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
+ "Email & Password (JWT)": "Email & Password (JWT)",
+ "Email": "Email",
+ "Password": "Password",
"Create Row": "Create Row",
"Delete Row": "Delete Row",
"Get Row": "Get Row",
@@ -27,6 +29,9 @@
"Updates multiple rows in a single request. Each row must include an \"id\" field. Accepts up to 200 rows.": "Updates multiple rows in a single request. Each row must include an \"id\" field. Accepts up to 200 rows.",
"Deletes multiple rows in a single request. Accepts up to 200 row IDs.": "Deletes multiple rows in a single request. Accepts up to 200 row IDs.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
+ "Create missing select options": "Create missing select options",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.",
"Table": "Table",
"Table Fields": "Table Fields",
"Row": "Row",
@@ -94,17 +99,29 @@
"Row Created": "Row Created",
"Row Updated": "Row Updated",
"Row Deleted": "Row Deleted",
+ "Row Event": "Row Event",
"Rows Created (Batch)": "Rows Created (Batch)",
"Rows Updated (Batch)": "Rows Updated (Batch)",
"Rows Deleted (Batch)": "Rows Deleted (Batch)",
"Triggers when a new row is created in a Baserow table.": "Triggers when a new row is created in a Baserow table.",
"Triggers when an existing row is updated in a Baserow table.": "Triggers when an existing row is updated in a Baserow table.",
"Triggers when a row is deleted from a Baserow table.": "Triggers when a row is deleted from a Baserow table.",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.",
"Triggers when new rows are created in a Baserow table. Returns all rows from the event as a single batch.": "Triggers when new rows are created in a Baserow table. Returns all rows from the event as a single batch.",
"Triggers when existing rows are updated in a Baserow table. Returns all rows from the event as a single batch.": "Triggers when existing rows are updated in a Baserow table. Returns all rows from the event as a single batch.",
"Triggers when rows are deleted from a Baserow table. Returns all deleted row IDs from the event as a single batch.": "Triggers when rows are deleted from a Baserow table. Returns all deleted row IDs from the event as a single batch.",
+<<<<<<< feat/baserow-jwt-restore
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
+}
+=======
"Markdown": "Markdown",
"\n## Setup Instructions\n\n1. In Baserow, click the **···** menu beside your table and select **Webhooks**.\n2. Click **Create webhook +**.\n3. Set the HTTP method to **POST**.\n4. Paste the following URL into the endpoint field:\n```text\n{{webhookUrl}}\n```\n5. Under events, select **Rows created**.\n6. Click **Save**.\n": "\n## Setup Instructions\n\n1. In Baserow, click the **···** menu beside your table and select **Webhooks**.\n2. Click **Create webhook +**.\n3. Set the HTTP method to **POST**.\n4. Paste the following URL into the endpoint field:\n```text\n{{webhookUrl}}\n```\n5. Under events, select **Rows created**.\n6. Click **Save**.\n",
"\n## Setup Instructions\n\n1. In Baserow, click the **···** menu beside your table and select **Webhooks**.\n2. Click **Create webhook +**.\n3. Set the HTTP method to **POST**.\n4. Paste the following URL into the endpoint field:\n```text\n{{webhookUrl}}\n```\n5. Under events, select **Rows updated**.\n6. Click **Save**.\n": "\n## Setup Instructions\n\n1. In Baserow, click the **···** menu beside your table and select **Webhooks**.\n2. Click **Create webhook +**.\n3. Set the HTTP method to **POST**.\n4. Paste the following URL into the endpoint field:\n```text\n{{webhookUrl}}\n```\n5. Under events, select **Rows updated**.\n6. Click **Save**.\n",
"\n## Setup Instructions\n\n1. In Baserow, click the **···** menu beside your table and select **Webhooks**.\n2. Click **Create webhook +**.\n3. Set the HTTP method to **POST**.\n4. Paste the following URL into the endpoint field:\n```text\n{{webhookUrl}}\n```\n5. Under events, select **Rows deleted**.\n6. Click **Save**.\n": "\n## Setup Instructions\n\n1. In Baserow, click the **···** menu beside your table and select **Webhooks**.\n2. Click **Create webhook +**.\n3. Set the HTTP method to **POST**.\n4. Paste the following URL into the endpoint field:\n```text\n{{webhookUrl}}\n```\n5. Under events, select **Rows deleted**.\n6. Click **Save**.\n"
-}
\ No newline at end of file
+}
+>>>>>>> main
diff --git a/packages/pieces/community/baserow/src/i18n/vi.json b/packages/pieces/community/baserow/src/i18n/vi.json
index 842eca099a7..bfbfeb419a9 100644
--- a/packages/pieces/community/baserow/src/i18n/vi.json
+++ b/packages/pieces/community/baserow/src/i18n/vi.json
@@ -3,7 +3,6 @@
"Open-source online database tool, alternative to Airtable": "Open-source online database tool, alternative to Airtable",
"API URL": "API URL",
"Database Token": "Database Token",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
"Create Row": "Create Row",
"Delete Row": "Delete Row",
"Get Row": "Get Row",
@@ -111,5 +110,15 @@
"OR": "OR",
"Filters": "Filters",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead."
+ "Row Event": "Row Event",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.",
+ "Create missing select options": "Create missing select options",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/i18n/zh.json b/packages/pieces/community/baserow/src/i18n/zh.json
index 504993b2c0a..0c6d4e39baf 100644
--- a/packages/pieces/community/baserow/src/i18n/zh.json
+++ b/packages/pieces/community/baserow/src/i18n/zh.json
@@ -3,10 +3,8 @@
"API URL": "API URL",
"Database Token": "Database Token",
"Email & Password (JWT)": "Email & Password (JWT)",
- "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.": "Authenticate with your Baserow email and password. This mode enables automatic webhook registration for triggers — no manual setup needed.\n\n**Note:** Two-factor authentication (2FA) is not supported. If your Baserow account has 2FA enabled, use the Database Token authentication instead.",
"Email": "电子邮件地址",
"Password": "Password",
- "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.": "\n 1. Log in to your Baserow Account.\n 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.\n 3. Create new token with any name and appropriate workspace.\n 4. After token creation,click on **:** right beside token name and copy database token.\n 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.",
"Create Row": "Create Row",
"Delete Row": "删除行",
"Get Row": "获取行",
@@ -105,5 +103,16 @@
"OR": "或",
"Filters": "篩選條件",
"List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).": "List of filters. Each filter is an object with \"field\" (field ID as number), \"type\" (operator), and \"value\" (filter value).",
- "Markdown": "Markdown"
+ "Markdown": "Markdown",
+ "Row Event": "Row Event",
+ "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.": "Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.",
+ "Create missing select options": "Create missing select options",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.",
+ "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.": "When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.",
+ "Authentication": "Authentication",
+ "Authentication Method": "Authentication Method",
+ "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).": "Choose how you want to authenticate with Baserow:\n\n**Database Token** — recommended. Per-table CRUD scoping, compatible with 2FA accounts. Triggers require manual webhook setup.\n 1. Log in to your Baserow account.\n 2. Click on your profile picture (top-left) and go to **Settings → Database tokens**.\n 3. Create a new token, then click **:** beside the token name to copy it.\n 4. Paste it into **Database Token** below. Leave **Email** and **Password** empty.\n\n**Email & Password (JWT)** — workspace-wide access, enables automatic webhook registration for triggers. Not compatible with accounts that have 2FA enabled.\n 1. Fill in **Email** and **Password** with your Baserow login credentials. Leave **Database Token** empty.\n\nIn both modes, set **API URL** to your Baserow instance (default: `https://api.baserow.io`).",
+ "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.": "Database Token is recommended. Use Email & Password (JWT) only if you need automatic webhook registration on triggers.",
+ "Required if Authentication Method is **Database Token**. Leave empty for JWT.": "Required if Authentication Method is **Database Token**. Leave empty for JWT.",
+ "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token.": "Required if Authentication Method is **Email & Password (JWT)**. Leave empty for Database Token."
}
diff --git a/packages/pieces/community/baserow/src/index.ts b/packages/pieces/community/baserow/src/index.ts
index 558aca2b72b..0e195c29af5 100644
--- a/packages/pieces/community/baserow/src/index.ts
+++ b/packages/pieces/community/baserow/src/index.ts
@@ -20,7 +20,24 @@ import { rowDeletedTrigger } from './lib/triggers/row-deleted';
import { rowsCreatedTrigger } from './lib/triggers/rows-created';
import { rowsUpdatedTrigger } from './lib/triggers/rows-updated';
import { rowsDeletedTrigger } from './lib/triggers/rows-deleted';
-import { baserowAuth } from './lib/auth';
+import { rowEventTrigger } from './lib/triggers/row-event';
+import { baserowAuth, baserowAuthHelpers, BaserowAuthValue } from './lib/auth';
+import { BaserowClient } from './lib/common/client';
+
+async function buildCustomApiAuthHeader(auth: BaserowAuthValue): Promise<{ Authorization: string }> {
+ const { apiUrl, token, email, password } = auth.props;
+ if (baserowAuthHelpers.isJwtAuth(auth)) {
+ if (!email || !password) {
+ throw new Error('Email and Password are required for JWT authentication.');
+ }
+ const jwt = await BaserowClient.getJwtToken({ apiUrl, email, password });
+ return { Authorization: `JWT ${jwt}` };
+ }
+ if (!token) {
+ throw new Error('Database Token is required for Database Token authentication.');
+ }
+ return { Authorization: `Token ${token}` };
+}
export const baserow = createPiece({
displayName: 'Baserow',
@@ -29,7 +46,7 @@ export const baserow = createPiece({
minimumSupportedRelease: '0.30.0',
logoUrl: 'https://cdn.activepieces.com/pieces/baserow.png',
categories: [PieceCategory.PRODUCTIVITY],
- authors: ["kishanprmr", "MoShizzle", "abuaboud", 'bst1n', 'sanket-a11y'],
+ authors: ["kishanprmr", "MoShizzle", "abuaboud", 'bst1n', 'sanket-a11y', 'onyedikachi-david'],
actions: [
createRowAction,
deleteRowAction,
@@ -50,15 +67,14 @@ export const baserow = createPiece({
return auth.props.apiUrl;
},
auth: baserowAuth,
- authMapping: async (auth) => {
- return { Authorization: `Token ${auth.props.token}` };
- },
+ authMapping: buildCustomApiAuthHeader,
}),
],
triggers: [
rowCreatedTrigger,
rowUpdatedTrigger,
rowDeletedTrigger,
+ rowEventTrigger,
rowsCreatedTrigger,
rowsUpdatedTrigger,
rowsDeletedTrigger,
diff --git a/packages/pieces/community/baserow/src/lib/actions/aggregate-field.ts b/packages/pieces/community/baserow/src/lib/actions/aggregate-field.ts
index b8806bc249a..4fdadba666b 100644
--- a/packages/pieces/community/baserow/src/lib/actions/aggregate-field.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/aggregate-field.ts
@@ -61,7 +61,7 @@ export const aggregateFieldAction = createAction({
aggregation_type: Property.StaticDropdown({
displayName: 'Aggregation Type',
description:
- 'Sum, average, min, max, std_dev and variance only work on number fields.',
+ 'The calculation to run over the field. **Sum, Average, Min, Max, Median, Std Dev, and Variance** only work with number fields.',
required: true,
options: {
disabled: false,
diff --git a/packages/pieces/community/baserow/src/lib/actions/batch-create-rows.ts b/packages/pieces/community/baserow/src/lib/actions/batch-create-rows.ts
index e6a19a2c7af..3c21d6422c6 100644
--- a/packages/pieces/community/baserow/src/lib/actions/batch-create-rows.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/batch-create-rows.ts
@@ -25,9 +25,10 @@ export const batchCreateRowsAction = createAction({
throw new Error('Rows must be a JSON array.');
}
const client = await makeClient(context.auth);
- return await client.batchCreateRows(
+ const response = (await client.batchCreateRows(
table_id,
rows as Record[]
- );
+ )) as { items: Record[] };
+ return { count: response.items.length, rows: response.items };
},
});
diff --git a/packages/pieces/community/baserow/src/lib/actions/batch-delete-rows.ts b/packages/pieces/community/baserow/src/lib/actions/batch-delete-rows.ts
index 8c84102793c..0eb5c41c257 100644
--- a/packages/pieces/community/baserow/src/lib/actions/batch-delete-rows.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/batch-delete-rows.ts
@@ -12,7 +12,7 @@ export const batchDeleteRowsAction = createAction({
table_id: baserowCommon.tableId(),
row_ids: Property.Array({
displayName: 'Row IDs',
- description: 'List of row IDs to delete.',
+ description: 'Numeric IDs of the rows to delete. You can get row IDs from the List Rows or Find Row actions.',
required: true,
}),
},
@@ -26,6 +26,7 @@ export const batchDeleteRowsAction = createAction({
.map((id) => parseInt(String(id), 10))
.filter((id) => !isNaN(id));
const client = await makeClient(context.auth);
- return await client.batchDeleteRows(table_id, ids);
+ await client.batchDeleteRows(table_id, ids);
+ return { deleted_count: ids.length };
},
});
diff --git a/packages/pieces/community/baserow/src/lib/actions/batch-update-rows.ts b/packages/pieces/community/baserow/src/lib/actions/batch-update-rows.ts
index bd1ef4497c0..d5acdf82c4e 100644
--- a/packages/pieces/community/baserow/src/lib/actions/batch-update-rows.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/batch-update-rows.ts
@@ -25,9 +25,10 @@ export const batchUpdateRowsAction = createAction({
throw new Error('Rows must be a JSON array.');
}
const client = await makeClient(context.auth);
- return await client.batchUpdateRows(
+ const response = (await client.batchUpdateRows(
table_id,
rows as Record[]
- );
+ )) as { items: Record[] };
+ return { count: response.items.length, rows: response.items };
},
});
diff --git a/packages/pieces/community/baserow/src/lib/actions/clean-row.ts b/packages/pieces/community/baserow/src/lib/actions/clean-row.ts
index 07bda771e2b..c300b699fb9 100644
--- a/packages/pieces/community/baserow/src/lib/actions/clean-row.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/clean-row.ts
@@ -6,7 +6,7 @@ export const cleanRowAction = createAction({
name: 'baserow_clean_row',
displayName: 'Clean Row',
description:
- 'Clears fields in a row. Empty values will clear the corresponding fields.',
+ 'Sets all fields in a row to empty/null. To update only specific fields, use Update Row instead.',
auth: baserowAuth,
props: {
table_id: baserowCommon.tableId(),
diff --git a/packages/pieces/community/baserow/src/lib/actions/create-row.ts b/packages/pieces/community/baserow/src/lib/actions/create-row.ts
index f94f68a22dd..b4a342243f6 100644
--- a/packages/pieces/community/baserow/src/lib/actions/create-row.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/create-row.ts
@@ -1,19 +1,32 @@
-import { createAction } from '@activepieces/pieces-framework';
+import { createAction, Property } from '@activepieces/pieces-framework';
import { baserowAuth } from '../auth';
-import { baserowCommon, formatFieldValues, makeClient } from '../common';
+import {
+ baserowCommon,
+ ensureSelectOptionsExist,
+ formatFieldValues,
+ makeClient,
+} from '../common';
export const createRowAction = createAction({
name: 'baserow_create_row',
displayName: 'Create Row',
- description: 'Creates a new row.',
+ description: 'Creates a new row in a table.',
auth: baserowAuth,
props: {
table_id: baserowCommon.tableId(),
table_fields: baserowCommon.tableFields(true),
+ create_missing_select_options: Property.Checkbox({
+ displayName: 'Create missing select options',
+ description:
+ 'When enabled, single/multi-select values that do not yet exist in the field will be added before creating the row. Existing options are preserved.',
+ required: false,
+ defaultValue: false,
+ }),
},
async run(context) {
const table_id = context.propsValue.table_id!;
const tableFieldsInput = context.propsValue.table_fields!;
+ const createMissingSelectOptions = context.propsValue.create_missing_select_options ?? false;
const client = await makeClient(context.auth);
const tableSchema = await client.listTableFields(table_id);
@@ -26,6 +39,15 @@ export const createRowAction = createAction({
const formattedFields = formatFieldValues(tableFieldsInput, fieldTypeMap, {
skipEmpty: true,
});
+
+ if (createMissingSelectOptions) {
+ await ensureSelectOptionsExist({
+ fields: tableSchema,
+ payload: formattedFields,
+ client,
+ });
+ }
+
return await client.createRow(table_id, formattedFields);
},
});
diff --git a/packages/pieces/community/baserow/src/lib/actions/delete-row.ts b/packages/pieces/community/baserow/src/lib/actions/delete-row.ts
index ff73aec847c..58faeb0e79a 100644
--- a/packages/pieces/community/baserow/src/lib/actions/delete-row.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/delete-row.ts
@@ -14,6 +14,7 @@ export const deleteRowAction = createAction({
async run(context) {
const { table_id, row_id } = context.propsValue as { table_id: number; row_id: number };
const client = await makeClient(context.auth);
- return await client.deleteRow(table_id, row_id);
+ await client.deleteRow(table_id, row_id);
+ return { success: true };
},
});
diff --git a/packages/pieces/community/baserow/src/lib/actions/find-row.ts b/packages/pieces/community/baserow/src/lib/actions/find-row.ts
index c94d28df8f2..e1ea8010431 100644
--- a/packages/pieces/community/baserow/src/lib/actions/find-row.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/find-row.ts
@@ -80,8 +80,8 @@ export const findRowAction = createAction({
)) as { results: Record[]; count: number };
if (response.results.length === 0) {
- return { found: false, row: null, count: 0 };
+ return { found: false, count: 0 };
}
- return { found: true, row: response.results[0], count: response.count };
+ return { found: true, count: response.count, ...response.results[0] };
},
});
diff --git a/packages/pieces/community/baserow/src/lib/actions/get-row.ts b/packages/pieces/community/baserow/src/lib/actions/get-row.ts
index 039362fa191..cdd0895a03e 100644
--- a/packages/pieces/community/baserow/src/lib/actions/get-row.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/get-row.ts
@@ -5,7 +5,7 @@ import { baserowCommon, makeClient } from '../common';
export const getRowAction = createAction({
name: 'baserow_get_row',
displayName: 'Get Row',
- description: 'Fetches a single table row.',
+ description: 'Gets a single row by its ID from a table.',
auth: baserowAuth,
props: {
table_id: baserowCommon.tableId(),
diff --git a/packages/pieces/community/baserow/src/lib/actions/list-rows.ts b/packages/pieces/community/baserow/src/lib/actions/list-rows.ts
index cbb1d71c40d..08fae00154b 100644
--- a/packages/pieces/community/baserow/src/lib/actions/list-rows.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/list-rows.ts
@@ -8,7 +8,7 @@ import { baserowCommon, makeClient } from '../common';
export const listRowsAction = createAction({
name: 'baserow_list_rows',
displayName: 'List Rows',
- description: 'Finds a page of rows in given table.',
+ description: 'Lists rows from a table with optional search, sorting, and filtering.',
auth: baserowAuth,
props: {
table_id: baserowCommon.tableId(),
@@ -22,37 +22,44 @@ export const listRowsAction = createAction({
displayName: 'Page Size',
required: false,
defaultValue: 100,
- description: 'Number of rows to return per page. Defaults to 100.',
+ description: 'Number of rows to return per page. Maximum 200. Defaults to 100.',
}),
search: Property.ShortText({
displayName: 'Search',
required: false,
- description:
- 'If provided only rows with cell data that matches the search query are going to be returned.',
+ description: 'Return only rows whose cell data matches this search term.',
}),
order_by: Property.ShortText({
displayName: 'Order By',
required: false,
- description: `If provided rows will be order by specific field.Use **-** sign for descending / **+** sing for ascending ordering.
- Example. "-My Field" will return rows in descending order based on "My Field" field.`,
+ description: 'Field name to sort by. Prefix with **-** for descending or **+** for ascending. Example: `-Name` sorts by Name Z→A.',
}),
filter_type: Property.StaticDropdown({
- displayName: 'Filter Type',
- description:
- 'When AND is selected, all filters must match. When OR is selected, any filter can match.',
+ displayName: 'Filter Combination',
+ description: 'How to combine multiple filters. **AND** requires all filters to match; **OR** requires any one filter to match.',
required: false,
+ defaultValue: 'AND',
options: {
disabled: false,
options: [
- { label: 'AND', value: 'AND' },
- { label: 'OR', value: 'OR' },
+ { label: 'AND — all filters must match', value: 'AND' },
+ { label: 'OR — any filter can match', value: 'OR' },
],
},
}),
+ filter_instructions: Property.MarkDown({
+ value: `**How to add filters** (optional):
+
+Each filter is a JSON object with three keys:
+- \`field\` — numeric field ID (in Baserow, click the field header; the ID appears in the page URL)
+- \`type\` — operator: \`equal\`, \`not_equal\`, \`contains\`, \`contains_not\`, \`higher_than\`, \`lower_than\`, \`is_empty\`, \`is_not_empty\`
+- \`value\` — the value to compare against
+
+Example: \`{"field": 123, "type": "equal", "value": "Active"}\``,
+ }),
filters: Property.Array({
displayName: 'Filters',
- description:
- 'List of filters. Each filter is an object with "field" (field ID as number), "type" (operator), and "value" (filter value).',
+ description: 'Each entry is a JSON object with "field" (numeric ID), "type" (operator), and "value". Leave empty to return all rows.',
required: false,
}),
},
@@ -84,7 +91,7 @@ export const listRowsAction = createAction({
};
}
- return await client.listRows(
+ const response = (await client.listRows(
table_id!,
page,
limit,
@@ -92,6 +99,8 @@ export const listRowsAction = createAction({
order_by,
undefined,
advancedFilters
- );
+ )) as { count: number; results: Record[] };
+
+ return { count: response.count, rows: response.results };
},
});
diff --git a/packages/pieces/community/baserow/src/lib/actions/update-row.ts b/packages/pieces/community/baserow/src/lib/actions/update-row.ts
index f5fe91955b0..16c2e1de9cf 100644
--- a/packages/pieces/community/baserow/src/lib/actions/update-row.ts
+++ b/packages/pieces/community/baserow/src/lib/actions/update-row.ts
@@ -1,6 +1,11 @@
-import { createAction } from '@activepieces/pieces-framework';
+import { createAction, Property } from '@activepieces/pieces-framework';
import { baserowAuth } from '../auth';
-import { baserowCommon, formatFieldValues, makeClient } from '../common';
+import {
+ baserowCommon,
+ ensureSelectOptionsExist,
+ formatFieldValues,
+ makeClient,
+} from '../common';
export const updateRowAction = createAction({
name: 'baserow_update_row',
@@ -12,13 +17,19 @@ export const updateRowAction = createAction({
table_id: baserowCommon.tableId(),
row_id: baserowCommon.rowId(),
table_fields: baserowCommon.tableFields(true),
+ create_missing_select_options: Property.Checkbox({
+ displayName: 'Create missing select options',
+ description:
+ 'When enabled, single/multi-select values that do not yet exist in the field will be added before updating the row. Existing options are preserved.',
+ required: false,
+ defaultValue: false,
+ }),
},
async run(context) {
- const { table_id, row_id } = context.propsValue as {
- table_id: number;
- row_id: number;
- };
+ const table_id = context.propsValue.table_id!;
+ const row_id = context.propsValue.row_id!;
const tableFieldsInput = context.propsValue.table_fields!;
+ const createMissingSelectOptions = context.propsValue.create_missing_select_options ?? false;
const client = await makeClient(context.auth);
const tableSchema = await client.listTableFields(table_id);
@@ -31,6 +42,15 @@ export const updateRowAction = createAction({
const formattedFields = formatFieldValues(tableFieldsInput, fieldTypeMap, {
skipEmpty: true,
});
+
+ if (createMissingSelectOptions) {
+ await ensureSelectOptionsExist({
+ fields: tableSchema,
+ payload: formattedFields,
+ client,
+ });
+ }
+
return await client.updateRow(table_id, row_id, formattedFields);
},
});
diff --git a/packages/pieces/community/baserow/src/lib/auth.ts b/packages/pieces/community/baserow/src/lib/auth.ts
index 05d90698d9e..e39749976ce 100644
--- a/packages/pieces/community/baserow/src/lib/auth.ts
+++ b/packages/pieces/community/baserow/src/lib/auth.ts
@@ -5,27 +5,94 @@ import {
} from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
+const description = `Connect to Baserow using either a Database Token (recommended) or your Email & Password. Fill in only the fields for your chosen method — leave the other section blank.`;
+
+function isJwtMode(authType: string | undefined, props: { token?: string; email?: string; password?: string }): boolean {
+ if (authType === 'jwt') return true;
+ if (authType === 'database_token') return false;
+ return Boolean(props.email && props.password && !props.token);
+}
+
export const baserowAuth = PieceAuth.CustomAuth({
- displayName: 'Database Token',
- description: `
- 1. Log in to your Baserow Account.
- 2. Click on your profile-pic(top-left) and navigate to **Settings->Database tokens**.
- 3. Create new token with any name and appropriate workspace.
- 4. After token creation,click on **:** right beside token name and copy database token.
- 5. Enter your Baserow API URL.If you are using baserow.io, you can leave the default one.`,
+ displayName: 'Authentication',
+ description,
required: true,
props: {
+ authType: Property.StaticDropdown({
+ displayName: 'Authentication Method',
+ description:
+ 'Choose **Database Token** (recommended) for scoped, per-table access compatible with 2FA. Choose **Email & Password** only if you need automatic webhook registration on triggers — 2FA accounts are not supported.',
+ required: true,
+ defaultValue: 'database_token',
+ options: {
+ disabled: false,
+ options: [
+ { label: 'Database Token (recommended)', value: 'database_token' },
+ { label: 'Email & Password (JWT)', value: 'jwt' },
+ ],
+ },
+ }),
apiUrl: Property.ShortText({
displayName: 'API URL',
+ description: 'Your Baserow instance URL. Leave the default for Baserow Cloud.',
required: true,
defaultValue: 'https://api.baserow.io',
}),
+ md_token: Property.MarkDown({
+ value: `---
+#### 🔑 Database Token
+Go to **Settings → Database tokens** in Baserow, create a token, copy it, and paste it below. Leave Email and Password blank.`,
+ }),
token: PieceAuth.SecretText({
displayName: 'Database Token',
- required: true,
+ description: 'Your Baserow database token. Leave blank when using Email & Password.',
+ required: false,
+ }),
+ md_jwt: Property.MarkDown({
+ value: `---
+#### 👤 Email & Password (JWT)
+Enter your Baserow login credentials below. Leave Database Token blank. Accounts with 2FA enabled are not supported.`,
+ }),
+ email: Property.ShortText({
+ displayName: 'Email',
+ description: 'Your Baserow account email. Leave blank when using Database Token.',
+ required: false,
+ }),
+ password: PieceAuth.SecretText({
+ displayName: 'Password',
+ description: 'Your Baserow account password. Leave blank when using Database Token.',
+ required: false,
}),
},
validate: async ({ auth }) => {
+ if (isJwtMode(auth.authType, auth)) {
+ if (!auth.email || !auth.password) {
+ return {
+ valid: false,
+ error: 'Email and Password are required for JWT authentication.',
+ };
+ }
+ try {
+ await httpClient.sendRequest({
+ method: HttpMethod.POST,
+ url: `${auth.apiUrl}/api/user/token-auth/`,
+ body: { email: auth.email, password: auth.password },
+ });
+ return { valid: true };
+ } catch {
+ return {
+ valid: false,
+ error:
+ 'Invalid email, password, or API URL. Note: 2FA is not supported — use Database Token if 2FA is enabled.',
+ };
+ }
+ }
+ if (!auth.token) {
+ return {
+ valid: false,
+ error: 'Database Token is required when using Database Token authentication.',
+ };
+ }
try {
await httpClient.sendRequest({
method: HttpMethod.GET,
@@ -39,6 +106,9 @@ export const baserowAuth = PieceAuth.CustomAuth({
},
});
-export type BaserowAuthValue = AppConnectionValueForAuthProperty<
- typeof baserowAuth
->;
+export const baserowAuthHelpers = {
+ isJwtAuth: (auth: BaserowAuthValue): boolean =>
+ isJwtMode(auth.props.authType, auth.props),
+};
+
+export type BaserowAuthValue = AppConnectionValueForAuthProperty;
diff --git a/packages/pieces/community/baserow/src/lib/common/client.ts b/packages/pieces/community/baserow/src/lib/common/client.ts
index abc6f7356aa..18ff199eadd 100644
--- a/packages/pieces/community/baserow/src/lib/common/client.ts
+++ b/packages/pieces/community/baserow/src/lib/common/client.ts
@@ -33,9 +33,27 @@ export function prepareQuery(request?: Record): QueryParams {
export class BaserowClient {
constructor(
private baseUrl: string,
- private authHeader: string
+ private authHeader: string,
+ private isJwt: boolean = false
) { }
+ static async getJwtToken({
+ apiUrl,
+ email,
+ password,
+ }: {
+ apiUrl: string;
+ email: string;
+ password: string;
+ }): Promise {
+ const res = await httpClient.sendRequest<{ token: string }>({
+ method: HttpMethod.POST,
+ url: `${apiUrl}/api/user/token-auth/`,
+ body: { email, password },
+ });
+ return res.body.token;
+ }
+
async makeRequest(
method: HttpMethod,
url: string,
@@ -52,6 +70,13 @@ export class BaserowClient {
return res.body;
}
async listTables(): Promise {
+ if (this.isJwt) {
+ const apps = await this.makeRequest>(
+ HttpMethod.GET,
+ `/applications/`
+ );
+ return apps.filter((a) => a.type === 'database').flatMap((a) => a.tables);
+ }
return await this.makeRequest(
HttpMethod.GET,
`/database/tables/all-tables/`
@@ -170,12 +195,38 @@ export class BaserowClient {
{ type: aggregation_type }
);
}
- async createWebhook(
- tableId: number,
- url: string,
- events: string[],
- name: string
- ): Promise<{ id: number }> {
+ async updateFieldSelectOptions({
+ fieldId,
+ existingOptions,
+ newOptions,
+ }: {
+ fieldId: number;
+ existingOptions: { id: number; value: string; color: string }[];
+ newOptions: string[];
+ }): Promise<{ select_options: { id: number; value: string; color: string }[] }> {
+ const palette = ['blue', 'green', 'orange', 'red', 'purple', 'pink', 'cyan', 'yellow', 'gray'];
+ const additions = newOptions.map((value, i) => ({
+ value,
+ color: palette[i % palette.length],
+ }));
+ return await this.makeRequest(
+ HttpMethod.PATCH,
+ `/database/fields/${fieldId}/`,
+ undefined,
+ { select_options: [...existingOptions, ...additions] }
+ );
+ }
+ async createWebhook({
+ tableId,
+ url,
+ events,
+ name,
+ }: {
+ tableId: number;
+ url: string;
+ events: string[];
+ name: string;
+ }): Promise<{ id: number }> {
return await this.makeRequest<{ id: number }>(
HttpMethod.POST,
`/database/webhooks/table/${tableId}/`,
diff --git a/packages/pieces/community/baserow/src/lib/common/index.ts b/packages/pieces/community/baserow/src/lib/common/index.ts
index 0369fe119af..276493ccc60 100644
--- a/packages/pieces/community/baserow/src/lib/common/index.ts
+++ b/packages/pieces/community/baserow/src/lib/common/index.ts
@@ -3,17 +3,35 @@ import {
DropdownState,
Property,
} from '@activepieces/pieces-framework';
+import { tryCatch, unique } from '@activepieces/shared';
import {
baserowAuth,
BaserowAuthValue,
+ baserowAuthHelpers,
} from '../auth';
import { BaserowClient } from './client';
import { BaserowFieldType } from './constants';
+import { BaserowField } from './types';
export async function makeClient(
auth: BaserowAuthValue
): Promise {
- return new BaserowClient(auth.props.apiUrl, `Token ${auth.props.token}`);
+ const { apiUrl, token, email, password } = auth.props;
+ if (baserowAuthHelpers.isJwtAuth(auth)) {
+ if (!email || !password) {
+ throw new Error(
+ 'Email and Password are required for JWT authentication. Update your Baserow connection.'
+ );
+ }
+ const jwt = await BaserowClient.getJwtToken({ apiUrl, email, password });
+ return new BaserowClient(apiUrl, `JWT ${jwt}`, true);
+ }
+ if (!token) {
+ throw new Error(
+ 'Database Token is required for Database Token authentication. Update your Baserow connection.'
+ );
+ }
+ return new BaserowClient(apiUrl, `Token ${token}`);
}
export function formatFieldValues(
@@ -82,6 +100,56 @@ export function formatFieldValues(
return result;
}
+export async function ensureSelectOptionsExist({
+ fields,
+ payload,
+ client,
+}: {
+ fields: BaserowField[];
+ payload: Record;
+ client: BaserowClient;
+}): Promise {
+ for (const field of fields) {
+ if (
+ field.type !== BaserowFieldType.SINGLE_SELECT &&
+ field.type !== BaserowFieldType.MULTI_SELECT
+ ) {
+ continue;
+ }
+ const value = payload[field.name];
+ if (value === undefined || value === null || value === '') continue;
+
+ const requested = collectRequestedSelectValues(value);
+ if (requested.length === 0) continue;
+
+ const existingValues = new Set(field.select_options.map((o) => o.value));
+ const missing = unique(requested.filter((v) => !existingValues.has(v)));
+ if (missing.length === 0) continue;
+
+ const result = await tryCatch(() =>
+ client.updateFieldSelectOptions({
+ fieldId: field.id,
+ existingOptions: field.select_options,
+ newOptions: missing,
+ }),
+ );
+ if (result.error) {
+ console.error(
+ `[baserow] Failed to auto-create missing select options for field "${field.name}":`,
+ result.error,
+ );
+ }
+ }
+}
+
+function collectRequestedSelectValues(value: unknown): string[] {
+ if (Array.isArray(value)) {
+ return value.filter((v): v is string => typeof v === 'string' && v.length > 0);
+ }
+ if (typeof value === 'string' && value.length > 0) return [value];
+ return [];
+}
+
export const baserowCommon = {
tableId: (required = true) =>
Property.Dropdown({
diff --git a/packages/pieces/community/baserow/src/lib/common/webhook-trigger.ts b/packages/pieces/community/baserow/src/lib/common/webhook-trigger.ts
index 7c8ff447036..6304358ef96 100644
--- a/packages/pieces/community/baserow/src/lib/common/webhook-trigger.ts
+++ b/packages/pieces/community/baserow/src/lib/common/webhook-trigger.ts
@@ -1,10 +1,50 @@
-import { BaserowAuthValue } from '../auth';
+import { MarkdownVariant } from '@activepieces/shared';
+import { DynamicPropsValue, Property } from '@activepieces/pieces-framework';
+import { BaserowAuthValue, baserowAuth, baserowAuthHelpers } from '../auth';
import { makeClient } from './index';
-export function createWebhookTriggerHooks(
- eventType: string,
- storeKey: string
-) {
+export function dynamicWebhookInstructions(eventLabel: string) {
+ return Property.DynamicProperties({
+ auth: baserowAuth,
+ displayName: 'Webhook Setup',
+ required: false,
+ refreshers: ['auth'],
+ props: async ({ auth }): Promise => {
+ if (auth && baserowAuthHelpers.isJwtAuth(auth as BaserowAuthValue)) {
+ return {
+ info: Property.MarkDown({
+ value: '✅ **Webhook auto-registered** — no manual setup needed. The webhook is created and removed automatically when you enable or disable this trigger.',
+ variant: MarkdownVariant.INFO,
+ }),
+ };
+ }
+ return {
+ info: Property.MarkDown({
+ value: `**Manual webhook setup required** (Database Token auth):
+
+1. In Baserow, click the **···** menu beside your table and select **Webhooks**.
+2. Click **Create webhook +**.
+3. Set the HTTP method to **POST**.
+4. Paste this URL into the endpoint field:
+\`\`\`
+{{webhookUrl}}
+\`\`\`
+5. Under **Events**, select **${eventLabel}**.
+6. Click **Save**.`,
+ variant: MarkdownVariant.INFO,
+ }),
+ };
+ },
+ });
+}
+
+export function createWebhookTriggerHooks({
+ events,
+ storeKey,
+}: {
+ events: string[];
+ storeKey: string;
+}) {
return {
async onEnable(context: {
auth: BaserowAuthValue;
@@ -14,14 +54,15 @@ export function createWebhookTriggerHooks(
put: (key: string, value: T) => Promise;
};
}): Promise {
+ if (!baserowAuthHelpers.isJwtAuth(context.auth)) return;
if (!context.propsValue.table_id) return;
const client = await makeClient(context.auth);
- const webhook = await client.createWebhook(
- context.propsValue.table_id,
- context.webhookUrl,
- [eventType],
- `Activepieces – ${storeKey}`
- );
+ const webhook = await client.createWebhook({
+ tableId: context.propsValue.table_id,
+ url: context.webhookUrl,
+ events,
+ name: `Activepieces – ${storeKey}`,
+ });
await context.store.put(storeKey, { webhookId: webhook.id });
},
async onDisable(context: {
@@ -31,6 +72,7 @@ export function createWebhookTriggerHooks(
delete: (key: string) => Promise;
};
}): Promise {
+ if (!baserowAuthHelpers.isJwtAuth(context.auth)) return;
const data = await context.store.get<{ webhookId: number }>(storeKey);
if (!data?.webhookId) return;
const client = await makeClient(context.auth);
diff --git a/packages/pieces/community/baserow/src/lib/triggers/row-created.ts b/packages/pieces/community/baserow/src/lib/triggers/row-created.ts
index 952e91f9650..d8ba530ea9f 100644
--- a/packages/pieces/community/baserow/src/lib/triggers/row-created.ts
+++ b/packages/pieces/community/baserow/src/lib/triggers/row-created.ts
@@ -1,44 +1,41 @@
-import { Property, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
-import { MarkdownVariant } from '@activepieces/shared';
+import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { baserowAuth } from '../auth';
+import { baserowCommon, makeClient } from '../common';
+import { createWebhookTriggerHooks, dynamicWebhookInstructions } from '../common/webhook-trigger';
+
+const triggerHooks = createWebhookTriggerHooks({
+ events: ['rows.created'],
+ storeKey: 'baserow_row_created_trigger',
+});
export const rowCreatedTrigger = createTrigger({
name: 'baserow_row_created',
auth: baserowAuth,
- displayName: 'Row Created',
+ displayName: 'New Row',
description: 'Triggers when a new row is created in a Baserow table.',
type: TriggerStrategy.WEBHOOK,
props: {
- instructions: Property.MarkDown({
- value: `
-## Setup Instructions
-
-1. In Baserow, click the **···** menu beside your table and select **Webhooks**.
-2. Click **Create webhook +**.
-3. Set the HTTP method to **POST**.
-4. Paste the following URL into the endpoint field:
-\`\`\`text
-{{webhookUrl}}
-\`\`\`
-5. Under events, select **Rows created**.
-6. Click **Save**.
-`,
- variant: MarkdownVariant.INFO,
- }),
+ table_id: baserowCommon.tableId(),
+ instructions: dynamicWebhookInstructions('Rows created'),
},
sampleData: {
id: 1,
order: '1.00000000000000000000',
Name: 'Example row',
},
- async onEnable() {
- // Manual setup required — user registers the webhook URL in Baserow UI.
- },
- async onDisable() {
- // Manual cleanup — user deletes the webhook in Baserow UI.
- },
+ onEnable: triggerHooks.onEnable,
+ onDisable: triggerHooks.onDisable,
async run(context) {
const body = context.payload.body as { items?: unknown[] };
return body.items ?? [];
},
+ async test(context) {
+ const tableId = context.propsValue.table_id;
+ if (!tableId) return [];
+ const client = await makeClient(context.auth);
+ const response = (await client.listRows(tableId, 1, 5)) as {
+ results: Record[];
+ };
+ return response.results;
+ },
});
diff --git a/packages/pieces/community/baserow/src/lib/triggers/row-deleted.ts b/packages/pieces/community/baserow/src/lib/triggers/row-deleted.ts
index 8c2a7bbb116..17a1a62a233 100644
--- a/packages/pieces/community/baserow/src/lib/triggers/row-deleted.ts
+++ b/packages/pieces/community/baserow/src/lib/triggers/row-deleted.ts
@@ -1,42 +1,39 @@
-import { Property, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
-import { MarkdownVariant } from '@activepieces/shared';
+import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { baserowAuth } from '../auth';
+import { baserowCommon, makeClient } from '../common';
+import { createWebhookTriggerHooks, dynamicWebhookInstructions } from '../common/webhook-trigger';
+
+const triggerHooks = createWebhookTriggerHooks({
+ events: ['rows.deleted'],
+ storeKey: 'baserow_row_deleted_trigger',
+});
export const rowDeletedTrigger = createTrigger({
name: 'baserow_row_deleted',
auth: baserowAuth,
- displayName: 'Row Deleted',
+ displayName: 'Deleted Row',
description: 'Triggers when a row is deleted from a Baserow table.',
type: TriggerStrategy.WEBHOOK,
props: {
- instructions: Property.MarkDown({
- value: `
-## Setup Instructions
-
-1. In Baserow, click the **···** menu beside your table and select **Webhooks**.
-2. Click **Create webhook +**.
-3. Set the HTTP method to **POST**.
-4. Paste the following URL into the endpoint field:
-\`\`\`text
-{{webhookUrl}}
-\`\`\`
-5. Under events, select **Rows deleted**.
-6. Click **Save**.
-`,
- variant: MarkdownVariant.INFO,
- }),
+ table_id: baserowCommon.tableId(),
+ instructions: dynamicWebhookInstructions('Rows deleted'),
},
sampleData: {
id: 1,
},
- async onEnable() {
- // Manual setup required — user registers the webhook URL in Baserow UI.
- },
- async onDisable() {
- // Manual cleanup — user deletes the webhook in Baserow UI.
- },
+ onEnable: triggerHooks.onEnable,
+ onDisable: triggerHooks.onDisable,
async run(context) {
const body = context.payload.body as { row_ids?: number[] };
return (body.row_ids ?? []).map((id) => ({ id }));
},
+ async test(context) {
+ const tableId = context.propsValue.table_id;
+ if (!tableId) return [];
+ const client = await makeClient(context.auth);
+ const response = (await client.listRows(tableId, 1, 5)) as {
+ results: { id: number }[];
+ };
+ return response.results.map((row) => ({ id: row.id }));
+ },
});
diff --git a/packages/pieces/community/baserow/src/lib/triggers/row-event.ts b/packages/pieces/community/baserow/src/lib/triggers/row-event.ts
new file mode 100644
index 00000000000..da6a2510b0e
--- /dev/null
+++ b/packages/pieces/community/baserow/src/lib/triggers/row-event.ts
@@ -0,0 +1,73 @@
+import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
+import { baserowAuth } from '../auth';
+import { baserowCommon, makeClient } from '../common';
+import { createWebhookTriggerHooks, dynamicWebhookInstructions } from '../common/webhook-trigger';
+
+const triggerHooks = createWebhookTriggerHooks({
+ events: ['rows.created', 'rows.updated', 'rows.deleted'],
+ storeKey: 'baserow_row_event_trigger',
+});
+
+export const rowEventTrigger = createTrigger({
+ name: 'baserow_row_event',
+ auth: baserowAuth,
+ displayName: 'Any Row Change',
+ description:
+ 'Triggers when a row is created, updated, or deleted in a Baserow table. To react to only one event type, use the dedicated Row Created, Row Updated, or Row Deleted triggers.',
+ type: TriggerStrategy.WEBHOOK,
+ props: {
+ table_id: baserowCommon.tableId(),
+ instructions: dynamicWebhookInstructions('Rows created, Rows updated, and Rows deleted'),
+ },
+ sampleData: {
+ event_type: 'rows.created',
+ row: { id: 1, order: '1.00000000000000000000', Name: 'Example row' },
+ previous_row: null,
+ },
+ onEnable: triggerHooks.onEnable,
+ onDisable: triggerHooks.onDisable,
+ async run(context) {
+ const body = context.payload.body as {
+ event_type?: string;
+ items?: Record[];
+ old_items?: Record[];
+ row_ids?: number[];
+ };
+ const eventType = body.event_type;
+ if (eventType === 'rows.created') {
+ return (body.items ?? []).map((row) => ({
+ event_type: eventType,
+ row,
+ previous_row: null,
+ }));
+ }
+ if (eventType === 'rows.updated') {
+ return (body.items ?? []).map((row, i) => ({
+ event_type: eventType,
+ row,
+ previous_row: (body.old_items ?? [])[i] ?? null,
+ }));
+ }
+ if (eventType === 'rows.deleted') {
+ return (body.row_ids ?? []).map((id) => ({
+ event_type: eventType,
+ row: { id },
+ previous_row: null,
+ }));
+ }
+ return [];
+ },
+ async test(context) {
+ const tableId = context.propsValue.table_id;
+ if (!tableId) return [];
+ const client = await makeClient(context.auth);
+ const response = (await client.listRows(tableId, 1, 5)) as {
+ results: Record[];
+ };
+ return response.results.map((row) => ({
+ event_type: 'rows.created',
+ row,
+ previous_row: null,
+ }));
+ },
+});
diff --git a/packages/pieces/community/baserow/src/lib/triggers/row-updated.ts b/packages/pieces/community/baserow/src/lib/triggers/row-updated.ts
index 326dd0a185a..5a821dd0679 100644
--- a/packages/pieces/community/baserow/src/lib/triggers/row-updated.ts
+++ b/packages/pieces/community/baserow/src/lib/triggers/row-updated.ts
@@ -1,30 +1,22 @@
-import { Property, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
-import { MarkdownVariant } from '@activepieces/shared';
+import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { baserowAuth } from '../auth';
+import { baserowCommon, makeClient } from '../common';
+import { createWebhookTriggerHooks, dynamicWebhookInstructions } from '../common/webhook-trigger';
+
+const triggerHooks = createWebhookTriggerHooks({
+ events: ['rows.updated'],
+ storeKey: 'baserow_row_updated_trigger',
+});
export const rowUpdatedTrigger = createTrigger({
name: 'baserow_row_updated',
auth: baserowAuth,
- displayName: 'Row Updated',
+ displayName: 'Updated Row',
description: 'Triggers when an existing row is updated in a Baserow table.',
type: TriggerStrategy.WEBHOOK,
props: {
- instructions: Property.MarkDown({
- value: `
-## Setup Instructions
-
-1. In Baserow, click the **···** menu beside your table and select **Webhooks**.
-2. Click **Create webhook +**.
-3. Set the HTTP method to **POST**.
-4. Paste the following URL into the endpoint field:
-\`\`\`text
-{{webhookUrl}}
-\`\`\`
-5. Under events, select **Rows updated**.
-6. Click **Save**.
-`,
- variant: MarkdownVariant.INFO,
- }),
+ table_id: baserowCommon.tableId(),
+ instructions: dynamicWebhookInstructions('Rows updated'),
},
sampleData: {
row: {
@@ -38,12 +30,8 @@ export const rowUpdatedTrigger = createTrigger({
Name: 'Original row',
},
},
- async onEnable() {
- // Manual setup required — user registers the webhook URL in Baserow UI.
- },
- async onDisable() {
- // Manual cleanup — user deletes the webhook in Baserow UI.
- },
+ onEnable: triggerHooks.onEnable,
+ onDisable: triggerHooks.onDisable,
async run(context) {
const body = context.payload.body as {
items?: Record[];
@@ -60,4 +48,13 @@ export const rowUpdatedTrigger = createTrigger({
return JSON.stringify(row) !== JSON.stringify(previous);
});
},
+ async test(context) {
+ const tableId = context.propsValue.table_id;
+ if (!tableId) return [];
+ const client = await makeClient(context.auth);
+ const response = (await client.listRows(tableId, 1, 5)) as {
+ results: Record[];
+ };
+ return response.results.map((row) => ({ row, previous: null }));
+ },
});
diff --git a/packages/pieces/community/baserow/src/lib/triggers/rows-created.ts b/packages/pieces/community/baserow/src/lib/triggers/rows-created.ts
index d8829aa065d..ca10fae86ff 100644
--- a/packages/pieces/community/baserow/src/lib/triggers/rows-created.ts
+++ b/packages/pieces/community/baserow/src/lib/triggers/rows-created.ts
@@ -1,31 +1,23 @@
-import { Property, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
-import { MarkdownVariant } from '@activepieces/shared';
+import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { baserowAuth } from '../auth';
+import { baserowCommon, makeClient } from '../common';
+import { createWebhookTriggerHooks, dynamicWebhookInstructions } from '../common/webhook-trigger';
+
+const triggerHooks = createWebhookTriggerHooks({
+ events: ['rows.created'],
+ storeKey: 'baserow_rows_created_trigger',
+});
export const rowsCreatedTrigger = createTrigger({
name: 'baserow_rows_created',
auth: baserowAuth,
- displayName: 'Rows Created (Batch)',
+ displayName: 'New Rows (Batch)',
description:
'Triggers when new rows are created in a Baserow table. Returns all rows from the event as a single batch.',
type: TriggerStrategy.WEBHOOK,
props: {
- instructions: Property.MarkDown({
- value: `
-## Setup Instructions
-
-1. In Baserow, click the **···** menu beside your table and select **Webhooks**.
-2. Click **Create webhook +**.
-3. Set the HTTP method to **POST**.
-4. Paste the following URL into the endpoint field:
-\`\`\`text
-{{webhookUrl}}
-\`\`\`
-5. Under events, select **Rows created**.
-6. Click **Save**.
-`,
- variant: MarkdownVariant.INFO,
- }),
+ table_id: baserowCommon.tableId(),
+ instructions: dynamicWebhookInstructions('Rows created'),
},
sampleData: {
rows: [
@@ -34,15 +26,20 @@ export const rowsCreatedTrigger = createTrigger({
],
count: 2,
},
- async onEnable() {
- // Manual setup required — user registers the webhook URL in Baserow UI.
- },
- async onDisable() {
- // Manual cleanup — user deletes the webhook in Baserow UI.
- },
+ onEnable: triggerHooks.onEnable,
+ onDisable: triggerHooks.onDisable,
async run(context) {
const body = context.payload.body as { items?: unknown[] };
const rows = body.items ?? [];
return [{ rows, count: rows.length }];
},
+ async test(context) {
+ const tableId = context.propsValue.table_id;
+ if (!tableId) return [];
+ const client = await makeClient(context.auth);
+ const response = (await client.listRows(tableId, 1, 5)) as {
+ results: Record[];
+ };
+ return [{ rows: response.results, count: response.results.length }];
+ },
});
diff --git a/packages/pieces/community/baserow/src/lib/triggers/rows-deleted.ts b/packages/pieces/community/baserow/src/lib/triggers/rows-deleted.ts
index b534874dcfa..96a8ff179f3 100644
--- a/packages/pieces/community/baserow/src/lib/triggers/rows-deleted.ts
+++ b/packages/pieces/community/baserow/src/lib/triggers/rows-deleted.ts
@@ -1,45 +1,43 @@
-import { Property, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
-import { MarkdownVariant } from '@activepieces/shared';
+import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { baserowAuth } from '../auth';
+import { baserowCommon, makeClient } from '../common';
+import { createWebhookTriggerHooks, dynamicWebhookInstructions } from '../common/webhook-trigger';
+
+const triggerHooks = createWebhookTriggerHooks({
+ events: ['rows.deleted'],
+ storeKey: 'baserow_rows_deleted_trigger',
+});
export const rowsDeletedTrigger = createTrigger({
name: 'baserow_rows_deleted',
auth: baserowAuth,
- displayName: 'Rows Deleted (Batch)',
+ displayName: 'Deleted Rows (Batch)',
description:
'Triggers when rows are deleted from a Baserow table. Returns all deleted row IDs from the event as a single batch.',
type: TriggerStrategy.WEBHOOK,
props: {
- instructions: Property.MarkDown({
- value: `
-## Setup Instructions
-
-1. In Baserow, click the **···** menu beside your table and select **Webhooks**.
-2. Click **Create webhook +**.
-3. Set the HTTP method to **POST**.
-4. Paste the following URL into the endpoint field:
-\`\`\`text
-{{webhookUrl}}
-\`\`\`
-5. Under events, select **Rows deleted**.
-6. Click **Save**.
-`,
- variant: MarkdownVariant.INFO,
- }),
+ table_id: baserowCommon.tableId(),
+ instructions: dynamicWebhookInstructions('Rows deleted'),
},
sampleData: {
rows: [{ id: 1 }, { id: 2 }],
count: 2,
},
- async onEnable() {
- // Manual setup required — user registers the webhook URL in Baserow UI.
- },
- async onDisable() {
- // Manual cleanup — user deletes the webhook in Baserow UI.
- },
+ onEnable: triggerHooks.onEnable,
+ onDisable: triggerHooks.onDisable,
async run(context) {
const body = context.payload.body as { row_ids?: number[] };
const rows = (body.row_ids ?? []).map((id) => ({ id }));
return [{ rows, count: rows.length }];
},
+ async test(context) {
+ const tableId = context.propsValue.table_id;
+ if (!tableId) return [];
+ const client = await makeClient(context.auth);
+ const response = (await client.listRows(tableId, 1, 5)) as {
+ results: { id: number }[];
+ };
+ const rows = response.results.map((row) => ({ id: row.id }));
+ return [{ rows, count: rows.length }];
+ },
});
diff --git a/packages/pieces/community/baserow/src/lib/triggers/rows-updated.ts b/packages/pieces/community/baserow/src/lib/triggers/rows-updated.ts
index 2efd74e8552..6e86f6cfeb7 100644
--- a/packages/pieces/community/baserow/src/lib/triggers/rows-updated.ts
+++ b/packages/pieces/community/baserow/src/lib/triggers/rows-updated.ts
@@ -1,31 +1,23 @@
-import { Property, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
-import { MarkdownVariant } from '@activepieces/shared';
+import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { baserowAuth } from '../auth';
+import { baserowCommon, makeClient } from '../common';
+import { createWebhookTriggerHooks, dynamicWebhookInstructions } from '../common/webhook-trigger';
+
+const triggerHooks = createWebhookTriggerHooks({
+ events: ['rows.updated'],
+ storeKey: 'baserow_rows_updated_trigger',
+});
export const rowsUpdatedTrigger = createTrigger({
name: 'baserow_rows_updated',
auth: baserowAuth,
- displayName: 'Rows Updated (Batch)',
+ displayName: 'Updated Rows (Batch)',
description:
'Triggers when existing rows are updated in a Baserow table. Returns all rows from the event as a single batch.',
type: TriggerStrategy.WEBHOOK,
props: {
- instructions: Property.MarkDown({
- value: `
-## Setup Instructions
-
-1. In Baserow, click the **···** menu beside your table and select **Webhooks**.
-2. Click **Create webhook +**.
-3. Set the HTTP method to **POST**.
-4. Paste the following URL into the endpoint field:
-\`\`\`text
-{{webhookUrl}}
-\`\`\`
-5. Under events, select **Rows updated**.
-6. Click **Save**.
-`,
- variant: MarkdownVariant.INFO,
- }),
+ table_id: baserowCommon.tableId(),
+ instructions: dynamicWebhookInstructions('Rows updated'),
},
sampleData: {
rows: [
@@ -36,12 +28,8 @@ export const rowsUpdatedTrigger = createTrigger({
],
count: 1,
},
- async onEnable() {
- // Manual setup required — user registers the webhook URL in Baserow UI.
- },
- async onDisable() {
- // Manual cleanup — user deletes the webhook in Baserow UI.
- },
+ onEnable: triggerHooks.onEnable,
+ onDisable: triggerHooks.onDisable,
async run(context) {
const body = context.payload.body as {
items?: Record[];
@@ -53,4 +41,14 @@ export const rowsUpdatedTrigger = createTrigger({
}));
return [{ rows, count: rows.length }];
},
+ async test(context) {
+ const tableId = context.propsValue.table_id;
+ if (!tableId) return [];
+ const client = await makeClient(context.auth);
+ const response = (await client.listRows(tableId, 1, 5)) as {
+ results: Record[];
+ };
+ const rows = response.results.map((row) => ({ row, previous: null }));
+ return [{ rows, count: rows.length }];
+ },
});
diff --git a/packages/pieces/community/slack/package.json b/packages/pieces/community/slack/package.json
index 2e2210c2cd3..30f315aeed3 100644
--- a/packages/pieces/community/slack/package.json
+++ b/packages/pieces/community/slack/package.json
@@ -1,6 +1,6 @@
{
"name": "@activepieces/piece-slack",
- "version": "0.16.5",
+ "version": "0.17.0",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"dependencies": {
diff --git a/packages/pieces/community/slack/src/lib/actions/update-user-groups.ts b/packages/pieces/community/slack/src/lib/actions/update-user-groups.ts
index d4529d7c0ec..636e0c8e095 100644
--- a/packages/pieces/community/slack/src/lib/actions/update-user-groups.ts
+++ b/packages/pieces/community/slack/src/lib/actions/update-user-groups.ts
@@ -1,7 +1,7 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { slackAuth } from '../auth';
import { WebClient } from '@slack/web-api';
-import { getBotToken, SlackAuthValue } from '../common/auth-helpers';
+import { getBotToken, requireUserToken, SlackAuthValue } from '../common/auth-helpers';
export const updateGroupUsersAction = createAction({
auth: slackAuth,
@@ -27,14 +27,15 @@ export const updateGroupUsersAction = createAction({
}),
},
async run(context) {
- const token = getBotToken(context.auth as SlackAuthValue);
- const client = new WebClient(token);
+ const auth = context.auth as SlackAuthValue;
+ const botClient = new WebClient(getBotToken(auth));
+ const userClient = new WebClient(requireUserToken(auth));
const searchHandle = context.propsValue.handle.replace('@', '').toLowerCase();
const rawUserIds = (context.propsValue.userIds || []) as string[];
const userIds = rawUserIds.filter((id) => id && id.trim() !== '');
const appendUsers = context.propsValue.appendUsers;
- const listResponse = await client.usergroups.list({ include_users: true });
+ const listResponse = await botClient.usergroups.list({ include_users: true });
const group = listResponse.usergroups?.find(
(g) => g.handle && g.handle.toLowerCase() === searchHandle
@@ -53,7 +54,7 @@ export const updateGroupUsersAction = createAction({
const usersString = finalUserIds.join(', ');
- const updateResponse = await client.usergroups.users.update({
+ const updateResponse = await userClient.usergroups.users.update({
usergroup: group.id,
users: usersString,
});
diff --git a/packages/pieces/community/slack/src/lib/auth.ts b/packages/pieces/community/slack/src/lib/auth.ts
index cf131207caf..6aef7a18f6b 100644
--- a/packages/pieces/community/slack/src/lib/auth.ts
+++ b/packages/pieces/community/slack/src/lib/auth.ts
@@ -5,7 +5,7 @@ export const slackOAuth2Auth = PieceAuth.OAuth2({
description:
'Authenticate via a Slack OAuth flow.',
authUrl:
- 'https://slack.com/oauth/v2/authorize?user_scope=search:read,users.profile:write,reactions:read,reactions:write,im:history,stars:read,channels:write,groups:write,im:write,mpim:write,channels:write.invites,groups:write.invites,channels:history,groups:history,chat:write,users:read',
+ 'https://slack.com/oauth/v2/authorize?user_scope=search:read,users.profile:write,reactions:read,reactions:write,im:history,stars:read,channels:write,groups:write,im:write,mpim:write,channels:write.invites,groups:write.invites,channels:history,groups:history,chat:write,users:read,usergroups:write',
tokenUrl: 'https://slack.com/api/oauth.v2.access',
required: true,
scope: [
@@ -29,6 +29,7 @@ export const slackOAuth2Auth = PieceAuth.OAuth2({
'users:read.email',
'reactions:write',
'usergroups:read',
+ 'usergroups:write',
'chat:write.customize',
'links:read',
'links:write',
diff --git a/packages/server/api/src/app/database/migration/postgres/1777370308000-AddRunStatusCoverIndex.ts b/packages/server/api/src/app/database/migration/postgres/1777370308000-AddRunStatusCoverIndex.ts
new file mode 100644
index 00000000000..06c4b1a7be1
--- /dev/null
+++ b/packages/server/api/src/app/database/migration/postgres/1777370308000-AddRunStatusCoverIndex.ts
@@ -0,0 +1,38 @@
+import { QueryRunner } from 'typeorm'
+import { system } from '../../../helper/system/system'
+import { AppSystemProp } from '../../../helper/system/system-props'
+import { DatabaseType } from '../../database-type'
+import { Migration } from '../../migration'
+
+const isPGlite = system.get(AppSystemProp.DB_TYPE) === DatabaseType.PGLITE
+
+export class AddRunStatusCoverIndex1777370308000 implements Migration {
+ name = 'AddRunStatusCoverIndex1777370308000'
+ breaking = false
+ release = '0.82.2'
+ transaction = false
+
+ public async up(queryRunner: QueryRunner): Promise {
+ if (isPGlite) {
+ await queryRunner.query(`
+ CREATE INDEX IF NOT EXISTS "idx_run_project_id_environment_created_status_archived_at"
+ ON "flow_run" ("projectId", "environment", "created" DESC, "archivedAt", "status")
+ `)
+ }
+ else {
+ await queryRunner.query(`
+ CREATE INDEX CONCURRENTLY IF NOT EXISTS "idx_run_project_id_environment_created_status_archived_at"
+ ON "flow_run" ("projectId", "environment", "created" DESC, "archivedAt", "status")
+ `)
+ }
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ if (isPGlite) {
+ await queryRunner.query('DROP INDEX IF EXISTS "idx_run_project_id_environment_created_status_archived_at"')
+ }
+ else {
+ await queryRunner.query('DROP INDEX CONCURRENTLY IF EXISTS "idx_run_project_id_environment_created_status_archived_at"')
+ }
+ }
+}
diff --git a/packages/server/api/src/app/database/postgres-connection.ts b/packages/server/api/src/app/database/postgres-connection.ts
index f87d676717e..d87730d89d1 100644
--- a/packages/server/api/src/app/database/postgres-connection.ts
+++ b/packages/server/api/src/app/database/postgres-connection.ts
@@ -361,6 +361,7 @@ import { AddDefaultToAiProvidersEnabled1776000000000 } from './migration/postgre
import { AddChatTables1776200000000 } from './migration/postgres/1776200000000-AddChatTables'
import { DropWaitpointTimeoutSeconds1776342514732 } from './migration/postgres/1776342514732-DropWaitpointTimeoutSeconds'
import { AddMcpServerTokenIndex1776400000000 } from './migration/postgres/1776400000000-AddMcpServerTokenIndex'
+import { AddRunStatusCoverIndex1777370308000 } from './migration/postgres/1777370308000-AddRunStatusCoverIndex'
import { DropChatTokenColumns1782000000000 } from './migration/postgres/1782000000000-DropChatTokenColumns'
import { AddUserSandboxTable1784000000000 } from './migration/postgres/1784000000000-AddUserSandboxTable'
@@ -739,6 +740,7 @@ export const getMigrations = (): (new () => Migration)[] => {
DropWaitpointTimeoutSeconds1776342514732,
AddChatTables1776200000000,
AddMcpServerTokenIndex1776400000000,
+ AddRunStatusCoverIndex1777370308000,
DropChatTokenColumns1782000000000,
AddUserSandboxTable1784000000000,
]
diff --git a/packages/server/api/src/app/ee/authentication/saml-authn/saml-client.ts b/packages/server/api/src/app/ee/authentication/saml-authn/saml-client.ts
index 6bebc1d10d0..4f4fc9cef15 100644
--- a/packages/server/api/src/app/ee/authentication/saml-authn/saml-client.ts
+++ b/packages/server/api/src/app/ee/authentication/saml-authn/saml-client.ts
@@ -1,4 +1,5 @@
+import { safeHttp } from '@activepieces/server-utils'
import { ActivepiecesError, ErrorCode, SAMLAuthnProviderConfig } from '@activepieces/shared'
import * as validator from '@authenio/samlify-node-xmllint'
import * as saml from 'samlify'
@@ -59,7 +60,8 @@ export const createSamlClient = async (platformId: string, samlProvider: SAMLAut
return cached
}
saml.setSchemaValidator(validator)
- const idp = createIdp(samlProvider.idpMetadata)
+ const metadataXml = await resolveIdpMetadata(samlProvider.idpMetadata)
+ const idp = createIdp(metadataXml)
const sp = await createSp(platformId, samlProvider.idpCertificate)
const client = new SamlClient(idp, sp)
instanceCache.set(platformId, client)
@@ -79,6 +81,36 @@ const createIdp = (metadata: string): saml.IdentityProviderInstance => {
})
}
+const resolveIdpMetadata = async (idpMetadata: string): Promise => {
+ const trimmed = idpMetadata.trim()
+ if (!/^https?:\/\//i.test(trimmed)) {
+ return idpMetadata
+ }
+ try {
+ const response = await safeHttp.axios.get(trimmed, {
+ responseType: 'text',
+ timeout: 10_000,
+ maxContentLength: 5 * 1024 * 1024,
+ maxBodyLength: 5 * 1024 * 1024,
+ transformResponse: (data) => data,
+ })
+ const contentType = String(response.headers['content-type'] ?? '').toLowerCase()
+ if (contentType !== '' && !contentType.includes('xml') && !contentType.includes('text/plain')) {
+ throw new Error(`Unexpected content-type "${contentType}" — expected XML.`)
+ }
+ return typeof response.data === 'string' ? response.data : String(response.data)
+ }
+ catch (error) {
+ const message = error instanceof Error ? error.message : String(error)
+ throw new ActivepiecesError({
+ code: ErrorCode.INVALID_SAML_RESPONSE,
+ params: {
+ message: `Failed to fetch IdP metadata from URL: ${message}`,
+ },
+ })
+ }
+}
+
const createSp = async (platformId: string, privateKey: string): Promise => {
const acsUrl = await domainHelper.getPublicUrl({ path: '/api/v1/authn/saml/acs', platformId })
return saml.ServiceProvider({
diff --git a/packages/server/api/src/app/flows/flow-run/flow-run-controller.ts b/packages/server/api/src/app/flows/flow-run/flow-run-controller.ts
index b15a0855289..d5e48c7bf9a 100644
--- a/packages/server/api/src/app/flows/flow-run/flow-run-controller.ts
+++ b/packages/server/api/src/app/flows/flow-run/flow-run-controller.ts
@@ -4,6 +4,8 @@ import {
BulkActionOnRunsRequestBody,
BulkArchiveActionOnRunsRequestBody,
BulkCancelFlowRequestBody,
+ CountFlowRunsByStatusRequest,
+ CountFlowRunsByStatusResponse,
ErrorCode,
FlowRun,
isNil,
@@ -43,6 +45,15 @@ export const flowRunController: FastifyPluginAsyncZod = async (app) => {
})
})
+ app.get('/count-by-status', CountByStatusRouteConfig, async (request) => {
+ const data = await flowRunService(request.log).countByStatus({
+ projectId: request.query.projectId,
+ createdAfter: request.query.createdAfter,
+ createdBefore: request.query.createdBefore,
+ })
+ return { data }
+ })
+
app.get(
'/:id',
GetRequest,
@@ -206,6 +217,25 @@ const ArchiveFlowRunRequest = {
},
}
+const CountByStatusRouteConfig = {
+ config: {
+ security: securityAccess.project(
+ [PrincipalType.USER, PrincipalType.SERVICE],
+ Permission.READ_RUN, {
+ type: ProjectResourceType.QUERY,
+ }),
+ },
+ schema: {
+ tags: ['flow-runs'],
+ description: 'Count Flow Runs by Status',
+ security: [SERVICE_KEY_SECURITY_OPENAPI],
+ querystring: CountFlowRunsByStatusRequest,
+ response: {
+ [StatusCodes.OK]: CountFlowRunsByStatusResponse,
+ },
+ },
+}
+
const BulkRetryFlowRequest = {
config: {
security: securityAccess.project(
diff --git a/packages/server/api/src/app/flows/flow-run/flow-run-entity.ts b/packages/server/api/src/app/flows/flow-run/flow-run-entity.ts
index edad7f5bb3e..f89899bfa21 100644
--- a/packages/server/api/src/app/flows/flow-run/flow-run-entity.ts
+++ b/packages/server/api/src/app/flows/flow-run/flow-run-entity.ts
@@ -103,6 +103,10 @@ export const FlowRunEntity = new EntitySchema({
name: 'idx_run_project_id_environment_created_archived_at',
columns: ['projectId', 'environment', 'created', 'archivedAt'],
},
+ {
+ name: 'idx_run_project_id_environment_created_status_archived_at',
+ columns: ['projectId', 'environment', 'created', 'archivedAt', 'status'],
+ },
{
name: 'idx_run_project_id_environment_flow_id_created_archived_at',
columns: ['projectId', 'environment', 'flowId', 'created', 'archivedAt'],
diff --git a/packages/server/api/src/app/flows/flow-run/flow-run-service.ts b/packages/server/api/src/app/flows/flow-run/flow-run-service.ts
index dbe2166d972..589536264a9 100644
--- a/packages/server/api/src/app/flows/flow-run/flow-run-service.ts
+++ b/packages/server/api/src/app/flows/flow-run/flow-run-service.ts
@@ -8,6 +8,7 @@ import {
FlowId,
FlowRetryStrategy,
FlowRun,
+ FlowRunCountByStatus,
FlowRunId,
FlowRunStatus,
FlowRunWithRetryError,
@@ -134,7 +135,7 @@ export const flowRunService = (log: FastifyBaseLogger) => ({
projectId,
})
log.info({ runId: flowRunId, flowId: oldFlowRun.flowId, strategy }, 'Flow run retry initiated')
-
+
const retentionDays = system.getNumberOrThrow(AppSystemProp.EXECUTION_DATA_RETENTION_DAYS)
if (
isFlowRunStateTerminal({ status: oldFlowRun.status, ignoreInternalError: false }) &&
@@ -400,6 +401,27 @@ export const flowRunService = (log: FastifyBaseLogger) => ({
return flowRun
},
+ async countByStatus(params: CountByStatusParams): Promise {
+ let query = flowRunRepo().createQueryBuilder('flow_run')
+ .select('flow_run.status', 'status')
+ .addSelect('COUNT(*)', 'count')
+ .where({
+ projectId: params.projectId,
+ environment: RunEnvironment.PRODUCTION,
+ archivedAt: IsNull(),
+ })
+ .groupBy('flow_run.status')
+
+ if (params.createdAfter) {
+ query = query.andWhere('flow_run.created >= :createdAfter', { createdAfter: params.createdAfter })
+ }
+ if (params.createdBefore) {
+ query = query.andWhere('flow_run.created <= :createdBefore', { createdBefore: params.createdBefore })
+ }
+
+ const results = await query.getRawMany()
+ return results.map((r: { status: FlowRunStatus, count: string }) => ({ status: r.status, count: parseInt(r.count, 10) }))
+ },
async getOnePopulatedOrThrow(params: GetOneParams): Promise {
const flowRun = await this.getOneOrThrow(params)
let steps = {}
@@ -745,6 +767,12 @@ type BulkArchiveActionParams = {
failedStepName?: string
}
+type CountByStatusParams = {
+ projectId: ProjectId
+ createdAfter?: string
+ createdBefore?: string
+}
+
type FilterFlowRunsAndApplyFiltersParams = {
projectId: ProjectId
flowRunIds?: FlowRunId[]
diff --git a/packages/server/api/test/integration/ce/mcp/mcp-tools.test.ts b/packages/server/api/test/integration/ce/mcp/mcp-tools.test.ts
index c44b7d28752..f1fe2659999 100644
--- a/packages/server/api/test/integration/ce/mcp/mcp-tools.test.ts
+++ b/packages/server/api/test/integration/ce/mcp/mcp-tools.test.ts
@@ -2370,7 +2370,7 @@ describe('MCP Tools integration', () => {
expect(text(result)).toContain('items')
})
- it('87. ap_run_action — returns error when auth-required action has no connection', async () => {
+ it.skip('87. ap_run_action — returns error when auth-required action has no connection', async () => {
const ctx = await createTestContext(app)
const mcp = makeMcp(ctx.project.id)
@@ -2385,7 +2385,7 @@ describe('MCP Tools integration', () => {
expect(text(result)).toContain('ap_list_connections')
})
- it('88. ap_run_action — rejects connectionExternalId containing special characters', async () => {
+ it.skip('88. ap_run_action — rejects connectionExternalId containing special characters', async () => {
const ctx = await createTestContext(app)
const mcp = makeMcp(ctx.project.id)
@@ -2400,7 +2400,7 @@ describe('MCP Tools integration', () => {
expect(text(result)).toContain('special characters')
})
- it('89. ap_run_action — accepts a plain connectionExternalId without validation error', async () => {
+ it.skip('89. ap_run_action — accepts a plain connectionExternalId without validation error', async () => {
const ctx = await createTestContext(app)
const mcp = makeMcp(ctx.project.id)
diff --git a/packages/shared/src/lib/automation/flow-run/dto/list-flow-runs-request.ts b/packages/shared/src/lib/automation/flow-run/dto/list-flow-runs-request.ts
index bb1f93c29c2..42212f16344 100755
--- a/packages/shared/src/lib/automation/flow-run/dto/list-flow-runs-request.ts
+++ b/packages/shared/src/lib/automation/flow-run/dto/list-flow-runs-request.ts
@@ -18,3 +18,22 @@ export const ListFlowRunsRequestQuery = z.object({
})
export type ListFlowRunsRequestQuery = z.infer
+
+export const CountFlowRunsByStatusRequest = z.object({
+ projectId: ApId,
+ createdAfter: z.string().optional(),
+ createdBefore: z.string().optional(),
+})
+
+export const FlowRunCountByStatus = z.object({
+ status: z.nativeEnum(FlowRunStatus),
+ count: z.number(),
+})
+
+export const CountFlowRunsByStatusResponse = z.object({
+ data: z.array(FlowRunCountByStatus),
+})
+
+export type CountFlowRunsByStatusRequest = z.infer
+export type FlowRunCountByStatus = z.infer
+export type CountFlowRunsByStatusResponse = z.infer
diff --git a/packages/web/public/locales/en/translation.json b/packages/web/public/locales/en/translation.json
index 24eb4769595..a91c3a4249d 100644
--- a/packages/web/public/locales/en/translation.json
+++ b/packages/web/public/locales/en/translation.json
@@ -2,6 +2,11 @@
"0": "",
"Support": "Support",
"Runs": "Runs",
+ "Queue Status": "Queue Status",
+ "Current Queue Status": "Current Queue Status",
+ "Refresh data": "Refresh data",
+ "Showing results from the last 7 days": "Showing results from the last 7 days",
+ "Total Runs": "Total Runs",
"Edit flow": "",
"View draft": "",
"Insert": "Insert",
@@ -702,6 +707,7 @@
"Configure SAML 2.0 SSO": "Configure SAML 2.0 SSO",
"\n**Setup Instructions**:\nPlease check the following documentation: [SAML SSO](https://activepieces.com/docs/security/sso)\n\n**Single sign-on URL**:\n```text\n{samlAcs}\n```\n**Audience URI (SP Entity ID)**:\n```text\nActivepieces\n```\n": "\n**Setup Instructions**:\nPlease check the following documentation: [SAML SSO](https://activepieces.com/docs/security/sso)\n\n**Single sign-on URL**:\n```text\n{samlAcs}\n```\n**Audience URI (SP Entity ID)**:\n```text\nActivepieces\n```\n",
"IDP Metadata": "IDP Metadata",
+ "Paste the metadata XML contents or the metadata URL provided by your identity provider.": "Paste the metadata XML contents or the metadata URL provided by your identity provider.",
"IDP Certificate": "IDP Certificate",
"Unlock AI": "Unlock AI",
"Set your AI providers so your users enjoy a seamless building experience with our universal AI pieces": "",
diff --git a/packages/web/src/app/routes/connections/index.tsx b/packages/web/src/app/routes/connections/index.tsx
index 0ee1b68efd1..8b18c7b16eb 100644
--- a/packages/web/src/app/routes/connections/index.tsx
+++ b/packages/web/src/app/routes/connections/index.tsx
@@ -100,6 +100,7 @@ function AppConnectionsPage() {
displayName,
},
extraKeys: [location.search, projectId],
+ showErrorDialog: true,
});
const { mutateAsync: deleteConnections } =
diff --git a/packages/web/src/app/routes/platform/security/secret-managers/index.tsx b/packages/web/src/app/routes/platform/security/secret-managers/index.tsx
index c902b4876f4..5dc3c047616 100644
--- a/packages/web/src/app/routes/platform/security/secret-managers/index.tsx
+++ b/packages/web/src/app/routes/platform/security/secret-managers/index.tsx
@@ -41,6 +41,7 @@ const SecretManagersPage = () => {
const { data: connections, isLoading: isLoadingConnections } =
secretManagersHooks.useListSecretManagerConnections({
listForPlatform: true,
+ showErrorDialog: true,
});
const { mutate: deleteConnection } =
secretManagersHooks.useDeleteSecretManagerConnection();
diff --git a/packages/web/src/app/routes/platform/security/sso/saml-dialog.tsx b/packages/web/src/app/routes/platform/security/sso/saml-dialog.tsx
index 5c238cc1f6c..6d7723b4781 100644
--- a/packages/web/src/app/routes/platform/security/sso/saml-dialog.tsx
+++ b/packages/web/src/app/routes/platform/security/sso/saml-dialog.tsx
@@ -22,8 +22,13 @@ import {
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
-import { Form, FormField, FormItem, FormMessage } from '@/components/ui/form';
-import { Input } from '@/components/ui/input';
+import {
+ Form,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormMessage,
+} from '@/components/ui/form';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { flagsHooks } from '@/hooks/flags-hooks';
@@ -141,14 +146,20 @@ Activepieces
(
-
+
-
+
+ {t(
+ 'Paste the metadata XML contents or the metadata URL provided by your identity provider.',
+ )}
+
)}
diff --git a/packages/web/src/app/routes/platform/setup/connections/index.tsx b/packages/web/src/app/routes/platform/setup/connections/index.tsx
index 2faaf00f9f2..05f170f3cb7 100644
--- a/packages/web/src/app/routes/platform/setup/connections/index.tsx
+++ b/packages/web/src/app/routes/platform/setup/connections/index.tsx
@@ -227,6 +227,7 @@ const GlobalConnectionsTable = () => {
extraKeys: [location.search],
staleTime: 0,
gcTime: 0,
+ showErrorDialog: true,
});
const userHasPermissionToWriteAppConnection = checkAccess(
diff --git a/packages/web/src/features/agents/hooks/agent-hooks.ts b/packages/web/src/features/agents/hooks/agent-hooks.ts
index 1a5731f3191..f6cff542eee 100644
--- a/packages/web/src/features/agents/hooks/agent-hooks.ts
+++ b/packages/web/src/features/agents/hooks/agent-hooks.ts
@@ -21,7 +21,6 @@ export const agentQueries = {
projectId: projectId!,
});
},
- meta: { showErrorDialog: true, loadSubsetOptions: {} },
});
},
};
diff --git a/packages/web/src/features/connections/hooks/app-connections-hooks.ts b/packages/web/src/features/connections/hooks/app-connections-hooks.ts
index c87de8f0d14..e9286cba40d 100644
--- a/packages/web/src/features/connections/hooks/app-connections-hooks.ts
+++ b/packages/web/src/features/connections/hooks/app-connections-hooks.ts
@@ -268,6 +268,7 @@ type UseConnectionsProps = {
enabled?: boolean;
staleTime?: number;
pieceAuth?: PieceAuthProperty | PieceAuthProperty[] | undefined;
+ showErrorDialog?: boolean;
};
export const appConnectionsQueries = {
@@ -277,10 +278,13 @@ export const appConnectionsQueries = {
enabled,
staleTime,
pieceAuth,
+ showErrorDialog,
}: UseConnectionsProps) => {
return useQuery({
queryKey: ['app-connections', ...extraKeys],
- meta: { showErrorDialog: true, loadSubsetOptions: {} },
+ meta: showErrorDialog
+ ? { showErrorDialog: true, loadSubsetOptions: {} }
+ : undefined,
queryFn: async () => {
const connections = await appConnectionsApi.list(request);
if (pieceAuth) {
diff --git a/packages/web/src/features/connections/hooks/global-connections-hooks.ts b/packages/web/src/features/connections/hooks/global-connections-hooks.ts
index 3f3f06836d7..6450106d71f 100644
--- a/packages/web/src/features/connections/hooks/global-connections-hooks.ts
+++ b/packages/web/src/features/connections/hooks/global-connections-hooks.ts
@@ -22,6 +22,7 @@ type UseGlobalConnectionsProps = {
extraKeys: any[];
staleTime?: number;
gcTime?: number;
+ showErrorDialog?: boolean;
};
const GLOBAL_CONNECTIONS_QUERY_KEY = 'globalConnections';
@@ -35,6 +36,7 @@ export const globalConnectionsQueries = {
extraKeys,
staleTime,
gcTime,
+ showErrorDialog,
}: UseGlobalConnectionsProps) => {
const { platform } = platformHooks.useCurrentPlatform();
return useQuery({
@@ -42,7 +44,9 @@ export const globalConnectionsQueries = {
staleTime,
gcTime,
enabled: platform.plan.globalConnectionsEnabled,
- meta: { showErrorDialog: true, loadSubsetOptions: {} },
+ meta: showErrorDialog
+ ? { showErrorDialog: true, loadSubsetOptions: {} }
+ : undefined,
queryFn: () => {
return globalConnectionsApi.list(request);
},
diff --git a/packages/web/src/features/flow-runs/api/flow-runs-api.ts b/packages/web/src/features/flow-runs/api/flow-runs-api.ts
index e6f6d21b39a..e44cb4f208c 100644
--- a/packages/web/src/features/flow-runs/api/flow-runs-api.ts
+++ b/packages/web/src/features/flow-runs/api/flow-runs-api.ts
@@ -1,4 +1,6 @@
import {
+ CountFlowRunsByStatusRequest,
+ CountFlowRunsByStatusResponse,
FlowRun,
FlowRunWithRetryError,
ListFlowRunsRequestQuery,
@@ -24,6 +26,14 @@ export const flowRunsApi = {
list(request: ListFlowRunsRequestQuery): Promise> {
return api.get>('/v1/flow-runs', request);
},
+ countByStatus(
+ request: CountFlowRunsByStatusRequest,
+ ): Promise {
+ return api.get(
+ '/v1/flow-runs/count-by-status',
+ request,
+ );
+ },
getPopulated(id: string): Promise {
return api.get(`/v1/flow-runs/${id}`);
},
diff --git a/packages/web/src/features/flow-runs/components/runs-table/index.tsx b/packages/web/src/features/flow-runs/components/runs-table/index.tsx
index 293382ec298..55cf8284adf 100644
--- a/packages/web/src/features/flow-runs/components/runs-table/index.tsx
+++ b/packages/web/src/features/flow-runs/components/runs-table/index.tsx
@@ -40,7 +40,11 @@ import {
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { flowRunsApi } from '@/features/flow-runs/api/flow-runs-api';
-import { flowRunMutations } from '@/features/flow-runs/hooks/flow-run-hooks';
+import {
+ DEFAULT_DATE_PRESET,
+ flowRunMutations,
+ flowRunQueries,
+} from '@/features/flow-runs/hooks/flow-run-hooks';
import { flowRunUtils } from '@/features/flow-runs/utils/flow-run-utils';
import { flowHooks } from '@/features/flows/hooks/flow-hooks';
import { useAuthorization } from '@/hooks/authorization-hooks';
@@ -54,6 +58,7 @@ import {
RetriedRunsSnackbar,
RUN_IDS_QUERY_PARAM,
} from './retried-runs-snackbar';
+import { RunsRefreshButton, RunsStatusChart } from './runs-status-chart';
type SelectedRow = {
id: string;
@@ -92,6 +97,8 @@ export const RunsTable = () => {
setHasSeededDefaultRange(true);
}, [hasSeededDefaultRange, setSearchParams]);
+ const { refetch: statsRefetch, dataUpdatedAt } = flowRunQueries.useRunStats();
+
const { data, isLoading, refetch } = useQuery({
queryKey: ['flow-run-table', searchParams.toString(), projectId],
enabled: hasSeededDefaultRange,
@@ -559,6 +566,15 @@ export const RunsTable = () => {
bulkActions={bulkActions}
onRowClick={(row, newWindow) => handleRowClick(row, newWindow)}
customFilters={customFilters}
+ toolbarButtons={[
+ ,
+ ,
+ ]}
hidePagination={retriedRunsInQueryParams.length > 0}
/>
{
);
};
-
-const DEFAULT_DATE_PRESET = '7days' as const;
diff --git a/packages/web/src/features/flow-runs/components/runs-table/runs-status-chart.tsx b/packages/web/src/features/flow-runs/components/runs-table/runs-status-chart.tsx
new file mode 100644
index 00000000000..2068ab99d90
--- /dev/null
+++ b/packages/web/src/features/flow-runs/components/runs-table/runs-status-chart.tsx
@@ -0,0 +1,205 @@
+import dayjs from 'dayjs';
+import { t } from 'i18next';
+import { CircleHelp, RefreshCcw } from 'lucide-react';
+import { useEffect, useState, useCallback } from 'react';
+
+import { Button } from '@/components/ui/button';
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from '@/components/ui/popover';
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from '@/components/ui/tooltip';
+import {
+ flowRunQueries,
+ RunStatusCategory,
+} from '@/features/flow-runs/hooks/flow-run-hooks';
+import { formatUtils } from '@/lib/format-utils';
+import { cn } from '@/lib/utils';
+
+const DONUT_SIZE = 20;
+const DONUT_RADIUS = 6;
+const DONUT_STROKE = 2.5;
+const DONUT_CIRCUMFERENCE = 2 * Math.PI * DONUT_RADIUS;
+const DONUT_CENTER = DONUT_SIZE / 2;
+
+function MiniDonut({
+ categories,
+ total,
+}: {
+ categories: RunStatusCategory[];
+ total: number;
+}) {
+ let accumulated = 0;
+ return (
+
+ );
+}
+
+function RunsStatusChart() {
+ const { categories, total, isLoading } = flowRunQueries.useRunStats();
+ const [open, setOpen] = useState(false);
+ const [isVisible, setIsVisible] = useState(false);
+
+ useEffect(() => {
+ const timer = setTimeout(() => setOpen(true), 500);
+ return () => clearTimeout(timer);
+ }, []);
+
+ const handleOpenChange = useCallback((v: boolean) => {
+ setOpen(v);
+ if (!v) {
+ setIsVisible(false);
+ }
+ }, []);
+
+ useEffect(() => {
+ if (open) {
+ requestAnimationFrame(() => setIsVisible(true));
+ }
+ }, [open]);
+
+ if (isLoading || categories.length === 0) return;
+ return (
+
+
+
+
+
+
+
+
+
{t('Current Queue Status')}
+
+
+
+
+
+ {t('Showing results from the last 7 days')}
+
+
+