Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,18 @@
{
"extends": ["../../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-webflow
This library was generated with [Nx](https://nx.dev).
## Running lint
Run `nx lint pieces-webflow` to execute the lint via [ESLint](https://eslint.org/).

View File

@@ -0,0 +1,4 @@
{
"name": "@activepieces/piece-webflow",
"version": "0.1.12"
}

View File

@@ -0,0 +1,51 @@
{
"name": "pieces-webflow",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/webflow/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/webflow",
"tsConfig": "packages/pieces/community/webflow/tsconfig.lib.json",
"packageJson": "packages/pieces/community/webflow/package.json",
"main": "packages/pieces/community/webflow/src/index.ts",
"assets": [
"packages/pieces/community/webflow/*.md",
{
"input": "packages/pieces/community/webflow/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"^build",
"prebuild"
]
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
},
"prebuild": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/webflow",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
},
"tags": []
}

View File

@@ -0,0 +1,58 @@
{
"Webflow": "Webflow",
"Design, build, and launch responsive websites visually": "Design, build, and launch responsive websites visually",
"Create Collection Item": "Create Collection Item",
"Delete an item in a collection": "Delete an item in a collection",
"Update an item in a collection": "Update an item in a collection",
"Find a Collection Item by Field": "Find a Collection Item by Field",
"Get a Collection Item by ID": "Get a Collection Item by ID",
"Fulfill an order": "Fulfill an order",
"Unfulfill an order": "Unfulfill an order",
"Refund an order": "Refund an order",
"Find an order": "Find an order",
"Custom API Call": "Custom API Call",
"Creates new collection item.": "Creates new collection item.",
"Delete collection item": "Delete collection item",
"Update collection item": "Update collection item",
"Find collection item in a collection by field": "Find collection item in a collection by field",
"Get collection item in a collection by ID": "Get collection item in a collection by ID",
"Fulfill order": "Fulfill order",
"Unfulfill order": "Unfulfill order",
"Refund order": "Refund order",
"Find order": "Find order",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Site": "Site",
"Collection": "Collection",
"Collection Fields": "Collection Fields",
"Is Archived": "Is Archived",
"Is Draft": "Is Draft",
"Collection Item": "Collection Item",
"Field Name": "Field Name",
"Field Value": "Field Value",
"Max Results": "Max Results",
"Order": "Order",
"Send Order Fulfilled Email": "Send Order Fulfilled Email",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Whether the item is archived or not": "Whether the item is archived or not",
"Whether the item is a draft or not": "Whether the item is a draft or not",
"The name of the field to search by": "The name of the field to search by",
"The value of the field to search for": "The value of the field to search for",
"The maximum number of results to return": "The maximum number of results to return",
"Send an email to the customer that their order has been fulfilled": "Send an email to the customer that their order has been fulfilled",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Submission": "New Submission",
"Triggers when Webflow Site receives a new submission": "Triggers when Webflow Site receives a new submission",
"Form Name": "Form Name",
"Copy from the form settings, or from one of the responses": "Copy from the form settings, or from one of the responses"
}

View File

@@ -0,0 +1,59 @@
{
"Design, build, and launch responsive websites visually": "Gestalten, Erstellen und Starten von responsive Websites visuell",
"Create Collection Item": "Sammlungsobjekt erstellen",
"Delete an item in a collection": "Ein Element in einer Sammlung löschen",
"Update an item in a collection": "Aktualisiere ein Element in einer Sammlung",
"Find a Collection Item by Field": "Finde ein Sammlungsgegenstand nach Feld",
"Get a Collection Item by ID": "Holen Sie sich ein Sammlungselement per ID",
"Fulfill an order": "Erfüllen Sie eine Bestellung",
"Unfulfill an order": "Bestellung nicht erfüllen",
"Refund an order": "Bestellung zurückerstatten",
"Find an order": "Eine Bestellung suchen",
"Custom API Call": "Eigener API-Aufruf",
"Creates new collection item.": "Erstellt neues Sammlungselement.",
"Delete collection item": "Sammlungselement löschen",
"Update collection item": "Sammlungsgegenstand aktualisieren",
"Find collection item in a collection by field": "Sammlungsgegenstand in einer Sammlung nach Feld finden",
"Get collection item in a collection by ID": "Sammelartikel in einer Sammlung per ID abrufen",
"Fulfill order": "Erfüllungsauftrag",
"Unfulfill order": "Unerfüllte Bestellung",
"Refund order": "Erstattungsauftrag",
"Find order": "Bestellung suchen",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Site": "Site",
"Collection": "Sammlung",
"Collection Fields": "Sammlungsfelder",
"Is Archived": "Ist archiviert",
"Is Draft": "Ist Entwurf",
"Collection Item": "Sammlungsgegenstand",
"Field Name": "Feldname",
"Field Value": "Feldwert",
"Max Results": "Maximale Ergebnisse",
"Order": "Sortierung",
"Send Order Fulfilled Email": "Bestellungsausfüllte E-Mail senden",
"Method": "Methode",
"Headers": "Kopfzeilen",
"Query Parameters": "Abfrageparameter",
"Body": "Körper",
"Response is Binary ?": "Antwort ist binär?",
"No Error on Failure": "Kein Fehler bei Fehler",
"Timeout (in seconds)": "Timeout (in Sekunden)",
"Whether the item is archived or not": "Ob das Element archiviert ist oder nicht",
"Whether the item is a draft or not": "Ob der Artikel ein Entwurf ist oder nicht",
"The name of the field to search by": "Der Name des zu suchenden Feldes",
"The value of the field to search for": "Der Wert des zu suchenden Feldes",
"The maximum number of results to return": "Die maximale Anzahl der zurückzugebenden Ergebnisse",
"Send an email to the customer that their order has been fulfilled": "Senden Sie dem Kunden eine E-Mail, dass seine Bestellung erfüllt wurde",
"Authorization headers are injected automatically from your connection.": "Autorisierungs-Header werden automatisch von Ihrer Verbindung injiziert.",
"Enable for files like PDFs, images, etc..": "Aktivieren für Dateien wie PDFs, Bilder, etc..",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"New Submission": "Neue Einreichung",
"Triggers when Webflow Site receives a new submission": "Auslöser wenn die Webflow Site eine neue Einreichung erhält",
"Form Name": "Formularname",
"Copy from the form settings, or from one of the responses": "Kopieren Sie aus den Formulareinstellungen oder aus einer der Antworten"
}

View File

@@ -0,0 +1,59 @@
{
"Design, build, and launch responsive websites visually": "Diseñar, construir y lanzar sitios web receptivos de forma visual",
"Create Collection Item": "Crear objeto de colección",
"Delete an item in a collection": "Eliminar un elemento de una colección",
"Update an item in a collection": "Actualizar un elemento de una colección",
"Find a Collection Item by Field": "Encuentra un objeto de colección por campo",
"Get a Collection Item by ID": "Obtén un objeto de colección por ID",
"Fulfill an order": "Cumplir un pedido",
"Unfulfill an order": "Incumplir un pedido",
"Refund an order": "Reembolsar un pedido",
"Find an order": "Buscar un pedido",
"Custom API Call": "Llamada API personalizada",
"Creates new collection item.": "Crea nuevo elemento de colección.",
"Delete collection item": "Eliminar elemento de colección",
"Update collection item": "Actualizar elemento de colección",
"Find collection item in a collection by field": "Encontrar elemento de la colección en una colección por campo",
"Get collection item in a collection by ID": "Obtener elemento de colección en una colección por ID",
"Fulfill order": "Completar pedido",
"Unfulfill order": "Incumplir pedido",
"Refund order": "Orden de reembolso",
"Find order": "Buscar pedido",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Site": "Sitio",
"Collection": "Colección",
"Collection Fields": "Campos de colección",
"Is Archived": "Está archivado",
"Is Draft": "Es borrador",
"Collection Item": "Objeto de colección",
"Field Name": "Nombre del campo",
"Field Value": "Valor del campo",
"Max Results": "Resultados máximos",
"Order": "Pedido",
"Send Order Fulfilled Email": "Enviar correo electrónico completado de pedido",
"Method": "Método",
"Headers": "Encabezados",
"Query Parameters": "Parámetros de consulta",
"Body": "Cuerpo",
"Response is Binary ?": "¿Respuesta es binaria?",
"No Error on Failure": "No hay ningún error en fallo",
"Timeout (in seconds)": "Tiempo de espera (en segundos)",
"Whether the item is archived or not": "Si el elemento está archivado o no",
"Whether the item is a draft or not": "Si el elemento es un borrador o no",
"The name of the field to search by": "El nombre del campo a buscar por",
"The value of the field to search for": "El valor del campo a buscar",
"The maximum number of results to return": "El número máximo de resultados a devolver",
"Send an email to the customer that their order has been fulfilled": "Enviar un correo electrónico al cliente que su pedido ha sido completado",
"Authorization headers are injected automatically from your connection.": "Las cabeceras de autorización se inyectan automáticamente desde tu conexión.",
"Enable for files like PDFs, images, etc..": "Activar para archivos como PDFs, imágenes, etc.",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"New Submission": "Nuevo envío",
"Triggers when Webflow Site receives a new submission": "Dispara cuando Webflow Site recibe un nuevo envío",
"Form Name": "Nombre del formulario",
"Copy from the form settings, or from one of the responses": "Copiar desde la configuración del formulario, o desde una de las respuestas"
}

View File

@@ -0,0 +1,59 @@
{
"Design, build, and launch responsive websites visually": "Concevoir, construire et lancer des sites Web réactifs visuellement",
"Create Collection Item": "Créer un élément de collection",
"Delete an item in a collection": "Supprimer un élément d'une collection",
"Update an item in a collection": "Mettre à jour un élément dans une collection",
"Find a Collection Item by Field": "Trouver un élément de collection par champ",
"Get a Collection Item by ID": "Obtenir un élément de collection par ID",
"Fulfill an order": "Compléter une commande",
"Unfulfill an order": "Ne pas remplir une commande",
"Refund an order": "Rembourser une commande",
"Find an order": "Trouver une commande",
"Custom API Call": "Appel d'API personnalisé",
"Creates new collection item.": "Crée un nouvel élément de collection.",
"Delete collection item": "Supprimer l'élément de la collection",
"Update collection item": "Mettre à jour l'élément de collection",
"Find collection item in a collection by field": "Trouver un élément de collection dans une collection par champ",
"Get collection item in a collection by ID": "Obtenir un élément de collection dans une collection par ID",
"Fulfill order": "Compléter la commande",
"Unfulfill order": "Ne pas remplir la commande",
"Refund order": "Commande de remboursement",
"Find order": "Rechercher une commande",
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
"Site": "Site",
"Collection": "Collecte",
"Collection Fields": "Champs de la collection",
"Is Archived": "Est archivé",
"Is Draft": "Est un brouillon",
"Collection Item": "Élément de collection",
"Field Name": "Nom du champ",
"Field Value": "Valeur du champ",
"Max Results": "Nombre maximum de résultats",
"Order": "Commandes",
"Send Order Fulfilled Email": "Envoyer un e-mail de commande rempli",
"Method": "Méthode",
"Headers": "En-têtes",
"Query Parameters": "Paramètres de requête",
"Body": "Corps",
"Response is Binary ?": "La réponse est Binaire ?",
"No Error on Failure": "Aucune erreur en cas d'échec",
"Timeout (in seconds)": "Délai d'expiration (en secondes)",
"Whether the item is archived or not": "Si l'élément est archivé ou non",
"Whether the item is a draft or not": "Si l'élément est un brouillon ou non",
"The name of the field to search by": "Le nom du champ à rechercher par",
"The value of the field to search for": "La valeur du champ à rechercher",
"The maximum number of results to return": "Le nombre maximum de résultats à retourner",
"Send an email to the customer that their order has been fulfilled": "Envoyer un email au client pour lui indiquer que sa commande a été remplie",
"Authorization headers are injected automatically from your connection.": "Les en-têtes d'autorisation sont injectés automatiquement à partir de votre connexion.",
"Enable for files like PDFs, images, etc..": "Activer pour les fichiers comme les PDFs, les images, etc.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Submission": "Nouvelle soumission",
"Triggers when Webflow Site receives a new submission": "Déclenche lorsque Webflow Site reçoit une nouvelle soumission",
"Form Name": "Nom du formulaire",
"Copy from the form settings, or from one of the responses": "Copier depuis les paramètres du formulaire, ou à partir d'une des réponses"
}

View File

@@ -0,0 +1,58 @@
{
"Webflow": "Webflow",
"Design, build, and launch responsive websites visually": "Design, build, and launch responsive websites visually",
"Create Collection Item": "Create Collection Item",
"Delete an item in a collection": "Delete an item in a collection",
"Update an item in a collection": "Update an item in a collection",
"Find a Collection Item by Field": "Find a Collection Item by Field",
"Get a Collection Item by ID": "Get a Collection Item by ID",
"Fulfill an order": "Fulfill an order",
"Unfulfill an order": "Unfulfill an order",
"Refund an order": "Refund an order",
"Find an order": "Find an order",
"Custom API Call": "Custom API Call",
"Creates new collection item.": "Creates new collection item.",
"Delete collection item": "Delete collection item",
"Update collection item": "Update collection item",
"Find collection item in a collection by field": "Find collection item in a collection by field",
"Get collection item in a collection by ID": "Get collection item in a collection by ID",
"Fulfill order": "Fulfill order",
"Unfulfill order": "Unfulfill order",
"Refund order": "Refund order",
"Find order": "Find order",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Site": "Site",
"Collection": "Collection",
"Collection Fields": "Collection Fields",
"Is Archived": "Is Archived",
"Is Draft": "Is Draft",
"Collection Item": "Collection Item",
"Field Name": "Field Name",
"Field Value": "Field Value",
"Max Results": "Max Results",
"Order": "Order",
"Send Order Fulfilled Email": "Send Order Fulfilled Email",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Whether the item is archived or not": "Whether the item is archived or not",
"Whether the item is a draft or not": "Whether the item is a draft or not",
"The name of the field to search by": "The name of the field to search by",
"The value of the field to search for": "The value of the field to search for",
"The maximum number of results to return": "The maximum number of results to return",
"Send an email to the customer that their order has been fulfilled": "Send an email to the customer that their order has been fulfilled",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Submission": "New Submission",
"Triggers when Webflow Site receives a new submission": "Triggers when Webflow Site receives a new submission",
"Form Name": "Form Name",
"Copy from the form settings, or from one of the responses": "Copy from the form settings, or from one of the responses"
}

View File

@@ -0,0 +1,58 @@
{
"Webflow": "Webflow",
"Design, build, and launch responsive websites visually": "Design, build, and launch responsive websites visually",
"Create Collection Item": "Create Collection Item",
"Delete an item in a collection": "Delete an item in a collection",
"Update an item in a collection": "Update an item in a collection",
"Find a Collection Item by Field": "Find a Collection Item by Field",
"Get a Collection Item by ID": "Get a Collection Item by ID",
"Fulfill an order": "Fulfill an order",
"Unfulfill an order": "Unfulfill an order",
"Refund an order": "Refund an order",
"Find an order": "Find an order",
"Custom API Call": "Custom API Call",
"Creates new collection item.": "Creates new collection item.",
"Delete collection item": "Delete collection item",
"Update collection item": "Update collection item",
"Find collection item in a collection by field": "Find collection item in a collection by field",
"Get collection item in a collection by ID": "Get collection item in a collection by ID",
"Fulfill order": "Fulfill order",
"Unfulfill order": "Unfulfill order",
"Refund order": "Refund order",
"Find order": "Find order",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Site": "Site",
"Collection": "Collection",
"Collection Fields": "Collection Fields",
"Is Archived": "Is Archived",
"Is Draft": "Is Draft",
"Collection Item": "Collection Item",
"Field Name": "Field Name",
"Field Value": "Field Value",
"Max Results": "Max Results",
"Order": "Order",
"Send Order Fulfilled Email": "Send Order Fulfilled Email",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Whether the item is archived or not": "Whether the item is archived or not",
"Whether the item is a draft or not": "Whether the item is a draft or not",
"The name of the field to search by": "The name of the field to search by",
"The value of the field to search for": "The value of the field to search for",
"The maximum number of results to return": "The maximum number of results to return",
"Send an email to the customer that their order has been fulfilled": "Send an email to the customer that their order has been fulfilled",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Submission": "New Submission",
"Triggers when Webflow Site receives a new submission": "Triggers when Webflow Site receives a new submission",
"Form Name": "Form Name",
"Copy from the form settings, or from one of the responses": "Copy from the form settings, or from one of the responses"
}

View File

@@ -0,0 +1,59 @@
{
"Design, build, and launch responsive websites visually": "レスポンシブウェブサイトのデザイン、ビルド、起動",
"Create Collection Item": "コレクションアイテムを作成",
"Delete an item in a collection": "コレクション内のアイテムを削除",
"Update an item in a collection": "コレクション内のアイテムを更新",
"Find a Collection Item by Field": "フィールド別にコレクションアイテムを検索",
"Get a Collection Item by ID": "IDでコレクションアイテムを入手",
"Fulfill an order": "注文を実行する",
"Unfulfill an order": "注文を満たしていません",
"Refund an order": "注文を返金する",
"Find an order": "注文を検索",
"Custom API Call": "カスタムAPI通話",
"Creates new collection item.": "新しいコレクションアイテムを作成します。",
"Delete collection item": "コレクションアイテムを削除",
"Update collection item": "コレクションアイテムを更新",
"Find collection item in a collection by field": "フィールド別にコレクションアイテムを検索",
"Get collection item in a collection by ID": "コレクション内のアイテムをIDで取得",
"Fulfill order": "Fulfill order",
"Unfulfill order": "注文を満たしていません",
"Refund order": "払い戻し注文",
"Find order": "注文を検索",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Site": "サイト",
"Collection": "コレクション",
"Collection Fields": "コレクションフィールド",
"Is Archived": "アーカイブ済み",
"Is Draft": "下書きです",
"Collection Item": "コレクションアイテム",
"Field Name": "フィールド名",
"Field Value": "フィールド値",
"Max Results": "最大結果",
"Order": "ご注文",
"Send Order Fulfilled Email": "注文が完了したメールを送信",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Whether the item is archived or not": "アイテムがアーカイブされているかどうか",
"Whether the item is a draft or not": "アイテムがドラフトであるか否か",
"The name of the field to search by": "検索するフィールドの名前",
"The value of the field to search for": "検索するフィールドの値",
"The maximum number of results to return": "返す結果の最大数",
"Send an email to the customer that their order has been fulfilled": "注文が完了したことを顧客にメールで送信する",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"New Submission": "新しい提出",
"Triggers when Webflow Site receives a new submission": "Webflow Site が新しい提出物を受信したときにトリガーします",
"Form Name": "フォーム名",
"Copy from the form settings, or from one of the responses": "フォームの設定から、または応答のいずれかからコピー"
}

View File

@@ -0,0 +1,59 @@
{
"Design, build, and launch responsive websites visually": "Ontwerp, bouw en start responsive websites visueel",
"Create Collection Item": "Collectie item aanmaken",
"Delete an item in a collection": "Verwijder een item uit een collectie",
"Update an item in a collection": "Een item bijwerken in een collectie",
"Find a Collection Item by Field": "Vind een collectie item per veld",
"Get a Collection Item by ID": "Krijg een collectieitem via ID",
"Fulfill an order": "Volgorde voltooien",
"Unfulfill an order": "Voldoen aan een bestelling",
"Refund an order": "Bestelling terugbetalen",
"Find an order": "Zoek een bestelling",
"Custom API Call": "Custom API Call",
"Creates new collection item.": "Maakt nieuw collectie item aan.",
"Delete collection item": "Verzameling item verwijderen",
"Update collection item": "Verzameling bijwerken",
"Find collection item in a collection by field": "Verzamelen vinden in een collectie per veld",
"Get collection item in a collection by ID": "Haal de collectie op in een collectie via ID",
"Fulfill order": "Volgorde afronden",
"Unfulfill order": "Volgorde niet voldoen",
"Refund order": "Restitutie bestelling",
"Find order": "Bestelling zoeken",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Site": "Website",
"Collection": "Collectie",
"Collection Fields": "Collectie velden",
"Is Archived": "Is gearchiveerd",
"Is Draft": "Is concept",
"Collection Item": "Collectie voorwerp",
"Field Name": "Veld naam",
"Field Value": "Veld waarde",
"Max Results": "Max. aantal resultaten",
"Order": "Bestelling",
"Send Order Fulfilled Email": "Verstuur met bestelling gevulde e-mail",
"Method": "Methode",
"Headers": "Kopteksten",
"Query Parameters": "Query parameters",
"Body": "Lichaam",
"Response is Binary ?": "Antwoord is binair?",
"No Error on Failure": "Geen fout bij fout",
"Timeout (in seconds)": "Time-out (in seconden)",
"Whether the item is archived or not": "Of het item is gearchiveerd of niet",
"Whether the item is a draft or not": "Of het artikel een concept is of niet",
"The name of the field to search by": "De naam van het veld waarop gezocht moet worden",
"The value of the field to search for": "De waarde van het veld waarnaar gezocht moet worden",
"The maximum number of results to return": "Het maximale aantal resultaten om terug te sturen",
"Send an email to the customer that their order has been fulfilled": "Stuur een e-mail naar de klant dat zijn bestelling is voldaan",
"Authorization headers are injected automatically from your connection.": "Autorisatie headers worden automatisch geïnjecteerd vanuit uw verbinding.",
"Enable for files like PDFs, images, etc..": "Inschakelen voor bestanden zoals PDF's, afbeeldingen etc..",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"New Submission": "Nieuwe inzending",
"Triggers when Webflow Site receives a new submission": "Triggert wanneer Webflow Site een nieuwe uitwerking ontvangt",
"Form Name": "Formulier naam",
"Copy from the form settings, or from one of the responses": "Kopieer vanuit het formulier instellingen of vanuit een van de antwoorden"
}

View File

@@ -0,0 +1,59 @@
{
"Design, build, and launch responsive websites visually": "Projete, construa e inicia sites responsivos visualmente",
"Create Collection Item": "Criar Item da Coleção",
"Delete an item in a collection": "Deletar um item em uma coleção",
"Update an item in a collection": "Atualizar um item em uma coleção",
"Find a Collection Item by Field": "Encontre um item de coleção por campo",
"Get a Collection Item by ID": "Obter um Item de Coleção por ID",
"Fulfill an order": "Cumprir um pedido",
"Unfulfill an order": "Encadear um pedido",
"Refund an order": "Reembolsar um pedido",
"Find an order": "Encontrar um pedido",
"Custom API Call": "Chamada de API personalizada",
"Creates new collection item.": "Cria um novo item de coleção.",
"Delete collection item": "Excluir item da coleção",
"Update collection item": "Atualizar item de coleção",
"Find collection item in a collection by field": "Encontre o item de coleção em uma coleção por campo",
"Get collection item in a collection by ID": "Obtenha o item de coleção em uma coleção por ID",
"Fulfill order": "Pedido Cumprido",
"Unfulfill order": "Ordem não cumprida",
"Refund order": "Pedido de reembolso",
"Find order": "Encontrar pedido",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Site": "site",
"Collection": "Coleção",
"Collection Fields": "Campos de Coleção",
"Is Archived": "Está arquivado",
"Is Draft": "É rascunho",
"Collection Item": "Item da coleção",
"Field Name": "Nome do campo",
"Field Value": "Valor do Campo",
"Max Results": "Resultados no Máx.",
"Order": "Encomenda",
"Send Order Fulfilled Email": "Encomenda Cumprida de E-mail",
"Method": "Método",
"Headers": "Cabeçalhos",
"Query Parameters": "Parâmetros da consulta",
"Body": "Conteúdo",
"Response is Binary ?": "A resposta é binária ?",
"No Error on Failure": "Nenhum erro no Failure",
"Timeout (in seconds)": "Tempo limite (em segundos)",
"Whether the item is archived or not": "Se o item está arquivado ou não",
"Whether the item is a draft or not": "Se o item é um rascunho ou não",
"The name of the field to search by": "O nome do campo a ser pesquisado por",
"The value of the field to search for": "O valor do campo para procurar",
"The maximum number of results to return": "O número máximo de resultados para retornar",
"Send an email to the customer that their order has been fulfilled": "Envie um e-mail para o cliente que seu pedido foi atendido",
"Authorization headers are injected automatically from your connection.": "Os cabeçalhos de autorização são inseridos automaticamente a partir da sua conexão.",
"Enable for files like PDFs, images, etc..": "Habilitar para arquivos como PDFs, imagens, etc..",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"New Submission": "Nova Submissão",
"Triggers when Webflow Site receives a new submission": "Aciona quando o site receber uma nova submissão",
"Form Name": "Nome do formulário",
"Copy from the form settings, or from one of the responses": "Copiar a partir das configurações do formulário, ou de uma das respostas"
}

View File

@@ -0,0 +1,58 @@
{
"Webflow": "Веб-поток",
"Design, build, and launch responsive websites visually": "Дизайн, построение и запуск чутких веб-сайтов наглядно",
"Create Collection Item": "Создать элемент коллекции",
"Delete an item in a collection": "Удалить элемент в коллекции",
"Update an item in a collection": "Обновить элемент в коллекции",
"Find a Collection Item by Field": "Найти подборку по полю",
"Get a Collection Item by ID": "Получить элемент коллекции по ID",
"Fulfill an order": "Выполнить заказ",
"Unfulfill an order": "Невыполненные заказы",
"Refund an order": "Возврат заказа",
"Find an order": "Найти заказ",
"Custom API Call": "Пользовательский вызов API",
"Creates new collection item.": "Создать новый элемент подборки.",
"Delete collection item": "Удалить элемент коллекции",
"Update collection item": "Обновить элемент коллекции",
"Find collection item in a collection by field": "Найти элемент коллекции в коллекции по полю",
"Get collection item in a collection by ID": "Получить элемент коллекции в коллекции по идентификатору",
"Fulfill order": "Выполнить заказ",
"Unfulfill order": "Невыполненный заказ",
"Refund order": "Заказ на возврат",
"Find order": "Найти заказ",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Site": "Сайт",
"Collection": "Коллекция",
"Collection Fields": "Поля коллекции",
"Is Archived": "Архивировано",
"Is Draft": "Черновик",
"Collection Item": "Элемент коллекции",
"Field Name": "Имя поля",
"Field Value": "Значение поля",
"Max Results": "Макс. результатов",
"Order": "Заказ",
"Send Order Fulfilled Email": "Отправить заказ по электронной почте",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"Whether the item is archived or not": "Архивируется ли элемент или нет",
"Whether the item is a draft or not": "Является ли пункт черновиком или нет",
"The name of the field to search by": "Название поля для поиска",
"The value of the field to search for": "Значение поля для поиска",
"The maximum number of results to return": "Максимальное количество результатов для возврата",
"Send an email to the customer that their order has been fulfilled": "Отправить письмо клиенту, что его заказ был выполнен",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD",
"New Submission": "Новая заявка",
"Triggers when Webflow Site receives a new submission": "Триггеры, когда Webflow Site получает новую запись",
"Form Name": "Имя формы",
"Copy from the form settings, or from one of the responses": "Копировать из настроек формы или из одного из ответов"
}

View File

@@ -0,0 +1,59 @@
{
"Design, build, and launch responsive websites visually": "Design, build, and launch responsive websites visually",
"Create Collection Item": "Create Collection Item",
"Delete an item in a collection": "Delete an item in a collection",
"Update an item in a collection": "Update an item in a collection",
"Find a Collection Item by Field": "Find a Collection Item by Field",
"Get a Collection Item by ID": "Get a Collection Item by ID",
"Fulfill an order": "Fulfill an order",
"Unfulfill an order": "Unfulfill an order",
"Refund an order": "Refund an order",
"Find an order": "Find an order",
"Custom API Call": "Custom API Call",
"Creates new collection item.": "Creates new collection item.",
"Delete collection item": "Delete collection item",
"Update collection item": "Update collection item",
"Find collection item in a collection by field": "Find collection item in a collection by field",
"Get collection item in a collection by ID": "Get collection item in a collection by ID",
"Fulfill order": "Fulfill order",
"Unfulfill order": "Unfulfill order",
"Refund order": "Refund order",
"Find order": "Find order",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Site": "Site",
"Collection": "Collection",
"Collection Fields": "Collection Fields",
"Is Archived": "Is Archived",
"Is Draft": "Is Draft",
"Collection Item": "Collection Item",
"Field Name": "Field Name",
"Field Value": "Field Value",
"Max Results": "Max Results",
"Order": "Order",
"Send Order Fulfilled Email": "Send Order Fulfilled Email",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Whether the item is archived or not": "Whether the item is archived or not",
"Whether the item is a draft or not": "Whether the item is a draft or not",
"The name of the field to search by": "The name of the field to search by",
"The value of the field to search for": "The value of the field to search for",
"The maximum number of results to return": "The maximum number of results to return",
"Send an email to the customer that their order has been fulfilled": "Send an email to the customer that their order has been fulfilled",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Submission": "New Submission",
"Triggers when Webflow Site receives a new submission": "Triggers when Webflow Site receives a new submission",
"Form Name": "Form Name",
"Copy from the form settings, or from one of the responses": "Copy from the form settings, or from one of the responses"
}

View File

@@ -0,0 +1,58 @@
{
"Webflow": "Webflow",
"Design, build, and launch responsive websites visually": "Design, build, and launch responsive websites visually",
"Create Collection Item": "Create Collection Item",
"Delete an item in a collection": "Delete an item in a collection",
"Update an item in a collection": "Update an item in a collection",
"Find a Collection Item by Field": "Find a Collection Item by Field",
"Get a Collection Item by ID": "Get a Collection Item by ID",
"Fulfill an order": "Fulfill an order",
"Unfulfill an order": "Unfulfill an order",
"Refund an order": "Refund an order",
"Find an order": "Find an order",
"Custom API Call": "Custom API Call",
"Creates new collection item.": "Creates new collection item.",
"Delete collection item": "Delete collection item",
"Update collection item": "Update collection item",
"Find collection item in a collection by field": "Find collection item in a collection by field",
"Get collection item in a collection by ID": "Get collection item in a collection by ID",
"Fulfill order": "Fulfill order",
"Unfulfill order": "Unfulfill order",
"Refund order": "Refund order",
"Find order": "Find order",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Site": "Site",
"Collection": "Collection",
"Collection Fields": "Collection Fields",
"Is Archived": "Is Archived",
"Is Draft": "Is Draft",
"Collection Item": "Collection Item",
"Field Name": "Field Name",
"Field Value": "Field Value",
"Max Results": "Max Results",
"Order": "Order",
"Send Order Fulfilled Email": "Send Order Fulfilled Email",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Whether the item is archived or not": "Whether the item is archived or not",
"Whether the item is a draft or not": "Whether the item is a draft or not",
"The name of the field to search by": "The name of the field to search by",
"The value of the field to search for": "The value of the field to search for",
"The maximum number of results to return": "The maximum number of results to return",
"Send an email to the customer that their order has been fulfilled": "Send an email to the customer that their order has been fulfilled",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Submission": "New Submission",
"Triggers when Webflow Site receives a new submission": "Triggers when Webflow Site receives a new submission",
"Form Name": "Form Name",
"Copy from the form settings, or from one of the responses": "Copy from the form settings, or from one of the responses"
}

View File

@@ -0,0 +1,59 @@
{
"Design, build, and launch responsive websites visually": "Design, build, and launch responsive websites visually",
"Create Collection Item": "Create Collection Item",
"Delete an item in a collection": "Delete an item in a collection",
"Update an item in a collection": "Update an item in a collection",
"Find a Collection Item by Field": "Find a Collection Item by Field",
"Get a Collection Item by ID": "Get a Collection Item by ID",
"Fulfill an order": "Fulfill an order",
"Unfulfill an order": "Unfulfill an order",
"Refund an order": "Refund an order",
"Find an order": "Find an order",
"Custom API Call": "自定义 API 呼叫",
"Creates new collection item.": "Creates new collection item.",
"Delete collection item": "Delete collection item",
"Update collection item": "Update collection item",
"Find collection item in a collection by field": "Find collection item in a collection by field",
"Get collection item in a collection by ID": "Get collection item in a collection by ID",
"Fulfill order": "Fulfill order",
"Unfulfill order": "Unfulfill order",
"Refund order": "Refund order",
"Find order": "Find order",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Site": "Site",
"Collection": "Collection",
"Collection Fields": "Collection Fields",
"Is Archived": "Is Archived",
"Is Draft": "Is Draft",
"Collection Item": "Collection Item",
"Field Name": "Field Name",
"Field Value": "Field Value",
"Max Results": "Max Results",
"Order": "Order",
"Send Order Fulfilled Email": "Send Order Fulfilled Email",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Whether the item is archived or not": "Whether the item is archived or not",
"Whether the item is a draft or not": "Whether the item is a draft or not",
"The name of the field to search by": "The name of the field to search by",
"The value of the field to search for": "The value of the field to search for",
"The maximum number of results to return": "The maximum number of results to return",
"Send an email to the customer that their order has been fulfilled": "Send an email to the customer that their order has been fulfilled",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"New Submission": "New Submission",
"Triggers when Webflow Site receives a new submission": "Triggers when Webflow Site receives a new submission",
"Form Name": "Form Name",
"Copy from the form settings, or from one of the responses": "Copy from the form settings, or from one of the responses"
}

View File

@@ -0,0 +1,57 @@
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import { OAuth2PropertyValue, PieceAuth, createPiece } from '@activepieces/pieces-framework';
import { PieceCategory } from '@activepieces/shared';
import { webflowCreateCollectionItemAction } from './lib/actions/create-collection-item';
import { webflowDeleteCollectionItem } from './lib/actions/delete-collection-item';
import { webflowFindCollectionItem } from './lib/actions/find-collection-item';
import { webflowFindOrder } from './lib/actions/find-order';
import { webflowFulfillOrder } from './lib/actions/fulfill-order';
import { webflowGetCollectionItem } from './lib/actions/get-collection-item';
import { webflowRefundOrder } from './lib/actions/refund-order';
import { webflowUnfulfillOrder } from './lib/actions/unfulfill-order';
import { webflowUpdateCollectionItem } from './lib/actions/update-collection-item';
import { webflowNewSubmission } from './lib/triggers/new-form-submitted';
export const webflowAuth = PieceAuth.OAuth2({
description: '',
authUrl: 'https://webflow.com/oauth/authorize',
tokenUrl: 'https://api.webflow.com/oauth/access_token',
required: true,
scope: ['webhooks:write', 'forms:read'],
});
export const webflow = createPiece({
displayName: 'Webflow',
description: 'Design, build, and launch responsive websites visually',
minimumSupportedRelease: '0.5.0',
logoUrl: 'https://cdn.activepieces.com/pieces/webflow.png',
categories: [PieceCategory.MARKETING],
authors: [
'Ahmad-AbuOsbeh',
'TaskMagicKyle',
'kishanprmr',
'MoShizzle',
'khaledmashaly',
'abuaboud',
],
auth: webflowAuth,
actions: [
webflowCreateCollectionItemAction,
webflowDeleteCollectionItem,
webflowUpdateCollectionItem,
webflowFindCollectionItem,
webflowGetCollectionItem,
webflowFulfillOrder,
webflowUnfulfillOrder,
webflowRefundOrder,
webflowFindOrder,
createCustomApiCallAction({
baseUrl: () => 'https://api.webflow.com',
auth: webflowAuth,
authMapping: async (auth) => ({
Authorization: `Bearer ${(auth as OAuth2PropertyValue).access_token}`,
}),
}),
],
triggers: [webflowNewSubmission],
});

View File

@@ -0,0 +1,62 @@
import { createAction, DynamicPropsValue, Property } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowCreateCollectionItemAction = createAction({
auth: webflowAuth,
name: 'create_collection_item',
displayName: 'Create Collection Item',
description: 'Creates new collection item.',
props: {
site_id: webflowProps.site_id,
collection_id: webflowProps.collection_id,
collection_fields: webflowProps.collection_fields,
is_archived: Property.Checkbox({
displayName: 'Is Archived',
description: 'Whether the item is archived or not',
required: false,
}),
is_draft: Property.Checkbox({
displayName: 'Is Draft',
description: 'Whether the item is a draft or not',
required: false,
}),
},
async run(context) {
const collectionId = context.propsValue.collection_id;
const isArchived = context.propsValue.is_archived;
const isDraft = context.propsValue.is_draft;
const collectionInputFields = context.propsValue.collection_fields;
const client = new WebflowApiClient(context.auth.access_token);
const { fields: CollectionFields } = await client.getCollection(collectionId);
const formattedCollectionFields: DynamicPropsValue = {};
for (const field of CollectionFields) {
const fieldValue = collectionInputFields[field.slug];
if (fieldValue !== undefined && fieldValue !== '') {
switch (field.type) {
case 'ImageRef':
case 'FileRef':
formattedCollectionFields[field.slug] = { url: fieldValue };
break;
case 'Set':
formattedCollectionFields[field.slug] = fieldValue.map((url: string) => ({ url: url }));
break;
case 'Number':
formattedCollectionFields[field.slug] = Number(fieldValue);
break;
default:
formattedCollectionFields[field.slug] = fieldValue;
}
}
}
return await client.createCollectionItem(collectionId, {
fields: { ...formattedCollectionFields, _archived: isArchived, _draft: isDraft },
});
},
});

View File

@@ -0,0 +1,26 @@
import { createAction } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowDeleteCollectionItem = createAction({
auth: webflowAuth,
name: 'delete_collection_item',
description: 'Delete collection item',
displayName: 'Delete an item in a collection',
props: {
site_id: webflowProps.site_id,
collection_id: webflowProps.collection_id,
collection_item_id: webflowProps.collection_item_id,
},
async run(context) {
const collectionId = context.propsValue.collection_id;
const collectionItemId = context.propsValue.collection_item_id;
const client = new WebflowApiClient(context.auth.access_token);
return await client.deleteCollectionItem(collectionId, collectionItemId);
},
});

View File

@@ -0,0 +1,70 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import {
HttpRequest,
HttpMethod,
httpClient,
AuthenticationType,
} from '@activepieces/pieces-common';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
export const webflowFindCollectionItem = createAction({
auth: webflowAuth,
name: 'find_collection_item',
description: 'Find collection item in a collection by field',
displayName: 'Find a Collection Item by Field',
props: {
site_id: webflowProps.site_id,
collection_id: webflowProps.collection_id,
field_name: Property.ShortText({
displayName: 'Field Name',
description: 'The name of the field to search by',
required: true,
}),
field_value: Property.ShortText({
displayName: 'Field Value',
description: 'The value of the field to search for',
required: true,
}),
max_results: Property.Number({
displayName: 'Max Results',
description: 'The maximum number of results to return',
required: false,
}),
},
async run(configValue) {
const accessToken = configValue.auth['access_token'];
const collectionId = configValue.propsValue['collection_id'];
const fieldName = configValue.propsValue['field_name'];
const fieldValue = configValue.propsValue['field_value'];
const maxResults = configValue.propsValue['max_results'];
const request: HttpRequest = {
method: HttpMethod.GET,
url: `https://api.webflow.com/collections/${collectionId}/items`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: accessToken,
},
};
try {
const res = await httpClient.sendRequest(request);
if (res.status !== 200) {
throw new Error('Failed to fetch collection items');
}
const items = res.body.items;
const matches = items
.filter((item: any) => {
return item.fields[fieldName] === fieldValue;
})
.slice(0, maxResults);
return { success: true, result: matches };
} catch (err) {
return { success: false, message: err };
}
},
});

View File

@@ -0,0 +1,25 @@
import { createAction } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowFindOrder = createAction({
auth: webflowAuth,
name: 'find_order',
description: 'Find order',
displayName: 'Find an order',
props: {
site_id: webflowProps.site_id,
order_id: webflowProps.order_id,
},
async run(context) {
const orderId = context.propsValue.order_id;
const siteId = context.propsValue.site_id;
const client = new WebflowApiClient(context.auth.access_token);
return await client.getOrder(siteId, orderId);
},
});

View File

@@ -0,0 +1,31 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowFulfillOrder = createAction({
auth: webflowAuth,
name: 'fulfill_order',
description: 'Fulfill order',
displayName: 'Fulfill an order',
props: {
site_id: webflowProps.site_id,
order_id: webflowProps.order_id,
send_order_fulfilled_email: Property.Checkbox({
displayName: 'Send Order Fulfilled Email',
description: 'Send an email to the customer that their order has been fulfilled',
required: false,
}),
},
async run(context) {
const orderId = context.propsValue.order_id;
const siteId = context.propsValue.site_id;
const sendOrderFulfilledEmail = context.propsValue.send_order_fulfilled_email;
const client = new WebflowApiClient(context.auth.access_token);
return await client.fulfillOrder(siteId, orderId, { sendOrderFulfilledEmail });
},
});

View File

@@ -0,0 +1,26 @@
import { createAction } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowGetCollectionItem = createAction({
auth: webflowAuth,
name: 'get_collection_item',
description: 'Get collection item in a collection by ID',
displayName: 'Get a Collection Item by ID',
props: {
site_id: webflowProps.site_id,
collection_id: webflowProps.collection_id,
collection_item_id: webflowProps.collection_item_id,
},
async run(context) {
const collectionId = context.propsValue.collection_id;
const collectionItemId = context.propsValue.collection_item_id;
const client = new WebflowApiClient(context.auth.access_token);
return await client.getCollectionItem(collectionId, collectionItemId);
},
});

View File

@@ -0,0 +1,26 @@
import { createAction } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowPublishCollectionItem = createAction({
auth: webflowAuth,
name: 'publish_collection_item',
description: 'Publish collection item',
displayName: 'Publish a Collection Item',
props: {
site_id: webflowProps.site_id,
collection_id: webflowProps.collection_id,
collection_item_id: webflowProps.collection_item_id,
},
async run(context) {
const collectionId = context.propsValue.collection_id;
const collectionItemId = context.propsValue.collection_item_id;
const client = new WebflowApiClient(context.auth.access_token);
return await client.publishCollectionItem(collectionId, collectionItemId);
},
});

View File

@@ -0,0 +1,47 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowRefundOrder = createAction({
auth: webflowAuth,
name: 'refund_order',
description: 'Refund order',
displayName: 'Refund an order',
props: {
site_id: webflowProps.site_id,
order_id: webflowProps.order_id,
// reason: Property.StaticDropdown({
// displayName: 'Reason',
// description: 'The reason for the refund',
// required: false,
// options: {
// disabled: false,
// options: [
// {
// label: 'Duplicate',
// value: 'duplicate',
// },
// {
// label: 'Fraudulent',
// value: 'fraudulent',
// },
// {
// label: 'Requested',
// value: 'requested',
// },
// ],
// },
// }),
},
async run(context) {
const orderId = context.propsValue.order_id;
const siteId = context.propsValue.site_id;
const client = new WebflowApiClient(context.auth.access_token);
return await client.refundOrder(siteId, orderId);
},
});

View File

@@ -0,0 +1,25 @@
import { createAction } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowUnfulfillOrder = createAction({
auth: webflowAuth,
name: 'unfulfill_order',
description: 'Unfulfill order',
displayName: 'Unfulfill an order',
props: {
site_id: webflowProps.site_id,
order_id: webflowProps.order_id,
},
async run(context) {
const orderId = context.propsValue.order_id;
const siteId = context.propsValue.site_id;
const client = new WebflowApiClient(context.auth.access_token);
return await client.unfulfillOrder(siteId, orderId);
},
});

View File

@@ -0,0 +1,74 @@
import { createAction, DynamicPropsValue, Property } from '@activepieces/pieces-framework';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
import { WebflowApiClient } from '../common/client';
export const webflowUpdateCollectionItem = createAction({
auth: webflowAuth,
name: 'update_collection_item',
description: 'Update collection item',
displayName: 'Update an item in a collection',
props: {
site_id: webflowProps.site_id,
collection_id: webflowProps.collection_id,
collection_item_id: webflowProps.collection_item_id,
collection_fields: webflowProps.collection_fields,
is_archived: Property.Checkbox({
displayName: 'Is Archived',
description: 'Whether the item is archived or not',
required: false,
}),
is_draft: Property.Checkbox({
displayName: 'Is Draft',
description: 'Whether the item is a draft or not',
required: false,
}),
},
async run(context) {
const collectionId = context.propsValue.collection_id;
const collectionItemId = context.propsValue.collection_item_id;
const isArchived = context.propsValue.is_archived;
const isDraft = context.propsValue.is_draft;
const collectionInputFields = context.propsValue.collection_fields;
const client = new WebflowApiClient(context.auth.access_token);
const { fields: CollectionFields } = await client.getCollection(collectionId);
const formattedCollectionFields: DynamicPropsValue = {};
for (const field of CollectionFields) {
const fieldValue = collectionInputFields[field.slug];
if (fieldValue !== undefined && fieldValue !== '') {
switch (field.type) {
case 'ImageRef':
case 'FileRef':
formattedCollectionFields[field.slug] = { url: fieldValue };
break;
case 'Set':
if (fieldValue.length > 0) {
formattedCollectionFields[field.slug] = fieldValue.map((url: string) => ({
url: url,
}));
}
break;
case 'ItemRefSet':
if (fieldValue.length > 0) {
formattedCollectionFields[field.slug] = fieldValue;
}
break;
case 'Number':
formattedCollectionFields[field.slug] = Number(fieldValue);
break;
default:
formattedCollectionFields[field.slug] = fieldValue;
}
}
}
return await client.updateCollectionItem(collectionId, collectionItemId, {
fields: { ...formattedCollectionFields, _archived: isArchived, _draft: isDraft },
});
},
});

View File

@@ -0,0 +1,148 @@
import {
AuthenticationType,
httpClient,
HttpMethod,
HttpRequest,
QueryParams,
} from '@activepieces/pieces-common';
export class WebflowApiClient {
constructor(private accessToken: string) {}
async makeRequest(
method: HttpMethod,
resourceUri: string,
query?: Record<string, string | number | string[] | undefined>,
body: any | undefined = undefined,
): Promise<any> {
const apiUrl = 'https://api.webflow.com';
const params: QueryParams = {};
if (query) {
for (const [key, value] of Object.entries(query)) {
if (value !== null && value !== undefined) {
params[key] = String(value);
}
}
}
const request: HttpRequest = {
method: method,
url: apiUrl + resourceUri,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: this.accessToken,
},
queryParams: params,
body: body,
};
const response = await httpClient.sendRequest(request);
return response.body;
}
async listSites() {
return await this.makeRequest(HttpMethod.GET, '/sites');
}
async listCollections(siteId: string) {
return await this.makeRequest(HttpMethod.GET, `/sites/${siteId}/collections`);
}
async getCollection(collectionId: string) {
return await this.makeRequest(HttpMethod.GET, `/collections/${collectionId}`);
}
async createCollectionItem(collectionId: string, request: Record<string, any>) {
return await this.makeRequest(
HttpMethod.POST,
`/collections/${collectionId}/items`,
undefined,
request,
);
}
async updateCollectionItem(collectionId: string, itemId: string, request: Record<string, any>) {
return await this.makeRequest(
HttpMethod.PUT,
`/collections/${collectionId}/items/${itemId}`,
undefined,
request,
);
}
async getCollectionItem(collectionId: string, itemId: string) {
return await this.makeRequest(HttpMethod.GET, `/collections/${collectionId}/items/${itemId}`);
}
async deleteCollectionItem(collectionId: string, itemId: string) {
return await this.makeRequest(
HttpMethod.DELETE,
`/collections/${collectionId}/items/${itemId}`,
);
}
async publishCollectionItem(collectionId: string, itemId: string) {
return await this.makeRequest(
HttpMethod.POST,
`/collections/${collectionId}/items/publish`,
undefined,
{ itemIds: [itemId] },
);
}
async listCollectionItems(collectionId: string, page: number, limit: number) {
return await this.makeRequest(HttpMethod.GET, `/collections/${collectionId}/items`, {
offset: page,
limit,
});
}
async getOrder(siteId: string, orderId: string) {
return await this.makeRequest(HttpMethod.GET, `/sites/${siteId}/orders/${orderId}`);
}
async fulfillOrder(siteId: string, orderId: string, request: Record<string, any>) {
return await this.makeRequest(
HttpMethod.POST,
`/sites/${siteId}/orders/${orderId}/fulfill`,
undefined,
request,
);
}
async unfulfillOrder(siteId: string, orderId: string) {
return await this.makeRequest(
HttpMethod.POST,
`/sites/${siteId}/orders/${orderId}/unfulfill`,
undefined,
);
}
async refundOrder(siteId: string, orderId: string) {
return await this.makeRequest(HttpMethod.POST, `/sites/${siteId}/orders/${orderId}/refund`);
}
async listOrders(siteId: string, page: number, limit: number) {
return await this.makeRequest(HttpMethod.GET, `/sites/${siteId}/orders`, {
offset: page,
limit,
});
}
async createWebhook(siteId: string, triggerType: string, webhookUrl: string) {
return await this.makeRequest(
HttpMethod.POST,
`'/sites/${siteId}/webhooks`,
{},
{
triggerType,
url: webhookUrl,
},
);
}
async deleteWebhook(webhookId: string) {
return await this.makeRequest(HttpMethod.DELETE, `/webhooks/${webhookId}`);
}
}

View File

@@ -0,0 +1,52 @@
import { Property, OAuth2PropertyValue, DynamicPropsValue } from '@activepieces/pieces-framework';
import {
HttpRequest,
HttpMethod,
AuthenticationType,
httpClient,
} from '@activepieces/pieces-common';
export const webflowCommon = {
baseUrl: 'https://api.webflow.com/',
subscribeWebhook: async (
siteId: string,
tag: string,
webhookUrl: string,
accessToken: string,
) => {
const request: HttpRequest = {
method: HttpMethod.POST,
url: `https://api.webflow.com/sites/${siteId}/webhooks`,
headers: {
'Content-Type': 'application/json',
},
body: {
triggerType: tag,
url: webhookUrl,
},
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: accessToken,
},
queryParams: {},
};
const res = await httpClient.sendRequest(request);
return res;
},
unsubscribeWebhook: async (siteId: string, webhookId: string, accessToken: string) => {
const request: HttpRequest = {
method: HttpMethod.DELETE,
url: `https://api.webflow.com/sites/${siteId}/webhooks/${webhookId}`,
headers: {
'Content-Type': 'application/json',
},
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: accessToken,
},
};
return await httpClient.sendRequest(request);
},
};

