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:
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"extends": [
|
||||
"../../../../.eslintrc.base.json"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"!**/*"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.ts",
|
||||
"*.tsx",
|
||||
"*.js",
|
||||
"*.jsx"
|
||||
],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.ts",
|
||||
"*.tsx"
|
||||
],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.js",
|
||||
"*.jsx"
|
||||
],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# pieces-smartsuite
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Building
|
||||
|
||||
Run `nx build pieces-smartsuite` to build the library.
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "@activepieces/piece-smartsuite",
|
||||
"version": "0.0.8"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "pieces-smartsuite",
|
||||
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "packages/pieces/community/smartsuite/src",
|
||||
"projectType": "library",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nx/js:tsc",
|
||||
"outputs": [
|
||||
"{options.outputPath}"
|
||||
],
|
||||
"options": {
|
||||
"outputPath": "dist/packages/pieces/community/smartsuite",
|
||||
"tsConfig": "packages/pieces/community/smartsuite/tsconfig.lib.json",
|
||||
"packageJson": "packages/pieces/community/smartsuite/package.json",
|
||||
"main": "packages/pieces/community/smartsuite/src/index.ts",
|
||||
"assets": [
|
||||
"packages/pieces/community/smartsuite/*.md",
|
||||
{
|
||||
"input": "packages/pieces/community/smartsuite/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/smartsuite",
|
||||
"command": "bun install --no-save --silent"
|
||||
},
|
||||
"dependsOn": [
|
||||
"^build"
|
||||
]
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Kollaborative Arbeitsmanagementplattform, die Datenbanken mit Tabellenkalkulationen kombiniert.",
|
||||
"API Key": "API-Schlüssel",
|
||||
"Account ID": "Konto-ID",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n Du kannst API-Schlüssel über **Mein Profil->API-Schlüssel** aus der oberen rechten Ecke erhalten.\n \n Sie können Konto-ID von der Browser-URL erhalten. oder beispielsweise, wenn die URL des smartsuite Arbeitsbereiches https://app.smartsuite.com/xyz/home ist, ist Ihre Konto-ID **xyz**.",
|
||||
"Create a Record": "Datensatz erstellen",
|
||||
"Update a Record": "Datensatz aktualisieren",
|
||||
"Delete a Record": "Datensatz löschen",
|
||||
"Upload File": "Datei hochladen",
|
||||
"Find Records": "Datensätze finden",
|
||||
"Get a Record": "Datensatz abrufen",
|
||||
"Custom API Call": "Eigener API-Aufruf",
|
||||
"Creates a new record in the specified table.": "Erstellt einen neuen Datensatz in der angegebenen Tabelle.",
|
||||
"Updates an existing record in the specified table": "Aktualisiert einen vorhandenen Datensatz in der angegebenen Tabelle",
|
||||
"Deletes a record from the specified table": "Löscht einen Eintrag aus der angegebenen Tabelle",
|
||||
"Uploads a file and attaches it to a record.": "Lädt eine Datei hoch und fügt sie an einen Datensatz an.",
|
||||
"Searches for records in the specified table based on criteria.": "Sucht nach Datensätzen in der angegebenen Tabelle basierend auf Kriterien.",
|
||||
"Retrieves a specific record by ID": "Ruft einen bestimmten Datensatz per ID ab",
|
||||
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
|
||||
"Solution": "Lösung",
|
||||
"Table": "Tisch",
|
||||
"Fields": "Felder",
|
||||
"Record ID": "Datensatz-ID",
|
||||
"Search Field": "Suchfeld",
|
||||
"File": "Datei",
|
||||
"Search Value": "Suchwert",
|
||||
"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)",
|
||||
"The file to upload": "Die hochzuladende Datei",
|
||||
"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 Record": "Neuer Datensatz",
|
||||
"Updated Record": "Aktualisierte Datensatz",
|
||||
"Triggers when a new record is created in the specified table": "Wird ausgelöst, wenn ein neuer Datensatz in der angegebenen Tabelle erstellt wird",
|
||||
"Triggers when a record is updated in the specified table.": "Wird ausgelöst, wenn ein Datensatz in der angegebenen Tabelle aktualisiert wird."
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Plataforma de gestión de trabajo colaborativa que combina bases de datos con hojas de cálculo.",
|
||||
"API Key": "Clave API",
|
||||
"Account ID": "ID de cuenta",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.",
|
||||
"Create a Record": "Crear un registro",
|
||||
"Update a Record": "Actualizar un registro",
|
||||
"Delete a Record": "Eliminar un registro",
|
||||
"Upload File": "Subir archivo",
|
||||
"Find Records": "Buscar registros",
|
||||
"Get a Record": "Obtener un registro",
|
||||
"Custom API Call": "Llamada API personalizada",
|
||||
"Creates a new record in the specified table.": "Crea un nuevo registro en la tabla especificada.",
|
||||
"Updates an existing record in the specified table": "Actualiza un registro existente en la tabla especificada",
|
||||
"Deletes a record from the specified table": "Borrar un registro de la tabla especificada",
|
||||
"Uploads a file and attaches it to a record.": "Sube un archivo y lo adjunta a un registro.",
|
||||
"Searches for records in the specified table based on criteria.": "Busca registros en la tabla especificada según criterios.",
|
||||
"Retrieves a specific record by ID": "Recuperar un registro específico por ID",
|
||||
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
|
||||
"Solution": "Solución",
|
||||
"Table": "Tabla",
|
||||
"Fields": "Campos",
|
||||
"Record ID": "ID de registro",
|
||||
"Search Field": "Campo de búsqueda",
|
||||
"File": "Archivo",
|
||||
"Search Value": "Valor de búsqueda",
|
||||
"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)",
|
||||
"The file to upload": "El archivo a subir",
|
||||
"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 Record": "Nuevo registro",
|
||||
"Updated Record": "Registro actualizado",
|
||||
"Triggers when a new record is created in the specified table": "Dispara cuando se crea un nuevo registro en la tabla especificada",
|
||||
"Triggers when a record is updated in the specified table.": "Dispara cuando un registro se actualiza en la tabla especificada."
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Plateforme de gestion de travail collaborative combinant les bases de données et les feuilles de calcul.",
|
||||
"API Key": "Clé API",
|
||||
"Account ID": "ID du compte client",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.",
|
||||
"Create a Record": "Créer un enregistrement",
|
||||
"Update a Record": "Mettre à jour un enregistrement",
|
||||
"Delete a Record": "Supprimer un enregistrement",
|
||||
"Upload File": "Charger un fichier",
|
||||
"Find Records": "Trouver des enregistrements",
|
||||
"Get a Record": "Obtenir un enregistrement",
|
||||
"Custom API Call": "Appel d'API personnalisé",
|
||||
"Creates a new record in the specified table.": "Crée un nouvel enregistrement dans la table spécifiée.",
|
||||
"Updates an existing record in the specified table": "Met à jour un enregistrement existant dans la table spécifiée",
|
||||
"Deletes a record from the specified table": "Supprime un enregistrement de la table spécifiée",
|
||||
"Uploads a file and attaches it to a record.": "Télécharge un fichier et le joint à un enregistrement.",
|
||||
"Searches for records in the specified table based on criteria.": "Recherche les enregistrements dans la table spécifiée en fonction des critères.",
|
||||
"Retrieves a specific record by ID": "Récupère un enregistrement spécifique par ID",
|
||||
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
|
||||
"Solution": "Solution",
|
||||
"Table": "Tableau",
|
||||
"Fields": "Champs",
|
||||
"Record ID": "ID de l'enregistrement",
|
||||
"Search Field": "Champ de recherche",
|
||||
"File": "Ficher",
|
||||
"Search Value": "Valeur de la recherche",
|
||||
"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)",
|
||||
"The file to upload": "Le fichier à télécharger",
|
||||
"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 Record": "Nouvel enregistrement",
|
||||
"Updated Record": "Enregistrement mis à jour",
|
||||
"Triggers when a new record is created in the specified table": "Déclenche lorsqu'un nouvel enregistrement est créé dans la table spécifiée",
|
||||
"Triggers when a record is updated in the specified table.": "Déclenche lorsqu'un enregistrement est mis à jour dans la table spécifiée."
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "データベースとスプレッドシートを組み合わせた共同作業管理プラットフォーム。",
|
||||
"API Key": "API キー",
|
||||
"Account ID": "アカウントID",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.",
|
||||
"Create a Record": "レコードを作成",
|
||||
"Update a Record": "レコードを更新",
|
||||
"Delete a Record": "レコードを削除",
|
||||
"Upload File": "ファイルをアップロード",
|
||||
"Find Records": "レコードを検索",
|
||||
"Get a Record": "レコードを取得する",
|
||||
"Custom API Call": "カスタムAPI通話",
|
||||
"Creates a new record in the specified table.": "指定したテーブルに新しいレコードを作成します。",
|
||||
"Updates an existing record in the specified table": "指定したテーブル内の既存のレコードを更新します",
|
||||
"Deletes a record from the specified table": "指定したテーブルからレコードを削除します",
|
||||
"Uploads a file and attaches it to a record.": "ファイルをアップロードし、レコードに添付します。",
|
||||
"Searches for records in the specified table based on criteria.": "指定したテーブル内のレコードを条件に基づいて検索します。",
|
||||
"Retrieves a specific record by ID": "IDで特定のレコードを取得します。",
|
||||
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
|
||||
"Solution": "解決策",
|
||||
"Table": "表",
|
||||
"Fields": "フィールド",
|
||||
"Record ID": "レコードID",
|
||||
"Search Field": "検索フィールド",
|
||||
"File": "ファイル",
|
||||
"Search Value": "検索値",
|
||||
"Method": "方法",
|
||||
"Headers": "ヘッダー",
|
||||
"Query Parameters": "クエリパラメータ",
|
||||
"Body": "本文",
|
||||
"Response is Binary ?": "応答はバイナリですか?",
|
||||
"No Error on Failure": "失敗時にエラーはありません",
|
||||
"Timeout (in seconds)": "タイムアウト(秒)",
|
||||
"The file to upload": "アップロードするファイル",
|
||||
"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 Record": "新しいレコード",
|
||||
"Updated Record": "更新されたレコード",
|
||||
"Triggers when a new record is created in the specified table": "指定したテーブルに新しいレコードが作成されたときにトリガーされます。",
|
||||
"Triggers when a record is updated in the specified table.": "指定したテーブルでレコードが更新されたときにトリガーされます。"
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Het gezamenlijke werkbeheerplatform dat databases combineert met spreadsheets.",
|
||||
"API Key": "API Sleutel",
|
||||
"Account ID": "ID klant",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n Je kunt een API-sleutel verkrijgen door naar **Mijn profiel>API Key** te navigeren vanuit de rechterbovenhoek.\n \n U kunt een Account ID verkrijgen via de browser URL. of voorbeeld, als de smartsuite workspace URL https://app.smartsuite.com/xyz/home is, dan is uw account ID **xyz**.",
|
||||
"Create a Record": "Een record maken",
|
||||
"Update a Record": "Een record bijwerken",
|
||||
"Delete a Record": "Een record verwijderen",
|
||||
"Upload File": "Bestand uploaden",
|
||||
"Find Records": "Records zoeken",
|
||||
"Get a Record": "Krijg een record",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Creates a new record in the specified table.": "Maakt een nieuwe record aan in de opgegeven tabel.",
|
||||
"Updates an existing record in the specified table": "Werkt een bestaand record in de opgegeven tabel bij",
|
||||
"Deletes a record from the specified table": "Verwijdert een record van de opgegeven tabel",
|
||||
"Uploads a file and attaches it to a record.": "Uploaden van een bestand en hecht het aan een record.",
|
||||
"Searches for records in the specified table based on criteria.": "Zoekt naar records in de opgegeven tabel op basis van criteria.",
|
||||
"Retrieves a specific record by ID": "Ophalen van een specifiek record via ID",
|
||||
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
|
||||
"Solution": "Oplossing",
|
||||
"Table": "Tabel",
|
||||
"Fields": "Velden",
|
||||
"Record ID": "Record ID",
|
||||
"Search Field": "Zoek veld",
|
||||
"File": "Bestand",
|
||||
"Search Value": "Waarde zoeken",
|
||||
"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)",
|
||||
"The file to upload": "Het bestand om te uploaden",
|
||||
"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 Record": "Nieuwe Record",
|
||||
"Updated Record": "Bijgewerkt Record",
|
||||
"Triggers when a new record is created in the specified table": "Triggert wanneer een nieuwe record wordt aangemaakt in de opgegeven tabel",
|
||||
"Triggers when a record is updated in the specified table.": "Activeert wanneer een record wordt bijgewerkt in de opgegeven tabel."
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Plataforma de gerenciamento de trabalho colaborativo combinando bancos de dados com planilhas.",
|
||||
"API Key": "Chave de API",
|
||||
"Account ID": "ID da Conta",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "U\n Você pode obter chave de API navegando até **Minha chave de perfil->API** no canto superior direito.\n \n Você pode obter o ID da conta através do URL do navegador. ou exemplo, se o URL do espaço de trabalho smartsuite for https://app.smartsuite.com/xyz/home, seu ID de conta é **xyz**.",
|
||||
"Create a Record": "Criar um Registro",
|
||||
"Update a Record": "Atualizar um Registro",
|
||||
"Delete a Record": "Apagar um registro",
|
||||
"Upload File": "Enviar Arquivo",
|
||||
"Find Records": "Encontrar registros",
|
||||
"Get a Record": "Obter um Registro",
|
||||
"Custom API Call": "Chamada de API personalizada",
|
||||
"Creates a new record in the specified table.": "Cria um novo registro na tabela especificada.",
|
||||
"Updates an existing record in the specified table": "Atualiza um registro existente na tabela especificada",
|
||||
"Deletes a record from the specified table": "Exclui um registro da tabela especificada",
|
||||
"Uploads a file and attaches it to a record.": "Carrega um arquivo e o anexa a um registro.",
|
||||
"Searches for records in the specified table based on criteria.": "Busca registros na tabela especificada com base em critérios.",
|
||||
"Retrieves a specific record by ID": "Recupera um registro específico por ID",
|
||||
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
|
||||
"Solution": "Soluções",
|
||||
"Table": "Classificações",
|
||||
"Fields": "campos",
|
||||
"Record ID": "ID do Registro",
|
||||
"Search Field": "Campo de pesquisa",
|
||||
"File": "Arquivo",
|
||||
"Search Value": "Pesquisar Valor",
|
||||
"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)",
|
||||
"The file to upload": "O arquivo para enviar",
|
||||
"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 Record": "Novo Registro",
|
||||
"Updated Record": "Registro atualizado",
|
||||
"Triggers when a new record is created in the specified table": "Aciona quando um novo registro é criado na tabela especificada",
|
||||
"Triggers when a record is updated in the specified table.": "Aciona quando um registro é atualizado na tabela especificada."
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"SmartSuite": "SmartSuite",
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Платформа совместного управления работой, объединяющая базы данных с электронными таблицами.",
|
||||
"API Key": "Ключ API",
|
||||
"Account ID": "ID клиента",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n Вы можете получить ключ API, перейдя по ссылке **My Profile->API Key** в правом верхнем углу.\n \n Вы можете получить идентификатор аккаунта по URL-адресу браузера. или, например, если URL-адрес smartsuite workspace https://app.smartsuite.com/xyz/home, ваш идентификатор учетной записи **xyz**.",
|
||||
"Create a Record": "Создать запись",
|
||||
"Update a Record": "Обновить запись",
|
||||
"Delete a Record": "Удалить запись",
|
||||
"Upload File": "Загрузить файл",
|
||||
"Find Records": "Найти записи",
|
||||
"Get a Record": "Получить запись",
|
||||
"Custom API Call": "Пользовательский вызов API",
|
||||
"Creates a new record in the specified table.": "Создает новую запись в указанной таблице.",
|
||||
"Updates an existing record in the specified table": "Обновляет существующую запись в указанной таблице",
|
||||
"Deletes a record from the specified table": "Удаляет запись из указанной таблицы",
|
||||
"Uploads a file and attaches it to a record.": "Загружает файл и прикрепляет его к записи.",
|
||||
"Searches for records in the specified table based on criteria.": "Поиск записей в указанной таблице на основе критериев.",
|
||||
"Retrieves a specific record by ID": "Извлекает определенную запись по ID",
|
||||
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
|
||||
"Solution": "Решение",
|
||||
"Table": "Таблица",
|
||||
"Fields": "Поля",
|
||||
"Record ID": "ID записи",
|
||||
"Search Field": "Поле поиска",
|
||||
"File": "Файл",
|
||||
"Search Value": "Поисковое значение",
|
||||
"Method": "Метод",
|
||||
"Headers": "Заголовки",
|
||||
"Query Parameters": "Параметры запроса",
|
||||
"Body": "Тело",
|
||||
"No Error on Failure": "Нет ошибок при ошибке",
|
||||
"Timeout (in seconds)": "Таймаут (в секундах)",
|
||||
"The file to upload": "Файл для загрузки",
|
||||
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
|
||||
"GET": "ПОЛУЧИТЬ",
|
||||
"POST": "ПОСТ",
|
||||
"PATCH": "ПАТЧ",
|
||||
"PUT": "ПОКУПИТЬ",
|
||||
"DELETE": "УДАЛИТЬ",
|
||||
"HEAD": "HEAD",
|
||||
"New Record": "Новая запись",
|
||||
"Updated Record": "Запись обновлена",
|
||||
"Triggers when a new record is created in the specified table": "Триггеры при создании новой записи в указанной таблице",
|
||||
"Triggers when a record is updated in the specified table.": "Триггеры при обновлении записи в указанной таблице."
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Collaborative work management platform combining databases with spreadsheets.",
|
||||
"API Key": "API Key",
|
||||
"Account ID": "Account ID",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.",
|
||||
"Create a Record": "Create a Record",
|
||||
"Update a Record": "Update a Record",
|
||||
"Delete a Record": "Delete a Record",
|
||||
"Upload File": "Upload File",
|
||||
"Find Records": "Find Records",
|
||||
"Get a Record": "Get a Record",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Creates a new record in the specified table.": "Creates a new record in the specified table.",
|
||||
"Updates an existing record in the specified table": "Updates an existing record in the specified table",
|
||||
"Deletes a record from the specified table": "Deletes a record from the specified table",
|
||||
"Uploads a file and attaches it to a record.": "Uploads a file and attaches it to a record.",
|
||||
"Searches for records in the specified table based on criteria.": "Searches for records in the specified table based on criteria.",
|
||||
"Retrieves a specific record by ID": "Retrieves a specific record by ID",
|
||||
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
|
||||
"Solution": "Solution",
|
||||
"Table": "Table",
|
||||
"Fields": "Fields",
|
||||
"Record ID": "Record ID",
|
||||
"Search Field": "Search Field",
|
||||
"File": "File",
|
||||
"Search Value": "Search Value",
|
||||
"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)",
|
||||
"The file to upload": "The file to upload",
|
||||
"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 Record": "New Record",
|
||||
"Updated Record": "Updated Record",
|
||||
"Triggers when a new record is created in the specified table": "Triggers when a new record is created in the specified table",
|
||||
"Triggers when a record is updated in the specified table.": "Triggers when a record is updated in the specified table."
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"SmartSuite": "SmartSuite",
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Collaborative work management platform combining databases with spreadsheets.",
|
||||
"API Key": "API Key",
|
||||
"Account ID": "Account ID",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.",
|
||||
"Create a Record": "Create a Record",
|
||||
"Update a Record": "Update a Record",
|
||||
"Delete a Record": "Delete a Record",
|
||||
"Upload File": "Upload File",
|
||||
"Find Records": "Find Records",
|
||||
"Get a Record": "Get a Record",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Creates a new record in the specified table.": "Creates a new record in the specified table.",
|
||||
"Updates an existing record in the specified table": "Updates an existing record in the specified table",
|
||||
"Deletes a record from the specified table": "Deletes a record from the specified table",
|
||||
"Uploads a file and attaches it to a record.": "Uploads a file and attaches it to a record.",
|
||||
"Searches for records in the specified table based on criteria.": "Searches for records in the specified table based on criteria.",
|
||||
"Retrieves a specific record by ID": "Retrieves a specific record by ID",
|
||||
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
|
||||
"Solution": "Solution",
|
||||
"Table": "Table",
|
||||
"Fields": "Fields",
|
||||
"Record ID": "Record ID",
|
||||
"Search Field": "Search Field",
|
||||
"File": "File",
|
||||
"Search Value": "Search Value",
|
||||
"Method": "Method",
|
||||
"Headers": "Headers",
|
||||
"Query Parameters": "Query Parameters",
|
||||
"Body": "Body",
|
||||
"No Error on Failure": "No Error on Failure",
|
||||
"Timeout (in seconds)": "Timeout (in seconds)",
|
||||
"The file to upload": "The file to upload",
|
||||
"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 Record": "New Record",
|
||||
"Updated Record": "Updated Record",
|
||||
"Triggers when a new record is created in the specified table": "Triggers when a new record is created in the specified table",
|
||||
"Triggers when a record is updated in the specified table.": "Triggers when a record is updated in the specified table."
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Collaborative work management platform combining databases with spreadsheets.": "Collaborative work management platform combining databases with spreadsheets.",
|
||||
"API Key": "API 密钥",
|
||||
"Account ID": "Account ID",
|
||||
"\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.": "\n You can obtain API key by navigate to **My Profile->API Key** from top-right corner.\n \n You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.",
|
||||
"Create a Record": "Create a Record",
|
||||
"Update a Record": "Update a Record",
|
||||
"Delete a Record": "Delete a Record",
|
||||
"Upload File": "Upload File",
|
||||
"Find Records": "Find Records",
|
||||
"Get a Record": "Get a Record",
|
||||
"Custom API Call": "自定义 API 呼叫",
|
||||
"Creates a new record in the specified table.": "Creates a new record in the specified table.",
|
||||
"Updates an existing record in the specified table": "Updates an existing record in the specified table",
|
||||
"Deletes a record from the specified table": "Deletes a record from the specified table",
|
||||
"Uploads a file and attaches it to a record.": "Uploads a file and attaches it to a record.",
|
||||
"Searches for records in the specified table based on criteria.": "Searches for records in the specified table based on criteria.",
|
||||
"Retrieves a specific record by ID": "Retrieves a specific record by ID",
|
||||
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
|
||||
"Solution": "Solution",
|
||||
"Table": "表",
|
||||
"Fields": "Fields",
|
||||
"Record ID": "Record ID",
|
||||
"Search Field": "Search Field",
|
||||
"File": "文件",
|
||||
"Search Value": "搜索值",
|
||||
"Method": "方法",
|
||||
"Headers": "信头",
|
||||
"Query Parameters": "查询参数",
|
||||
"Body": "正文内容",
|
||||
"Response is Binary ?": "Response is Binary ?",
|
||||
"No Error on Failure": "失败时没有错误",
|
||||
"Timeout (in seconds)": "超时(秒)",
|
||||
"The file to upload": "The file to upload",
|
||||
"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 Record": "New Record",
|
||||
"Updated Record": "Updated Record",
|
||||
"Triggers when a new record is created in the specified table": "Triggers when a new record is created in the specified table",
|
||||
"Triggers when a record is updated in the specified table.": "Triggers when a record is updated in the specified table."
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import {
|
||||
createPiece,
|
||||
PiecePropValueSchema,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { PieceCategory } from '@activepieces/shared';
|
||||
import { smartsuiteAuth } from './lib/auth';
|
||||
|
||||
// Actions
|
||||
import { createRecord } from './lib/actions/create-record';
|
||||
import { updateRecord } from './lib/actions/update-record';
|
||||
import { deleteRecord } from './lib/actions/delete-record';
|
||||
import { uploadFile } from './lib/actions/upload-file';
|
||||
import { findRecords } from './lib/actions/find-records';
|
||||
import { getRecord } from './lib/actions/get-record';
|
||||
|
||||
// Triggers
|
||||
import { newRecord } from './lib/triggers/new-record';
|
||||
import { updatedRecord } from './lib/triggers/updated-record';
|
||||
import { createCustomApiCallAction } from '@activepieces/pieces-common';
|
||||
import { SMARTSUITE_API_URL } from './lib/common/constants';
|
||||
|
||||
export const smartsuite = createPiece({
|
||||
displayName: 'SmartSuite',
|
||||
description:
|
||||
'Collaborative work management platform combining databases with spreadsheets.',
|
||||
logoUrl: 'https://cdn.activepieces.com/pieces/smartsuite.png',
|
||||
categories: [PieceCategory.PRODUCTIVITY],
|
||||
auth: smartsuiteAuth,
|
||||
minimumSupportedRelease: '0.30.0',
|
||||
authors: ['Kunal-Darekar', 'kishanprmr'],
|
||||
actions: [
|
||||
createRecord,
|
||||
updateRecord,
|
||||
deleteRecord,
|
||||
uploadFile,
|
||||
findRecords,
|
||||
getRecord,
|
||||
createCustomApiCallAction({
|
||||
auth: smartsuiteAuth,
|
||||
baseUrl: () => SMARTSUITE_API_URL,
|
||||
authMapping: async (auth) => {
|
||||
const authValue = auth
|
||||
return {
|
||||
Authorization: `Token ${auth.props.apiKey}`,
|
||||
'ACCOUNT-ID': auth.props.accountId,
|
||||
};
|
||||
},
|
||||
}),
|
||||
],
|
||||
triggers: [newRecord, updatedRecord],
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { smartsuiteCommon, formatRecordFields, transformRecordFields } from '../common/props';
|
||||
import { smartSuiteApiCall, TableStucture } from '../common';
|
||||
|
||||
export const createRecord = createAction({
|
||||
name: 'create_record',
|
||||
displayName: 'Create a Record',
|
||||
description: 'Creates a new record in the specified table.',
|
||||
auth: smartsuiteAuth,
|
||||
props: {
|
||||
solutionId: smartsuiteCommon.solutionId,
|
||||
tableId: smartsuiteCommon.tableId,
|
||||
fields: smartsuiteCommon.tableFields,
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const { tableId, fields, solutionId } = propsValue;
|
||||
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
|
||||
const formattedFields = formatRecordFields(tableSchema, fields);
|
||||
|
||||
try {
|
||||
const response = await smartSuiteApiCall<Record<string, any>>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: `/applications/${tableId}/records/`,
|
||||
body: formattedFields,
|
||||
});
|
||||
|
||||
const transformedFields = transformRecordFields(tableSchema, response);
|
||||
|
||||
return transformedFields;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 422) {
|
||||
throw new Error(
|
||||
`Invalid request: ${
|
||||
error.response?.body?.message || 'Missing required fields or invalid data'
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 403) {
|
||||
throw new Error('You do not have permission to create records in this table');
|
||||
}
|
||||
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(`Solution or table not found: ${solutionId}/${tableId}`);
|
||||
}
|
||||
|
||||
throw new Error(`Failed to create record: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod} from '@activepieces/pieces-common';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { smartsuiteCommon } from '../common/props';
|
||||
import { smartSuiteApiCall } from '../common';
|
||||
|
||||
export const deleteRecord = createAction({
|
||||
name: 'delete_record',
|
||||
displayName: 'Delete a Record',
|
||||
description: 'Deletes a record from the specified table',
|
||||
auth: smartsuiteAuth,
|
||||
props: {
|
||||
solutionId: smartsuiteCommon.solutionId,
|
||||
tableId: smartsuiteCommon.tableId,
|
||||
recordId: smartsuiteCommon.recordId,
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const { tableId, recordId } = propsValue;
|
||||
|
||||
try {
|
||||
const response = await smartSuiteApiCall<Record<string, any>>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.DELETE,
|
||||
resourceUri: `/applications/${tableId}/records/${recordId}/`,
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(`Record with ID ${recordId} not found in table ${tableId}`);
|
||||
}
|
||||
|
||||
if (error.response?.status === 403) {
|
||||
throw new Error('You do not have permission to delete this record');
|
||||
}
|
||||
|
||||
throw new Error(`Failed to delete record: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,136 @@
|
||||
import {
|
||||
DropdownOption,
|
||||
Property,
|
||||
createAction,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { smartsuiteCommon, transformRecordFields } from '../common/props';
|
||||
import { smartSuiteApiCall, TableStucture } from '../common';
|
||||
|
||||
export const findRecords = createAction({
|
||||
name: 'find_records',
|
||||
displayName: 'Find Records',
|
||||
description: 'Searches for records in the specified table based on criteria.',
|
||||
auth: smartsuiteAuth,
|
||||
props: {
|
||||
solutionId: smartsuiteCommon.solutionId,
|
||||
tableId: smartsuiteCommon.tableId,
|
||||
searchField: Property.Dropdown({
|
||||
auth: smartsuiteAuth,
|
||||
displayName: 'Search Field',
|
||||
required: true,
|
||||
refreshers: ['tableId'],
|
||||
options: async ({ auth, tableId }) => {
|
||||
if (!auth || !tableId) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please connect your account first.',
|
||||
};
|
||||
}
|
||||
|
||||
const { apiKey, accountId } = auth.props;
|
||||
|
||||
const response = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey,
|
||||
accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}`,
|
||||
});
|
||||
|
||||
const options: DropdownOption<string>[] = [];
|
||||
|
||||
for (const field of response.structure) {
|
||||
if (field.params.is_auto_generated || field.params.system) {
|
||||
continue;
|
||||
}
|
||||
|
||||
options.push({ label: field.label, value: field.slug });
|
||||
}
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
}),
|
||||
searchValue: Property.ShortText({
|
||||
displayName: 'Search Value',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const { solutionId, tableId, searchField, searchValue } = propsValue;
|
||||
|
||||
try {
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
|
||||
const matchedRecords = [];
|
||||
|
||||
const qs = { limit: 100, offset: 0 };
|
||||
let hasMore = true;
|
||||
|
||||
do {
|
||||
const response = await smartSuiteApiCall<{ items: Record<string, any>[] }>({
|
||||
accountId: auth.props.accountId,
|
||||
apiKey: auth.props.apiKey,
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: `/applications/${tableId}/records/list/`,
|
||||
query: qs,
|
||||
body: {
|
||||
filter: {
|
||||
operator: 'and',
|
||||
fields: [
|
||||
{
|
||||
field: searchField,
|
||||
comparison: 'is',
|
||||
value: searchValue,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
const items = response.items || [];
|
||||
matchedRecords.push(...items);
|
||||
|
||||
hasMore = items.length > 0;
|
||||
if (hasMore) {
|
||||
qs.offset = Number(qs.offset) + Number(qs.limit);
|
||||
}
|
||||
} while (hasMore);
|
||||
|
||||
return {
|
||||
found: matchedRecords.length > 0,
|
||||
result: matchedRecords.map((record) => transformRecordFields(tableSchema, record)),
|
||||
};
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 400) {
|
||||
throw new Error(
|
||||
`Invalid filter or sort criteria: ${
|
||||
error.response?.body?.message || 'Please check your filter JSON format'
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 403) {
|
||||
throw new Error('You do not have permission to access this table');
|
||||
}
|
||||
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(`Solution or table not found: ${solutionId}/${tableId}`);
|
||||
}
|
||||
|
||||
throw new Error(`Failed to find records: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { smartsuiteCommon, transformRecordFields } from '../common/props';
|
||||
import { smartSuiteApiCall, TableStucture } from '../common';
|
||||
|
||||
export const getRecord = createAction({
|
||||
name: 'get_record',
|
||||
displayName: 'Get a Record',
|
||||
description: 'Retrieves a specific record by ID',
|
||||
auth: smartsuiteAuth,
|
||||
props: {
|
||||
solutionId: smartsuiteCommon.solutionId,
|
||||
tableId: smartsuiteCommon.tableId,
|
||||
recordId: smartsuiteCommon.recordId,
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const { tableId, recordId } = propsValue;
|
||||
|
||||
try {
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
const response = await smartSuiteApiCall<Record<string, any>>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}/records/${recordId}/`,
|
||||
});
|
||||
|
||||
const transformedFields = transformRecordFields(tableSchema, response);
|
||||
|
||||
return transformedFields;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 403) {
|
||||
throw new Error('You do not have permission to access this record');
|
||||
}
|
||||
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(`Record with ID ${recordId} not found in table ${tableId}`);
|
||||
}
|
||||
|
||||
throw new Error(`Failed to get record: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { smartsuiteCommon, formatRecordFields, transformRecordFields } from '../common/props';
|
||||
import { smartSuiteApiCall, TableStucture } from '../common';
|
||||
|
||||
export const updateRecord = createAction({
|
||||
name: 'update_record',
|
||||
displayName: 'Update a Record',
|
||||
description: 'Updates an existing record in the specified table',
|
||||
auth: smartsuiteAuth,
|
||||
props: {
|
||||
solutionId: smartsuiteCommon.solutionId,
|
||||
tableId: smartsuiteCommon.tableId,
|
||||
recordId: smartsuiteCommon.recordId,
|
||||
fields: smartsuiteCommon.tableFields,
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const { tableId, recordId, fields } = propsValue;
|
||||
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
|
||||
const formattedFields = formatRecordFields(tableSchema, fields);
|
||||
|
||||
try {
|
||||
const response = await smartSuiteApiCall<Record<string, any>>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.PATCH,
|
||||
resourceUri: `/applications/${tableId}/records/${recordId}/`,
|
||||
body: formattedFields,
|
||||
});
|
||||
|
||||
const transformedFields = transformRecordFields(tableSchema, response);
|
||||
|
||||
return transformedFields;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 422) {
|
||||
throw new Error(
|
||||
`Invalid request: ${error.response?.body?.message || 'Invalid data format'}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 403) {
|
||||
throw new Error('You do not have permission to update this record');
|
||||
}
|
||||
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(`Record with ID ${recordId} not found in table ${tableId}`);
|
||||
}
|
||||
|
||||
throw new Error(`Failed to update record: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,123 @@
|
||||
import {
|
||||
DropdownOption,
|
||||
PiecePropValueSchema,
|
||||
Property,
|
||||
createAction,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { smartsuiteCommon, transformRecordFields } from '../common/props';
|
||||
import { smartSuiteApiCall, TableStucture } from '../common';
|
||||
import FormData from 'form-data';
|
||||
|
||||
export const uploadFile = createAction({
|
||||
name: 'upload_file',
|
||||
displayName: 'Upload File',
|
||||
description: 'Uploads a file and attaches it to a record.',
|
||||
auth: smartsuiteAuth,
|
||||
props: {
|
||||
solutionId: smartsuiteCommon.solutionId,
|
||||
tableId: smartsuiteCommon.tableId,
|
||||
recordId: smartsuiteCommon.recordId,
|
||||
field: Property.Dropdown({
|
||||
auth: smartsuiteAuth,
|
||||
displayName: 'Search Field',
|
||||
required: true,
|
||||
refreshers: ['tableId'],
|
||||
options: async ({ auth, tableId }) => {
|
||||
if (!auth || !tableId) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please connect your account first.',
|
||||
};
|
||||
}
|
||||
|
||||
const { apiKey, accountId } = auth.props;
|
||||
|
||||
const response = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey,
|
||||
accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}`,
|
||||
});
|
||||
|
||||
const options: DropdownOption<string>[] = [];
|
||||
|
||||
for (const field of response.structure) {
|
||||
if (field.field_type === 'filefield') {
|
||||
options.push({ label: field.label, value: field.slug });
|
||||
}
|
||||
}
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
}),
|
||||
file: Property.File({
|
||||
displayName: 'File',
|
||||
description: 'The file to upload',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const { recordId, field, tableId, file } = propsValue;
|
||||
try {
|
||||
const formData = new FormData();
|
||||
|
||||
formData.append('files', Buffer.from(file.base64, 'base64'), file.filename);
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `https://app.smartsuite.com/api/v1/recordfiles/${tableId}/${recordId}/${field}/`,
|
||||
body: formData,
|
||||
headers: {
|
||||
...formData.getHeaders(),
|
||||
Authorization: `Token ${auth.props.apiKey}`,
|
||||
'ACCOUNT-ID': auth.props.accountId,
|
||||
},
|
||||
});
|
||||
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: auth.props.apiKey,
|
||||
accountId: auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
|
||||
const formattedFields = transformRecordFields(tableSchema, response.body);
|
||||
|
||||
return formattedFields;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 400) {
|
||||
throw new Error(
|
||||
`Invalid file format or size: ${
|
||||
error.response?.body?.message || 'File may be too large or in an unsupported format'
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 403) {
|
||||
throw new Error('You do not have permission to upload files to this record');
|
||||
}
|
||||
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(
|
||||
`Record with ID ${recordId} not found or field ${field} is not a file field`,
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 413) {
|
||||
throw new Error('File is too large. SmartSuite has file size limits');
|
||||
}
|
||||
|
||||
throw new Error(`Failed to upload file: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { PieceAuth, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { smartSuiteApiCall } from './common';
|
||||
|
||||
export const smartsuiteAuth = PieceAuth.CustomAuth({
|
||||
description: `
|
||||
You can obtain API key by navigate to **My Profile->API Key** from top-right corner.
|
||||
|
||||
You can obtain Account ID from browser URL.For example, if smartsuite workspace URL is https://app.smartsuite.com/xyz/home, your Account ID is **xyz**.`,
|
||||
required: true,
|
||||
props: {
|
||||
apiKey: PieceAuth.SecretText({
|
||||
displayName: 'API Key',
|
||||
required: true,
|
||||
}),
|
||||
accountId: Property.ShortText({
|
||||
displayName: 'Account ID',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
validate: async ({ auth }) => {
|
||||
try {
|
||||
await smartSuiteApiCall({
|
||||
apiKey: auth.apiKey,
|
||||
accountId: auth.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/solutions',
|
||||
});
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Invalid Credentials.',
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
export const SMARTSUITE_API_URL = 'https://app.smartsuite.com/api/v1';
|
||||
export const SMARTSUITE_WEBHOOKS_API_URL = 'https://webhooks.smartsuite.com/smartsuite.webhooks.engine.Webhooks';
|
||||
|
||||
export const WEBHOOK_EVENTS = {
|
||||
RECORD_CREATED: 'RECORD_CREATED',
|
||||
RECORD_UPDATED: 'RECORD_UPDATED',
|
||||
RECORD_DELETED: 'RECORD_DELETED',
|
||||
};
|
||||
|
||||
export const API_ENDPOINTS = {
|
||||
// Webhooks
|
||||
CREATE_WEBHOOK: '/CreateWebhook',
|
||||
LIST_WEBHOOKS: '/ListWebhooks',
|
||||
GET_WEBHOOK: '/GetWebhook',
|
||||
UPDATE_WEBHOOK: '/UpdateWebhook',
|
||||
DELETE_WEBHOOK: '/DeleteWebhook',
|
||||
LIST_EVENTS: '/ListEvents',
|
||||
};
|
||||
@@ -0,0 +1,104 @@
|
||||
import {
|
||||
httpClient,
|
||||
HttpMessageBody,
|
||||
HttpMethod,
|
||||
HttpRequest,
|
||||
QueryParams,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { SMARTSUITE_API_URL } from './constants';
|
||||
import { isNil } from '@activepieces/shared';
|
||||
|
||||
export type SmartSuiteApiCallParams = {
|
||||
apiKey: string;
|
||||
accountId: string;
|
||||
method: HttpMethod;
|
||||
resourceUri: string;
|
||||
query?: Record<string, string | number | string[] | undefined>;
|
||||
body?: any;
|
||||
};
|
||||
|
||||
export type PaginatedResponse<T> = {
|
||||
results: T[];
|
||||
count: number;
|
||||
next?: string;
|
||||
previous?: string;
|
||||
};
|
||||
|
||||
export type TableStucture = {
|
||||
slug: string;
|
||||
label: string;
|
||||
field_type: string;
|
||||
params: {
|
||||
is_auto_generated: boolean;
|
||||
system: boolean;
|
||||
choices?: { label: string; value: string }[];
|
||||
};
|
||||
};
|
||||
|
||||
export async function smartSuiteApiCall<T extends HttpMessageBody>({
|
||||
apiKey,
|
||||
accountId,
|
||||
method,
|
||||
resourceUri,
|
||||
query,
|
||||
body,
|
||||
}: SmartSuiteApiCallParams): Promise<T> {
|
||||
const qs: QueryParams = {};
|
||||
|
||||
if (query) {
|
||||
for (const [key, value] of Object.entries(query)) {
|
||||
if (value !== null && value !== undefined) {
|
||||
qs[key] = String(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const request: HttpRequest = {
|
||||
method,
|
||||
url: SMARTSUITE_API_URL + resourceUri,
|
||||
headers: {
|
||||
Authorization: `Token ${apiKey}`,
|
||||
'ACCOUNT-ID': accountId,
|
||||
},
|
||||
queryParams: qs,
|
||||
body,
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest<T>(request);
|
||||
return response.body;
|
||||
}
|
||||
|
||||
export async function smartSuitePaginatedApiCall<T extends HttpMessageBody>({
|
||||
apiKey,
|
||||
accountId,
|
||||
method,
|
||||
resourceUri,
|
||||
query,
|
||||
body,
|
||||
}: SmartSuiteApiCallParams): Promise<T[]> {
|
||||
const qs = { ...(query || {}), limit: 100, offset: 0 };
|
||||
|
||||
const resultData: T[] = [];
|
||||
let hasMore = true;
|
||||
|
||||
do {
|
||||
const response = await smartSuiteApiCall<PaginatedResponse<T>>({
|
||||
accountId,
|
||||
apiKey,
|
||||
method,
|
||||
resourceUri,
|
||||
query: qs,
|
||||
body,
|
||||
});
|
||||
|
||||
const items = response.results || [];
|
||||
resultData.push(...items);
|
||||
|
||||
hasMore = !!response.next && items.length > 0;
|
||||
if (hasMore) {
|
||||
qs.offset = Number(qs.offset) + Number(qs.limit);
|
||||
}
|
||||
} while (hasMore);
|
||||
|
||||
return resultData;
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
import { Property, DynamicPropsValue, PiecePropValueSchema } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { smartSuiteApiCall, smartSuitePaginatedApiCall, TableStucture } from '.';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { isNil } from '@activepieces/shared';
|
||||
|
||||
export const smartsuiteCommon = {
|
||||
solutionId: Property.Dropdown({
|
||||
auth: smartsuiteAuth,
|
||||
displayName: 'Solution',
|
||||
required: true,
|
||||
refreshers: [],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please enter your API key first.',
|
||||
};
|
||||
}
|
||||
|
||||
const { apiKey, accountId } = auth.props;
|
||||
|
||||
try {
|
||||
const response = await smartSuitePaginatedApiCall<{
|
||||
name: string;
|
||||
id: string;
|
||||
hidden: boolean;
|
||||
}>({
|
||||
apiKey,
|
||||
accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/solutions',
|
||||
});
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: response
|
||||
.filter((solution) => !solution.hidden)
|
||||
.map((solution) => {
|
||||
return {
|
||||
label: solution.name,
|
||||
value: solution.id,
|
||||
};
|
||||
}),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Error fetching solutions. Please check your API key.',
|
||||
};
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
tableId: Property.Dropdown({
|
||||
auth: smartsuiteAuth,
|
||||
displayName: 'Table',
|
||||
required: true,
|
||||
refreshers: ['solutionId'],
|
||||
options: async ({ auth, solutionId }) => {
|
||||
if (!auth || !solutionId) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: solutionId
|
||||
? 'Please select a solution first.'
|
||||
: 'Please enter your API key first.',
|
||||
};
|
||||
}
|
||||
|
||||
const { apiKey, accountId } = auth.props;
|
||||
|
||||
try {
|
||||
const response = await smartSuitePaginatedApiCall<{
|
||||
id: string;
|
||||
name: string;
|
||||
}>({
|
||||
apiKey,
|
||||
accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/applications',
|
||||
query: {
|
||||
solution: solutionId as string,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: response.map((table) => {
|
||||
return {
|
||||
label: table.name,
|
||||
value: table.id,
|
||||
};
|
||||
}),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Error fetching tables. Please check your permissions.',
|
||||
};
|
||||
}
|
||||
},
|
||||
}),
|
||||
tableFields: Property.DynamicProperties({
|
||||
auth: smartsuiteAuth,
|
||||
displayName: 'Fields',
|
||||
required: true,
|
||||
refreshers: ['solutionId', 'tableId'],
|
||||
props: async ({ auth, solutionId, tableId }) => {
|
||||
if (!auth || !solutionId || !tableId) {
|
||||
return {};
|
||||
}
|
||||
const { apiKey, accountId } = auth.props;
|
||||
|
||||
try {
|
||||
const response = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey,
|
||||
accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${tableId}`,
|
||||
});
|
||||
|
||||
const fieldProperties: DynamicPropsValue = {};
|
||||
|
||||
for (const field of response.structure) {
|
||||
if (
|
||||
field.params.is_auto_generated ||
|
||||
field.params.system ||
|
||||
[
|
||||
'countfield',
|
||||
'autonumberfield',
|
||||
'rollupfield',
|
||||
'votefield',
|
||||
'filefield',
|
||||
'fullnamefield',
|
||||
'addressfield',
|
||||
'daterangefield',
|
||||
'duedatefield',
|
||||
'userfield',
|
||||
'checklistfield',
|
||||
'signaturefield',
|
||||
'subitemsfield',
|
||||
'buttonfield',
|
||||
'lookupfield',
|
||||
'phonefield',
|
||||
].includes(field.field_type)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (field.field_type) {
|
||||
case 'recordtitlefield':
|
||||
case 'textfield':
|
||||
case 'emailfield':
|
||||
case 'linkfield':
|
||||
case 'durationfield':
|
||||
case 'numberfield':
|
||||
case 'colorpickerfield':
|
||||
case 'percentfield':
|
||||
case 'currencyfield':
|
||||
fieldProperties[field.slug] = Property.ShortText({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'timefield':
|
||||
fieldProperties[field.slug] = Property.ShortText({
|
||||
displayName: field.label,
|
||||
description: 'Provide value in HH:mm:ss format.',
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'richtextareafield':
|
||||
case 'textareafield':
|
||||
fieldProperties[field.slug] = Property.LongText({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'numbersliderfield':
|
||||
case 'percentcompletefield':
|
||||
case 'ratingfield':
|
||||
fieldProperties[field.slug] = Property.Number({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'yesnofield':
|
||||
fieldProperties[field.slug] = Property.Checkbox({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'datefield':
|
||||
fieldProperties[field.slug] = Property.DateTime({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'statusfield':
|
||||
case 'singleselectfield':
|
||||
fieldProperties[field.slug] = Property.StaticDropdown({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
options: {
|
||||
disabled: false,
|
||||
options: field.params.choices
|
||||
? field.params.choices.map((choice) => ({
|
||||
label: choice.label,
|
||||
value: choice.value,
|
||||
}))
|
||||
: [],
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'linkedrecordfield':
|
||||
fieldProperties[field.slug] = Property.Array({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
description: 'Provide Record IDs to link.',
|
||||
});
|
||||
break;
|
||||
case 'multipleselectfield':
|
||||
fieldProperties[field.slug] = Property.StaticMultiSelectDropdown({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
options: {
|
||||
disabled: false,
|
||||
options: field.params.choices
|
||||
? field.params.choices.map((choice) => ({
|
||||
label: choice.label,
|
||||
value: choice.value,
|
||||
}))
|
||||
: [],
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fieldProperties;
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
recordId: Property.ShortText({
|
||||
displayName: 'Record ID',
|
||||
required: true,
|
||||
}),
|
||||
};
|
||||
|
||||
export function formatRecordFields(
|
||||
tableSchema: TableStucture[],
|
||||
tableValues: Record<string, any>,
|
||||
): Record<string, any> {
|
||||
const formattedFields: Record<string, any> = {};
|
||||
|
||||
const fieldMap: Record<string, string> = tableSchema.reduce((acc, field) => {
|
||||
acc[field.slug] = field.field_type;
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
|
||||
for (const [key, value] of Object.entries(tableValues)) {
|
||||
if (isNil(value) || value === '') continue;
|
||||
|
||||
const fieldType = fieldMap[key];
|
||||
switch (fieldType) {
|
||||
case 'recordtitlefield':
|
||||
case 'textfield':
|
||||
case 'durationfield':
|
||||
case 'timefield':
|
||||
case 'textareafield':
|
||||
case 'numberfield':
|
||||
case 'numbersliderfield':
|
||||
case 'percentfield':
|
||||
case 'currencyfield':
|
||||
case 'percentcompletefield':
|
||||
case 'ratingfield':
|
||||
case 'yesnofield':
|
||||
case 'singleselectfield':
|
||||
formattedFields[key] = value;
|
||||
break;
|
||||
case 'emailfield':
|
||||
case 'linkfield':
|
||||
formattedFields[key] = [value];
|
||||
break;
|
||||
case 'colorpickerfield':
|
||||
formattedFields[key] = [
|
||||
{
|
||||
value,
|
||||
},
|
||||
];
|
||||
break;
|
||||
case 'datefield':
|
||||
formattedFields[key] = {
|
||||
date: value,
|
||||
include_time: false,
|
||||
};
|
||||
break;
|
||||
case 'statusfield':
|
||||
formattedFields[key] = {
|
||||
value,
|
||||
};
|
||||
break;
|
||||
case 'richtextareafield':
|
||||
formattedFields[key] = {
|
||||
data: {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: value,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
break;
|
||||
case 'linkedrecordfield':
|
||||
case 'multipleselectfield': {
|
||||
if (Array.isArray(value) && value.length > 0) {
|
||||
formattedFields[key] = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return formattedFields;
|
||||
}
|
||||
|
||||
export function transformRecordFields(
|
||||
tableSchema: TableStucture[],
|
||||
tableValues: Record<string, any>,
|
||||
) {
|
||||
const fieldMap: Record<string, string> = tableSchema.reduce((acc, field) => {
|
||||
acc[field.slug] = field.label;
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
|
||||
const transformedFields: Record<string, any> = {};
|
||||
|
||||
for (const [slug, value] of Object.entries(tableValues)) {
|
||||
const label = fieldMap[slug] ?? slug;
|
||||
transformedFields[label] = value;
|
||||
}
|
||||
|
||||
return transformedFields;
|
||||
}
|
||||
@@ -0,0 +1,441 @@
|
||||
import { TriggerStrategy, createTrigger } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { smartsuiteCommon, transformRecordFields } from '../common/props';
|
||||
import { SMARTSUITE_WEBHOOKS_API_URL, API_ENDPOINTS, WEBHOOK_EVENTS } from '../common/constants';
|
||||
import { smartSuiteApiCall, TableStucture } from '../common';
|
||||
|
||||
export const newRecord = createTrigger({
|
||||
name: 'new_record',
|
||||
displayName: 'New Record',
|
||||
description: 'Triggers when a new record is created in the specified table',
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
auth: smartsuiteAuth,
|
||||
props: {
|
||||
solutionId: smartsuiteCommon.solutionId,
|
||||
tableId: smartsuiteCommon.tableId,
|
||||
},
|
||||
|
||||
async onEnable(context) {
|
||||
const { solutionId, tableId } = context.propsValue;
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${SMARTSUITE_WEBHOOKS_API_URL}${API_ENDPOINTS.CREATE_WEBHOOK}`,
|
||||
body: {
|
||||
webhook: {
|
||||
filter: {
|
||||
applications: {
|
||||
application_ids: [tableId],
|
||||
},
|
||||
},
|
||||
kinds: [WEBHOOK_EVENTS.RECORD_CREATED],
|
||||
locator: {
|
||||
account_id: context.auth.props.accountId, // This will be filled by SmartSuite based on the API key
|
||||
solution_id: solutionId,
|
||||
},
|
||||
notification_status: {
|
||||
enabled: {
|
||||
url: context.webhookUrl,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Token ${context.auth.props.apiKey}`,
|
||||
'ACCOUNT-ID': context.auth.props.accountId,
|
||||
},
|
||||
});
|
||||
await context.store.put('new_record', response.body.webhook.webhook_id);
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
const webhookId = await context.store.get('new_record');
|
||||
|
||||
if (webhookId) {
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${SMARTSUITE_WEBHOOKS_API_URL}${API_ENDPOINTS.DELETE_WEBHOOK}`,
|
||||
body: {
|
||||
webhook_id: webhookId,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Token ${context.auth.props.apiKey}`,
|
||||
'ACCOUNT-ID': context.auth.props.accountId,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async test(context) {
|
||||
const { tableId } = context.propsValue;
|
||||
const response = await smartSuiteApiCall<{ items: Record<string, any>[] }>({
|
||||
accountId: context.auth.props.accountId,
|
||||
apiKey: context.auth.props.apiKey,
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: `/applications/${tableId}/records/list/`,
|
||||
query: { limit: '5', offset: '0' },
|
||||
});
|
||||
const items = response.items || [];
|
||||
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: context.auth.props.apiKey,
|
||||
accountId: context.auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${context.propsValue.tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
|
||||
return items.map((item) => transformRecordFields(tableSchema, item));
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const webhookPayload = context.payload.body as {
|
||||
webhookId: string;
|
||||
locator: {
|
||||
accountId: string;
|
||||
solutionId: string;
|
||||
};
|
||||
};
|
||||
|
||||
let pageToken = (await context.store.get('pageToken')) ?? '';
|
||||
|
||||
if (!webhookPayload || !webhookPayload.webhookId || !webhookPayload.locator) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const events = [];
|
||||
|
||||
let hasMore = true;
|
||||
|
||||
do {
|
||||
const response = await httpClient.sendRequest<{
|
||||
events: { record_event_data: { data: Record<string, any> } }[];
|
||||
next_page_token: string;
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
url: `${SMARTSUITE_WEBHOOKS_API_URL}${API_ENDPOINTS.LIST_EVENTS}`,
|
||||
body: {
|
||||
webhook_id: webhookPayload.webhookId,
|
||||
page_size: '50',
|
||||
page_token: pageToken,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Token ${context.auth.props.apiKey}`,
|
||||
'ACCOUNT-ID': context.auth.props.accountId,
|
||||
},
|
||||
});
|
||||
|
||||
pageToken = response.body.next_page_token;
|
||||
|
||||
const items = response.body.events ?? [];
|
||||
|
||||
events.push(...items);
|
||||
|
||||
hasMore = items.length > 0;
|
||||
} while (hasMore);
|
||||
|
||||
await context.store.put('pageToken', pageToken);
|
||||
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: context.auth.props.apiKey,
|
||||
accountId: context.auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${context.propsValue.tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
|
||||
return events.map((event) => transformRecordFields(tableSchema, event.record_event_data.data));
|
||||
},
|
||||
|
||||
sampleData: {
|
||||
Title: 'First Record',
|
||||
Description: {
|
||||
data: {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'xxzxzxzxzxz',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'xzxzxz',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'xzxz',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
html: '<div class="rendered"><p class="align-left" >xxzxzxzxzxz</p><p class="align-left" >xzxzxz</p><p class="align-left" >xzxz</p></div>',
|
||||
preview: 'xxzxzxzxzxz\n xzxzxz\n xzxz',
|
||||
yjsData: '',
|
||||
},
|
||||
Status: {
|
||||
value: 'backlog',
|
||||
updated_on: '2025-05-25T14:52:17.110000Z',
|
||||
},
|
||||
'First Created': {
|
||||
on: '2025-05-25T14:52:16.977000Z',
|
||||
by: '682c72c82336bf787bb5c7a0',
|
||||
},
|
||||
'Last Updated': {
|
||||
on: '2025-05-26T10:52:14.987027Z',
|
||||
by: '682c72c82336bf787bb5c7a0',
|
||||
},
|
||||
'Followed by': [],
|
||||
'Open Comments': 0,
|
||||
'Auto Number': 1,
|
||||
'text-field': 'text',
|
||||
'Text Area': 'area',
|
||||
Number: '12.0',
|
||||
'Number Slider': 33,
|
||||
Percent: '12.0',
|
||||
Currency: '12',
|
||||
'Yes / No': true,
|
||||
'Single Select': '3u0Cl',
|
||||
'Multiple Select': ['bZfFn', 'LvQIv'],
|
||||
Date: {
|
||||
date: '2025-05-30T00:00:00Z',
|
||||
include_time: false,
|
||||
},
|
||||
'Full Name': {
|
||||
title: '',
|
||||
first_name: 'john',
|
||||
middle_name: '',
|
||||
last_name: 'doe',
|
||||
sys_root: 'john doe',
|
||||
},
|
||||
Email: ['johndoe@gmail.com'],
|
||||
Phone: [
|
||||
{
|
||||
phone_country: 'IN',
|
||||
phone_number: '',
|
||||
phone_extension: '',
|
||||
phone_type: 2,
|
||||
sys_root: '',
|
||||
sys_title: '',
|
||||
},
|
||||
],
|
||||
Address: {
|
||||
location_address: '',
|
||||
location_address2: '',
|
||||
location_zip: '',
|
||||
location_country: '',
|
||||
location_state: '',
|
||||
location_city: '',
|
||||
location_longitude: '72.2',
|
||||
location_latitude: '21.12',
|
||||
sys_root: '',
|
||||
},
|
||||
Link: ['https://github.com'],
|
||||
'Files and Images': [
|
||||
{
|
||||
handle: 'CeRMEqhySiFboDMkiZlx',
|
||||
metadata: {
|
||||
container: 'smart-suite-media',
|
||||
filename: 'spotify.png',
|
||||
key: 'PAfWmgwRnOhw6KJygepi_spotify.png',
|
||||
mimetype: 'image/png',
|
||||
size: 23422,
|
||||
},
|
||||
transform_options: {},
|
||||
created_on: '2025-05-26T10:47:12.586000Z',
|
||||
updated_on: '2025-05-26T10:47:12.586000Z',
|
||||
description: '',
|
||||
video_conversion_status: '',
|
||||
video_thumbnail_handle: '',
|
||||
converted_video_handle: '',
|
||||
file_type: 'image',
|
||||
icon: 'image',
|
||||
},
|
||||
{
|
||||
handle: 'GUQyUrvYQrpswR97N8jT',
|
||||
metadata: {
|
||||
container: 'smart-suite-media',
|
||||
filename: 'zagomail.png',
|
||||
key: 'CSHRsjZRVS6HIFvJEfqQ_zagomail.png',
|
||||
mimetype: 'image/png',
|
||||
size: 96995,
|
||||
},
|
||||
transform_options: {},
|
||||
created_on: '2025-05-26T10:49:41.891000Z',
|
||||
updated_on: '2025-05-26T10:49:41.891000Z',
|
||||
description: '',
|
||||
video_conversion_status: '',
|
||||
video_thumbnail_handle: '',
|
||||
converted_video_handle: '',
|
||||
file_type: 'image',
|
||||
icon: 'image',
|
||||
},
|
||||
{
|
||||
handle: 'eUhDadE9Q3yFz3XLCEgC',
|
||||
metadata: {
|
||||
container: 'smart-suite-media',
|
||||
filename: 'coda.png',
|
||||
key: 'BrE3gQheS108HgFd1HYT_coda.png',
|
||||
mimetype: 'image/png',
|
||||
size: 880,
|
||||
},
|
||||
transform_options: {},
|
||||
created_on: '2025-05-26T10:52:14.981371Z',
|
||||
updated_on: '2025-05-26T10:52:14.981377Z',
|
||||
description: '',
|
||||
video_conversion_status: '',
|
||||
video_thumbnail_handle: '',
|
||||
converted_video_handle: '',
|
||||
file_type: 'image',
|
||||
icon: 'image',
|
||||
},
|
||||
],
|
||||
SmartDoc: {
|
||||
data: {},
|
||||
html: '',
|
||||
preview: '',
|
||||
yjsData: 'AAA=',
|
||||
},
|
||||
'Link to Tasks': ['682c72c84386b2737cab1bd0', '682c72c84386b2737cab1bcf'],
|
||||
Time: '00:15:00',
|
||||
'Date Range': {
|
||||
from_date: {
|
||||
date: '2025-05-25T00:00:00Z',
|
||||
include_time: false,
|
||||
},
|
||||
to_date: {
|
||||
date: '2025-05-29T00:00:00Z',
|
||||
include_time: false,
|
||||
},
|
||||
},
|
||||
'Percent Complete': 43,
|
||||
'Status 1': {
|
||||
value: 'backlog',
|
||||
updated_on: '2025-05-25T14:52:17.111000Z',
|
||||
},
|
||||
'Due Date': {
|
||||
from_date: {
|
||||
date: null,
|
||||
include_time: false,
|
||||
},
|
||||
to_date: {
|
||||
date: '2025-05-30T00:00:00Z',
|
||||
include_time: false,
|
||||
},
|
||||
status_is_completed: false,
|
||||
status_updated_on: '2025-05-25T14:52:17.110000Z',
|
||||
},
|
||||
'Assigned To': ['682c72c82336bf787bb5c7a0'],
|
||||
Duration: '60.0',
|
||||
'Time Tracking Log': {
|
||||
time_track_logs: [],
|
||||
total_duration: 0,
|
||||
},
|
||||
Checklist: {
|
||||
items: [
|
||||
{
|
||||
id: 'f93c6845-5823-4d73-945c-f10038125ae1',
|
||||
content: {
|
||||
data: {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'ss',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
html: '<div class="rendered"><p class="align-left" >ss</p></div>',
|
||||
preview: 'ss',
|
||||
},
|
||||
completed: false,
|
||||
assignee: null,
|
||||
due_date: null,
|
||||
completed_at: null,
|
||||
},
|
||||
],
|
||||
total_items: 1,
|
||||
completed_items: 0,
|
||||
},
|
||||
Rating: 5,
|
||||
Vote: {
|
||||
total_votes: 0,
|
||||
votes: [],
|
||||
},
|
||||
Tag: ['68333302894412d3ffa5f55a'],
|
||||
'Record ID': '68332ea07e87b585dca5f3da',
|
||||
Signature: {
|
||||
text: '',
|
||||
image_base64: '',
|
||||
},
|
||||
Count: '2',
|
||||
'Sub-Items': {
|
||||
count: 0,
|
||||
items: [],
|
||||
},
|
||||
Button: null,
|
||||
'Color Picker': [
|
||||
{
|
||||
value: '#715E5E',
|
||||
},
|
||||
],
|
||||
'IP Address': [
|
||||
{
|
||||
address: '192.121.0.0',
|
||||
country_code: 'gb',
|
||||
},
|
||||
],
|
||||
Rollup: '9.0',
|
||||
Lookup: [['Phase Gate'], ['Market Research and Design Conceptualization']],
|
||||
id: '68332ea07e87b585dca5f3da',
|
||||
application_slug: 'sc4keiie',
|
||||
application_id: '682c745daf3f33a521fc8c8c',
|
||||
ranking: {
|
||||
default: 'aaaaaaaouq',
|
||||
},
|
||||
deleted_date: {
|
||||
date: null,
|
||||
include_time: false,
|
||||
},
|
||||
deleted_by: null,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,445 @@
|
||||
import { TriggerStrategy, createTrigger } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
|
||||
import { smartsuiteAuth } from '../auth';
|
||||
import { smartsuiteCommon, transformRecordFields } from '../common/props';
|
||||
import {
|
||||
SMARTSUITE_WEBHOOKS_API_URL,
|
||||
API_ENDPOINTS,
|
||||
WEBHOOK_EVENTS,
|
||||
} from '../common/constants';
|
||||
import { smartSuiteApiCall, TableStucture } from '../common';
|
||||
|
||||
export const updatedRecord = createTrigger({
|
||||
name: 'updated_record',
|
||||
displayName: 'Updated Record',
|
||||
description: 'Triggers when a record is updated in the specified table.',
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
auth: smartsuiteAuth,
|
||||
props: {
|
||||
solutionId: smartsuiteCommon.solutionId,
|
||||
tableId: smartsuiteCommon.tableId,
|
||||
},
|
||||
|
||||
async onEnable(context) {
|
||||
const { solutionId, tableId } = context.propsValue;
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${SMARTSUITE_WEBHOOKS_API_URL}${API_ENDPOINTS.CREATE_WEBHOOK}`,
|
||||
body: {
|
||||
webhook: {
|
||||
filter: {
|
||||
applications: {
|
||||
application_ids: [tableId],
|
||||
},
|
||||
},
|
||||
kinds: [WEBHOOK_EVENTS.RECORD_UPDATED],
|
||||
locator: {
|
||||
account_id: context.auth.props.accountId, // This will be filled by SmartSuite based on the API key
|
||||
solution_id: solutionId,
|
||||
},
|
||||
notification_status: {
|
||||
enabled: {
|
||||
url: context.webhookUrl,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Token ${context.auth.props.apiKey}`,
|
||||
'ACCOUNT-ID': context.auth.props.accountId,
|
||||
},
|
||||
});
|
||||
await context.store.put('updated_record', response.body.webhook.webhook_id);
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
|
||||
const webhookId = await context.store.get('updated_record');
|
||||
|
||||
if (webhookId) {
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${SMARTSUITE_WEBHOOKS_API_URL}${API_ENDPOINTS.DELETE_WEBHOOK}`,
|
||||
body: {
|
||||
webhook_id: webhookId,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Token ${context.auth.props.apiKey}`,
|
||||
'ACCOUNT-ID': context.auth.props.accountId,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
async test(context) {
|
||||
const { tableId } = context.propsValue;
|
||||
const response = await smartSuiteApiCall<{ items: Record<string, any>[] }>({
|
||||
accountId: context.auth.props.accountId,
|
||||
apiKey: context.auth.props.apiKey,
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: `/applications/${tableId}/records/list/`,
|
||||
query: { limit: '5', offset: '0' },
|
||||
});
|
||||
const items = response.items || [];
|
||||
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: context.auth.props.apiKey,
|
||||
accountId: context.auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${context.propsValue.tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
|
||||
return items.map((item) => transformRecordFields(tableSchema, item));
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const webhookPayload = context.payload.body as {
|
||||
webhookId: string;
|
||||
locator: {
|
||||
accountId: string;
|
||||
solutionId: string;
|
||||
};
|
||||
};
|
||||
|
||||
let pageToken = (await context.store.get('pageToken')) ?? '';
|
||||
|
||||
if (!webhookPayload || !webhookPayload.webhookId || !webhookPayload.locator) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const events = [];
|
||||
|
||||
let hasMore = true;
|
||||
|
||||
do {
|
||||
const response = await httpClient.sendRequest<{
|
||||
events: { record_event_data: { data: Record<string, any> } }[];
|
||||
next_page_token: string;
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
url: `${SMARTSUITE_WEBHOOKS_API_URL}${API_ENDPOINTS.LIST_EVENTS}`,
|
||||
body: {
|
||||
webhook_id: webhookPayload.webhookId,
|
||||
page_size: '50',
|
||||
page_token: pageToken,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Token ${context.auth.props.apiKey}`,
|
||||
'ACCOUNT-ID': context.auth.props.accountId,
|
||||
},
|
||||
});
|
||||
|
||||
pageToken = response.body.next_page_token;
|
||||
|
||||
const items = response.body.events ?? [];
|
||||
|
||||
events.push(...items);
|
||||
|
||||
hasMore = items.length > 0;
|
||||
} while (hasMore);
|
||||
|
||||
await context.store.put('pageToken', pageToken);
|
||||
|
||||
const tableResponse = await smartSuiteApiCall<{
|
||||
structure: TableStucture[];
|
||||
}>({
|
||||
apiKey: context.auth.props.apiKey,
|
||||
accountId: context.auth.props.accountId,
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/applications/${context.propsValue.tableId}`,
|
||||
});
|
||||
const tableSchema = tableResponse.structure;
|
||||
|
||||
return events.map((event) => transformRecordFields(tableSchema, event.record_event_data.data));
|
||||
},
|
||||
|
||||
sampleData: {
|
||||
Title: 'First Record',
|
||||
Description: {
|
||||
data: {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'xxzxzxzxzxz',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'xzxzxz',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'xzxz',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
html: '<div class="rendered"><p class="align-left" >xxzxzxzxzxz</p><p class="align-left" >xzxzxz</p><p class="align-left" >xzxz</p></div>',
|
||||
preview: 'xxzxzxzxzxz\n xzxzxz\n xzxz',
|
||||
yjsData: '',
|
||||
},
|
||||
Status: {
|
||||
value: 'backlog',
|
||||
updated_on: '2025-05-25T14:52:17.110000Z',
|
||||
},
|
||||
'First Created': {
|
||||
on: '2025-05-25T14:52:16.977000Z',
|
||||
by: '682c72c82336bf787bb5c7a0',
|
||||
},
|
||||
'Last Updated': {
|
||||
on: '2025-05-26T10:52:14.987027Z',
|
||||
by: '682c72c82336bf787bb5c7a0',
|
||||
},
|
||||
'Followed by': [],
|
||||
'Open Comments': 0,
|
||||
'Auto Number': 1,
|
||||
'text-field': 'text',
|
||||
'Text Area': 'area',
|
||||
Number: '12.0',
|
||||
'Number Slider': 33,
|
||||
Percent: '12.0',
|
||||
Currency: '12',
|
||||
'Yes / No': true,
|
||||
'Single Select': '3u0Cl',
|
||||
'Multiple Select': ['bZfFn', 'LvQIv'],
|
||||
Date: {
|
||||
date: '2025-05-30T00:00:00Z',
|
||||
include_time: false,
|
||||
},
|
||||
'Full Name': {
|
||||
title: '',
|
||||
first_name: 'john',
|
||||
middle_name: '',
|
||||
last_name: 'doe',
|
||||
sys_root: 'john doe',
|
||||
},
|
||||
Email: ['johndoe@gmail.com'],
|
||||
Phone: [
|
||||
{
|
||||
phone_country: 'IN',
|
||||
phone_number: '',
|
||||
phone_extension: '',
|
||||
phone_type: 2,
|
||||
sys_root: '',
|
||||
sys_title: '',
|
||||
},
|
||||
],
|
||||
Address: {
|
||||
location_address: '',
|
||||
location_address2: '',
|
||||
location_zip: '',
|
||||
location_country: '',
|
||||
location_state: '',
|
||||
location_city: '',
|
||||
location_longitude: '72.2',
|
||||
location_latitude: '21.12',
|
||||
sys_root: '',
|
||||
},
|
||||
Link: ['https://github.com'],
|
||||
'Files and Images': [
|
||||
{
|
||||
handle: 'CeRMEqhySiFboDMkiZlx',
|
||||
metadata: {
|
||||
container: 'smart-suite-media',
|
||||
filename: 'spotify.png',
|
||||
key: 'PAfWmgwRnOhw6KJygepi_spotify.png',
|
||||
mimetype: 'image/png',
|
||||
size: 23422,
|
||||
},
|
||||
transform_options: {},
|
||||
created_on: '2025-05-26T10:47:12.586000Z',
|
||||
updated_on: '2025-05-26T10:47:12.586000Z',
|
||||
description: '',
|
||||
video_conversion_status: '',
|
||||
video_thumbnail_handle: '',
|
||||
converted_video_handle: '',
|
||||
file_type: 'image',
|
||||
icon: 'image',
|
||||
},
|
||||
{
|
||||
handle: 'GUQyUrvYQrpswR97N8jT',
|
||||
metadata: {
|
||||
container: 'smart-suite-media',
|
||||
filename: 'zagomail.png',
|
||||
key: 'CSHRsjZRVS6HIFvJEfqQ_zagomail.png',
|
||||
mimetype: 'image/png',
|
||||
size: 96995,
|
||||
},
|
||||
transform_options: {},
|
||||
created_on: '2025-05-26T10:49:41.891000Z',
|
||||
updated_on: '2025-05-26T10:49:41.891000Z',
|
||||
description: '',
|
||||
video_conversion_status: '',
|
||||
video_thumbnail_handle: '',
|
||||
converted_video_handle: '',
|
||||
file_type: 'image',
|
||||
icon: 'image',
|
||||
},
|
||||
{
|
||||
handle: 'eUhDadE9Q3yFz3XLCEgC',
|
||||
metadata: {
|
||||
container: 'smart-suite-media',
|
||||
filename: 'coda.png',
|
||||
key: 'BrE3gQheS108HgFd1HYT_coda.png',
|
||||
mimetype: 'image/png',
|
||||
size: 880,
|
||||
},
|
||||
transform_options: {},
|
||||
created_on: '2025-05-26T10:52:14.981371Z',
|
||||
updated_on: '2025-05-26T10:52:14.981377Z',
|
||||
description: '',
|
||||
video_conversion_status: '',
|
||||
video_thumbnail_handle: '',
|
||||
converted_video_handle: '',
|
||||
file_type: 'image',
|
||||
icon: 'image',
|
||||
},
|
||||
],
|
||||
SmartDoc: {
|
||||
data: {},
|
||||
html: '',
|
||||
preview: '',
|
||||
yjsData: 'AAA=',
|
||||
},
|
||||
'Link to Tasks': ['682c72c84386b2737cab1bd0', '682c72c84386b2737cab1bcf'],
|
||||
Time: '00:15:00',
|
||||
'Date Range': {
|
||||
from_date: {
|
||||
date: '2025-05-25T00:00:00Z',
|
||||
include_time: false,
|
||||
},
|
||||
to_date: {
|
||||
date: '2025-05-29T00:00:00Z',
|
||||
include_time: false,
|
||||
},
|
||||
},
|
||||
'Percent Complete': 43,
|
||||
'Status 1': {
|
||||
value: 'backlog',
|
||||
updated_on: '2025-05-25T14:52:17.111000Z',
|
||||
},
|
||||
'Due Date': {
|
||||
from_date: {
|
||||
date: null,
|
||||
include_time: false,
|
||||
},
|
||||
to_date: {
|
||||
date: '2025-05-30T00:00:00Z',
|
||||
include_time: false,
|
||||
},
|
||||
status_is_completed: false,
|
||||
status_updated_on: '2025-05-25T14:52:17.110000Z',
|
||||
},
|
||||
'Assigned To': ['682c72c82336bf787bb5c7a0'],
|
||||
Duration: '60.0',
|
||||
'Time Tracking Log': {
|
||||
time_track_logs: [],
|
||||
total_duration: 0,
|
||||
},
|
||||
Checklist: {
|
||||
items: [
|
||||
{
|
||||
id: 'f93c6845-5823-4d73-945c-f10038125ae1',
|
||||
content: {
|
||||
data: {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
attrs: {
|
||||
textAlign: 'left',
|
||||
size: 'medium',
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'ss',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
html: '<div class="rendered"><p class="align-left" >ss</p></div>',
|
||||
preview: 'ss',
|
||||
},
|
||||
completed: false,
|
||||
assignee: null,
|
||||
due_date: null,
|
||||
completed_at: null,
|
||||
},
|
||||
],
|
||||
total_items: 1,
|
||||
completed_items: 0,
|
||||
},
|
||||
Rating: 5,
|
||||
Vote: {
|
||||
total_votes: 0,
|
||||
votes: [],
|
||||
},
|
||||
Tag: ['68333302894412d3ffa5f55a'],
|
||||
'Record ID': '68332ea07e87b585dca5f3da',
|
||||
Signature: {
|
||||
text: '',
|
||||
image_base64: '',
|
||||
},
|
||||
Count: '2',
|
||||
'Sub-Items': {
|
||||
count: 0,
|
||||
items: [],
|
||||
},
|
||||
Button: null,
|
||||
'Color Picker': [
|
||||
{
|
||||
value: '#715E5E',
|
||||
},
|
||||
],
|
||||
'IP Address': [
|
||||
{
|
||||
address: '192.121.0.0',
|
||||
country_code: 'gb',
|
||||
},
|
||||
],
|
||||
Rollup: '9.0',
|
||||
Lookup: [['Phase Gate'], ['Market Research and Design Conceptualization']],
|
||||
id: '68332ea07e87b585dca5f3da',
|
||||
application_slug: 'sc4keiie',
|
||||
application_id: '682c745daf3f33a521fc8c8c',
|
||||
ranking: {
|
||||
default: 'aaaaaaaouq',
|
||||
},
|
||||
deleted_date: {
|
||||
date: null,
|
||||
include_time: false,
|
||||
},
|
||||
deleted_by: null,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
Reference in New Issue
Block a user