View File

@@ -0,0 +1,237 @@
import {
DropdownOption,
DynamicPropsValue,
PiecePropValueSchema,
Property,
} from '@activepieces/pieces-framework';
import { WebflowApiClient } from './client';
import { webflowAuth } from '../..';
export const webflowProps = {
site_id: Property.Dropdown({
auth: webflowAuth,
displayName: 'Site',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect account first.',
};
}
const authValue = auth;
const client = new WebflowApiClient(authValue.access_token);
const sites = await client.listSites();
const options: DropdownOption<string>[] = [];
for (const site of sites) {
options.push({ label: site.name, value: site._id });
}
return {
disabled: false,
options,
};
},
}),
collection_id: Property.Dropdown({
auth: webflowAuth,
displayName: 'Collection',
required: true,
refreshers: ['site_id'],
options: async ({ auth, site_id }) => {
if (!auth || !site_id) {
return {
disabled: true,
options: [],
placeholder: 'Please connect account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof webflowAuth>;
const client = new WebflowApiClient(authValue.access_token);
const collections = await client.listCollections(site_id as string);
const options: DropdownOption<string>[] = [];
for (const collection of collections) {
options.push({ label: collection.name, value: collection._id });
}
return {
disabled: false,
options,
};
},
}),
collection_fields: Property.DynamicProperties({
auth: webflowAuth,
displayName: 'Collection Fields',
required: true,
refreshers: ['collection_id'],
props: async ({ auth, collection_id }) => {
if (!auth) return {};
if (!collection_id) return {};
const collectionFields: DynamicPropsValue = {};
const authValue = auth as PiecePropValueSchema<typeof webflowAuth>;
const client = new WebflowApiClient(authValue.access_token);
const { fields } = await client.getCollection(collection_id as unknown as string);
for (const field of fields) {
if (field.editable && field.slug !== '_archived' && field.slug !== '_draft') {
switch (field.type) {
case 'Option':
collectionFields[field.slug] = Property.StaticDropdown({
displayName: field.name,
required: field.required,
options: {
disabled: false,
options: field.validations.options.map((option: { name: string }) => {
return {
label: option.name,
value: option.name,
};
}),
},
});
break;
case 'RichText':
case 'Email':
case 'PlainText':
case 'Phone':
case 'Link':
case 'Video':
case 'Color':
case 'ItemRef':
case 'FileRef':
collectionFields[field.slug] = Property.ShortText({
displayName: field.name,
required: field.required,
});
break;
case 'ImageRef':
collectionFields[field.slug] = Property.ShortText({
displayName: field.name,
required: field.required,
description:
'Images must be hosted on a publicly accessible URL to be uploaded via the API.The maximum file size for images is 4MB.',
});
break;
case 'Set':
collectionFields[field.slug] = Property.Array({
displayName: field.name,
required: field.required,
description:
' Images must be hosted on a publicly accessible URL to be uploaded via the API.The maximum file size for images is 4MB.',
});
break;
case 'ItemRefSet':
collectionFields[field.slug] = Property.Array({
displayName: field.name,
required: field.required,
});
break;
case 'Number':
collectionFields[field.slug] = Property.Number({
displayName: field.name,
required: field.required,
});
break;
case 'Date':
collectionFields[field.slug] = Property.DateTime({
displayName: field.name,
required: field.required,
});
break;
case 'Bool':
collectionFields[field.slug] = Property.Checkbox({
displayName: field.name,
required: false,
});
break;
}
}
}
return collectionFields;
},
}),
collection_item_id: Property.Dropdown({
auth: webflowAuth,
displayName: 'Collection Item',
required: true,
refreshers: ['collection_id'],
options: async ({ auth, collection_id }) => {
if (!auth || !collection_id) {
return {
disabled: true,
options: [],
placeholder: 'Please connect account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof webflowAuth>;
const client = new WebflowApiClient(authValue.access_token);
const options: DropdownOption<string>[] = [];
let page = 0;
let response;
do {
response = await client.listCollectionItems(collection_id as string, page, 100);
page += 100;
for (const item of response.items) {
options.push({ label: item.name, value: item._id });
}
} while (response.items.length > 0);
return {
disabled: false,
options,
};
},
}),
order_id: Property.Dropdown({
auth: webflowAuth,
displayName: 'Order',
required: true,
refreshers: ['site_id'],
options: async ({ auth, site_id }) => {
if (!auth || !site_id) {
return {
disabled: true,
options: [],
placeholder: 'Please connect account first.',
};
}
const authValue = auth as PiecePropValueSchema<typeof webflowAuth>;
const client = new WebflowApiClient(authValue.access_token);
const options: DropdownOption<string>[] = [];
let page = 0;
let response;
do {
response = await client.listOrders(site_id as string, page, 100);
page += 100;
for (const order of response) {
options.push({ label: order.orderId, value: order.orderId });
}
} while (response.length > 0);
return {
disabled: false,
options,
};
},
}),
};

View File

@@ -0,0 +1,79 @@
import { webflowCommon } from '../common/common';
import { createTrigger, TriggerStrategy, Property } from '@activepieces/pieces-framework';
import { getAccessTokenOrThrow } from '@activepieces/pieces-common';
import { webflowAuth } from '../..';
import { webflowProps } from '../common/props';
const triggerNameInStore = 'webflow_created_form_submissions_trigger';
export const webflowNewSubmission = createTrigger({
auth: webflowAuth,
name: 'new_submission',
displayName: 'New Submission',
description: 'Triggers when Webflow Site receives a new submission',
props: {
site_id: webflowProps.site_id,
formName: Property.ShortText({
displayName: 'Form Name',
required: false,
description: 'Copy from the form settings, or from one of the responses',
}),
},
type: TriggerStrategy.WEBHOOK,
// TODO remove and force testing as the data can be custom.
sampleData: {
name: 'Sample Form',
site: '62749158efef318abc8d5a0f',
data: {
field_one: 'mock valued',
},
d: '2022-09-14T12:35:16.117Z',
_id: '6321ca84df3949bfc6752327',
},
async onEnable(context) {
const formSubmissionTag = 'form_submission';
const res = await webflowCommon.subscribeWebhook(
context.propsValue['site_id']!,
formSubmissionTag,
context.webhookUrl,
getAccessTokenOrThrow(context.auth),
);
await context.store?.put<WebhookInformation>(triggerNameInStore, {
webhookId: res.body._id,
});
},
async onDisable(context) {
const response = await context.store?.get<WebhookInformation>(triggerNameInStore);
if (response !== null && response !== undefined) {
await webflowCommon.unsubscribeWebhook(
context.propsValue['site_id']!,
response.webhookId,
getAccessTokenOrThrow(context.auth),
);
}
},
async run(context) {
const body = context.payload.body as PayloadBody;
const { formName } = context.propsValue;
//if formName provided, trigger only required formName if it's matched; else trigger all forms in selected webflow site.
if (formName) {
if (body.name == formName) {
return [body];
} else {
return [];
}
} else {
return [body];
}
},
});
interface WebhookInformation {
webhookId: string;
}
type PayloadBody = {
name: string;
};

View File

@@ -0,0 +1,16 @@
{
"extends": "../../../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
],
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}

View File

@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}