Compare commits
1 Commits
aut-1374
...
test-async
Author | SHA1 | Date | |
---|---|---|---|
![]() |
424c251dde |
@@ -5,11 +5,8 @@ BACKEND_PORT=3000
|
||||
WEB_PORT=3001
|
||||
|
||||
echo "Configuring backend environment variables..."
|
||||
|
||||
cd packages/backend
|
||||
|
||||
rm -rf .env
|
||||
|
||||
echo "
|
||||
PORT=$BACKEND_PORT
|
||||
WEB_APP_URL=http://localhost:$WEB_PORT
|
||||
@@ -24,35 +21,24 @@ WEBHOOK_SECRET_KEY=sample_webhook_secret_key
|
||||
APP_SECRET_KEY=sample_app_secret_key
|
||||
REDIS_HOST=redis
|
||||
SERVE_WEB_APP_SEPARATELY=true" >> .env
|
||||
|
||||
echo "Installing backend dependencies..."
|
||||
|
||||
yarn
|
||||
|
||||
cd $CURRENT_DIR
|
||||
|
||||
echo "Configuring web environment variables..."
|
||||
|
||||
cd packages/web
|
||||
|
||||
rm -rf .env
|
||||
|
||||
echo "
|
||||
PORT=$WEB_PORT
|
||||
REACT_APP_BACKEND_URL=http://localhost:$BACKEND_PORT
|
||||
" >> .env
|
||||
|
||||
echo "Installing web dependencies..."
|
||||
|
||||
yarn
|
||||
|
||||
cd $CURRENT_DIR
|
||||
|
||||
echo "Installing and linking dependencies..."
|
||||
yarn
|
||||
yarn lerna bootstrap
|
||||
|
||||
echo "Migrating database..."
|
||||
|
||||
cd packages/backend
|
||||
|
||||
yarn db:migrate
|
||||
yarn db:seed:user
|
||||
|
||||
echo "Done!"
|
||||
echo "Done!"
|
9
.github/workflows/backend.yml
vendored
9
.github/workflows/backend.yml
vendored
@@ -41,11 +41,8 @@ jobs:
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
working-directory: packages/backend
|
||||
run: cd packages/backend && yarn
|
||||
- name: Copy .env-example.test file to .env.test
|
||||
run: cp .env-example.test .env.test
|
||||
working-directory: packages/backend
|
||||
run: cd packages/backend && cp .env-example.test .env.test
|
||||
- name: Run tests
|
||||
run: yarn test:coverage
|
||||
working-directory: packages/backend
|
||||
run: cd packages/backend && yarn test
|
||||
|
30
.github/workflows/ci.yml
vendored
30
.github/workflows/ci.yml
vendored
@@ -18,13 +18,11 @@ jobs:
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: packages/backend/yarn.lock
|
||||
cache-dependency-path: yarn.lock
|
||||
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||
- run: yarn --frozen-lockfile
|
||||
working-directory: packages/backend
|
||||
- run: yarn lint
|
||||
working-directory: packages/backend
|
||||
- run: cd packages/backend && yarn lint
|
||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||
start-backend-server:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -37,13 +35,11 @@ jobs:
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: packages/backend/yarn.lock
|
||||
cache-dependency-path: yarn.lock
|
||||
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||
- run: yarn --frozen-lockfile
|
||||
working-directory: packages/backend
|
||||
- run: yarn start
|
||||
working-directory: packages/backend
|
||||
- run: yarn --frozen-lockfile && yarn lerna bootstrap
|
||||
- run: cd packages/backend && yarn start
|
||||
env:
|
||||
ENCRYPTION_KEY: sample_encryption_key
|
||||
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
||||
@@ -59,13 +55,11 @@ jobs:
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: packages/backend/yarn.lock
|
||||
cache-dependency-path: yarn.lock
|
||||
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||
- run: yarn --frozen-lockfile
|
||||
working-directory: packages/backend
|
||||
- run: yarn start:worker
|
||||
working-directory: packages/backend
|
||||
- run: yarn --frozen-lockfile && yarn lerna bootstrap
|
||||
- run: cd packages/backend && yarn start:worker
|
||||
env:
|
||||
ENCRYPTION_KEY: sample_encryption_key
|
||||
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
||||
@@ -81,13 +75,11 @@ jobs:
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: packages/web/yarn.lock
|
||||
cache-dependency-path: yarn.lock
|
||||
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||
- run: yarn --frozen-lockfile
|
||||
working-directory: packages/web
|
||||
- run: yarn build
|
||||
working-directory: packages/web
|
||||
- run: yarn --frozen-lockfile && yarn lerna bootstrap
|
||||
- run: cd packages/web && yarn build
|
||||
env:
|
||||
CI: false
|
||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||
|
27
.github/workflows/playwright.yml
vendored
27
.github/workflows/playwright.yml
vendored
@@ -3,13 +3,12 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
# TODO: Add pull request after optimizing the total excecution time of the test suite.
|
||||
# pull_request:
|
||||
# paths:
|
||||
# - 'packages/backend/**'
|
||||
# - 'packages/e2e-tests/**'
|
||||
# - 'packages/web/**'
|
||||
# - '!packages/backend/src/apps/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'packages/backend/**'
|
||||
- 'packages/e2e-tests/**'
|
||||
- 'packages/web/**'
|
||||
- '!packages/backend/src/apps/**'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
@@ -59,21 +58,13 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install web dependencies
|
||||
run: yarn
|
||||
working-directory: ./packages/web
|
||||
- name: Install backend dependencies
|
||||
run: yarn
|
||||
working-directory: ./packages/backend
|
||||
- name: Install e2e-tests dependencies
|
||||
run: yarn
|
||||
working-directory: ./packages/e2e-tests
|
||||
- name: Install dependencies
|
||||
run: yarn && yarn lerna bootstrap
|
||||
- name: Install Playwright Browsers
|
||||
run: yarn playwright install --with-deps
|
||||
working-directory: ./packages/e2e-tests
|
||||
- name: Build Automatisch web
|
||||
run: yarn build
|
||||
working-directory: ./packages/web
|
||||
run: yarn build
|
||||
env:
|
||||
# Keep this until we clean up warnings in build processes
|
||||
CI: false
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
|
@@ -1,22 +1,20 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:18-alpine
|
||||
|
||||
ENV PORT=3000
|
||||
ENV PORT 3000
|
||||
|
||||
RUN \
|
||||
apk --no-cache add --virtual build-dependencies python3 build-base git make g++
|
||||
apk --no-cache add --virtual build-dependencies python3 build-base git
|
||||
|
||||
WORKDIR /automatisch
|
||||
|
||||
# copy the app, note .dockerignore
|
||||
COPY . /automatisch
|
||||
|
||||
RUN cd packages/web && yarn
|
||||
RUN yarn
|
||||
|
||||
RUN cd packages/web && yarn build
|
||||
|
||||
RUN cd packages/backend && yarn --production
|
||||
|
||||
RUN \
|
||||
rm -rf /usr/local/share/.cache/ && \
|
||||
apk del build-dependencies
|
||||
|
13
lerna.json
Normal file
13
lerna.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "0.10.0",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"command": {
|
||||
"add": {
|
||||
"exact": true
|
||||
}
|
||||
}
|
||||
}
|
32
package.json
Normal file
32
package.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@automatisch/root",
|
||||
"license": "See LICENSE file",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "lerna run --stream --parallel --scope=@*/{web,backend} dev",
|
||||
"start:web": "lerna run --stream --scope=@*/web dev",
|
||||
"start:backend": "lerna run --stream --scope=@*/backend dev",
|
||||
"build:docs": "cd ./packages/docs && yarn install && yarn build"
|
||||
},
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"nohoist": [
|
||||
"**/babel-loader",
|
||||
"**/webpack",
|
||||
"**/@automatisch/web",
|
||||
"**/ajv"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.13.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"lerna": "^4.0.0",
|
||||
"prettier": "^2.5.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@ import process from 'process';
|
||||
async function fetchAdminRole() {
|
||||
const role = await Role.query()
|
||||
.where({
|
||||
name: 'Admin',
|
||||
key: 'admin',
|
||||
})
|
||||
.limit(1)
|
||||
.first();
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { knexSnakeCaseMappers } from 'objection';
|
||||
import appConfig from './src/config/app.js';
|
||||
import path, { join } from 'path';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const fileExtension = 'js';
|
||||
@@ -20,12 +20,12 @@ const knexConfig = {
|
||||
searchPath: [appConfig.postgresSchema],
|
||||
pool: { min: 0, max: 20 },
|
||||
migrations: {
|
||||
directory: join(__dirname, '/src/db/migrations'),
|
||||
directory: __dirname + '/src/db/migrations',
|
||||
extension: fileExtension,
|
||||
loadExtensions: [`.${fileExtension}`],
|
||||
},
|
||||
seeds: {
|
||||
directory: join(__dirname, '/src/db/seeds'),
|
||||
directory: __dirname + '/src/db/seeds',
|
||||
},
|
||||
...(appConfig.isTest ? knexSnakeCaseMappers() : {}),
|
||||
};
|
||||
|
@@ -5,14 +5,12 @@
|
||||
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "nodemon --exec node src/server.js",
|
||||
"worker": "nodemon --exec node src/worker.js",
|
||||
"dev": "nodemon --watch 'src/**/*.js' --exec 'node' src/server.js",
|
||||
"worker": "nodemon --watch 'src/**/*.js' --exec 'node' src/worker.js",
|
||||
"start": "node src/server.js",
|
||||
"start:worker": "node src/worker.js",
|
||||
"pretest": "APP_ENV=test node ./test/setup/prepare-test-env.js",
|
||||
"test": "APP_ENV=test vitest run",
|
||||
"test:watch": "APP_ENV=test vitest watch",
|
||||
"test:coverage": "yarn test --coverage",
|
||||
"lint": "eslint .",
|
||||
"db:create": "node ./bin/database/create.js",
|
||||
"db:seed:user": "node ./bin/database/seed-user.js",
|
||||
@@ -24,7 +22,8 @@
|
||||
"dependencies": {
|
||||
"@bull-board/express": "^3.10.1",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@faker-js/faker": "^9.2.0",
|
||||
"@graphql-tools/graphql-file-loader": "^7.3.4",
|
||||
"@graphql-tools/load": "^7.5.2",
|
||||
"@node-saml/passport-saml": "^4.0.4",
|
||||
"@rudderstack/rudder-sdk-node": "^1.1.2",
|
||||
"@sentry/node": "^7.42.0",
|
||||
@@ -38,18 +37,18 @@
|
||||
"crypto-js": "^4.1.1",
|
||||
"debug": "~2.6.9",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^8.13.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"express": "~4.18.2",
|
||||
"express-async-errors": "^3.1.1",
|
||||
"express-async-handler": "^1.2.0",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"express-graphql": "^0.12.0",
|
||||
"fast-xml-parser": "^4.0.11",
|
||||
"graphql-middleware": "^6.1.15",
|
||||
"graphql-shield": "^7.5.0",
|
||||
"graphql-tools": "^8.2.0",
|
||||
"handlebars": "^4.7.7",
|
||||
"http-errors": "~1.6.3",
|
||||
"http-proxy-agent": "^7.0.0",
|
||||
"https-proxy-agent": "^7.0.1",
|
||||
"isolated-vm": "^5.0.1",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"knex": "^2.4.0",
|
||||
"libphonenumber-js": "^1.10.48",
|
||||
@@ -66,7 +65,6 @@
|
||||
"pg": "^8.7.1",
|
||||
"php-serialize": "^4.0.2",
|
||||
"pluralize": "^8.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"raw-body": "^2.5.2",
|
||||
"showdown": "^2.1.0",
|
||||
"uuid": "^9.0.1",
|
||||
@@ -98,19 +96,12 @@
|
||||
"url": "https://github.com/automatisch/automatisch/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitest/coverage-v8": "^2.1.5",
|
||||
"node-gyp": "^10.1.0",
|
||||
"nodemon": "^2.0.13",
|
||||
"supertest": "^6.3.3",
|
||||
"vitest": "^2.1.5"
|
||||
"vitest": "^1.1.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"nodemonConfig": {
|
||||
"watch": [
|
||||
"src/"
|
||||
],
|
||||
"ext": "js"
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import createError from 'http-errors';
|
||||
import express from 'express';
|
||||
import 'express-async-errors';
|
||||
import cors from 'cors';
|
||||
|
||||
import appConfig from './config/app.js';
|
||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://api.airtable.com',
|
||||
iconUrl: '{BASE_URL}/apps/airtable/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/airtable/connection',
|
||||
primaryColor: '#FFBF00',
|
||||
primaryColor: 'FFBF00',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://cloud.appwrite.io',
|
||||
iconUrl: '{BASE_URL}/apps/appwrite/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/appwrite/connection',
|
||||
primaryColor: '#FD366E',
|
||||
primaryColor: 'FD366E',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
||||
apiBaseUrl: '',
|
||||
iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/azure-openai/connection',
|
||||
primaryColor: '#000000',
|
||||
primaryColor: '000000',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
|
@@ -7,7 +7,7 @@ export default defineAction({
|
||||
'Creates an attachment of a specified object by given parent ID.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Template Data',
|
||||
label: 'Templete Data',
|
||||
key: 'templateData',
|
||||
type: 'string',
|
||||
required: true,
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://carbone.io',
|
||||
apiBaseUrl: 'https://api.carbone.io',
|
||||
primaryColor: '#6f42c1',
|
||||
primaryColor: '6f42c1',
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
actions,
|
||||
|
@@ -1,72 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create folder',
|
||||
key: 'createFolder',
|
||||
description: 'Creates a new folder.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Workspace',
|
||||
key: 'workspaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorkspaces',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Space',
|
||||
key: 'spaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
dependsOn: ['parameters.workspaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpaces',
|
||||
},
|
||||
{
|
||||
name: 'parameters.workspaceId',
|
||||
value: '{parameters.workspaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Folder Name',
|
||||
key: 'folderName',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const { spaceId, folderName } = $.step.parameters;
|
||||
|
||||
const body = {
|
||||
name: folderName,
|
||||
};
|
||||
|
||||
const { data } = await $.http.post(`/v2/space/${spaceId}/folder`, body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
@@ -1,135 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create list',
|
||||
key: 'createList',
|
||||
description: 'Creates a new list.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Workspace',
|
||||
key: 'workspaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorkspaces',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Space',
|
||||
key: 'spaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
dependsOn: ['parameters.workspaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpaces',
|
||||
},
|
||||
{
|
||||
name: 'parameters.workspaceId',
|
||||
value: '{parameters.workspaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Folder',
|
||||
key: 'folderId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
dependsOn: ['parameters.spaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listFolders',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spaceId',
|
||||
value: '{parameters.spaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'List Name',
|
||||
key: 'listName',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'List Info',
|
||||
key: 'listInfo',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Priority',
|
||||
key: 'priority',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Urgent', value: 1 },
|
||||
{ label: 'High', value: 2 },
|
||||
{ label: 'Normal', value: 3 },
|
||||
{ label: 'Low', value: 4 },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Due Date',
|
||||
key: 'dueDate',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'format: integer <int64>',
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const { folderId, listName, listInfo, priority, dueDate } =
|
||||
$.step.parameters;
|
||||
|
||||
const body = {
|
||||
name: listName,
|
||||
content: listInfo,
|
||||
};
|
||||
|
||||
if (priority) {
|
||||
body.priority = priority;
|
||||
}
|
||||
|
||||
if (dueDate) {
|
||||
body.due_date = dueDate;
|
||||
}
|
||||
|
||||
const { data } = await $.http.post(`/v2/folder/${folderId}/list`, body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
@@ -1,294 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create task',
|
||||
key: 'createTask',
|
||||
description: 'Creates a new task.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Workspace',
|
||||
key: 'workspaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorkspaces',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Space',
|
||||
key: 'spaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
dependsOn: ['parameters.workspaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpaces',
|
||||
},
|
||||
{
|
||||
name: 'parameters.workspaceId',
|
||||
value: '{parameters.workspaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Folder',
|
||||
key: 'folderId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
dependsOn: ['parameters.spaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listFolders',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spaceId',
|
||||
value: '{parameters.spaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'List',
|
||||
key: 'listId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
dependsOn: ['parameters.folderId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listLists',
|
||||
},
|
||||
{
|
||||
name: 'parameters.folderId',
|
||||
value: '{parameters.folderId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Task Name',
|
||||
key: 'taskName',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Task Description',
|
||||
key: 'taskDescription',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Markdown Content',
|
||||
key: 'markdownContent',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'False', value: 'false' },
|
||||
{ label: 'True', value: 'true' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Assignees',
|
||||
key: 'assigneeIds',
|
||||
type: 'dynamic',
|
||||
required: false,
|
||||
description: '',
|
||||
fields: [
|
||||
{
|
||||
label: 'Assignee',
|
||||
key: 'assigneeId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.listId'],
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listAssignees',
|
||||
},
|
||||
{
|
||||
name: 'parameters.listId',
|
||||
value: '{parameters.listId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Task Status',
|
||||
key: 'taskStatus',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.listId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listStatuses',
|
||||
},
|
||||
{
|
||||
name: 'parameters.listId',
|
||||
value: '{parameters.listId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Tags',
|
||||
key: 'tagIds',
|
||||
type: 'dynamic',
|
||||
required: false,
|
||||
description: '',
|
||||
fields: [
|
||||
{
|
||||
label: 'tag',
|
||||
key: 'tagId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listTags',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Priority',
|
||||
key: 'priority',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Urgent', value: 1 },
|
||||
{ label: 'High', value: 2 },
|
||||
{ label: 'Normal', value: 3 },
|
||||
{ label: 'Low', value: 4 },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Due Date',
|
||||
key: 'dueDate',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'format: integer <int64>',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Start Date',
|
||||
key: 'startDate',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'format: integer <int64>',
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
listId,
|
||||
taskName,
|
||||
taskDescription,
|
||||
markdownContent,
|
||||
assigneeIds,
|
||||
taskStatus,
|
||||
tagIds,
|
||||
priority,
|
||||
dueDate,
|
||||
startDate,
|
||||
} = $.step.parameters;
|
||||
|
||||
const tags = tagIds.map((tag) => tag.tagId);
|
||||
const assignees = assigneeIds.map((assignee) =>
|
||||
Number(assignee.assigneeId)
|
||||
);
|
||||
|
||||
const body = {
|
||||
name: taskName,
|
||||
};
|
||||
|
||||
if (assignees.length) {
|
||||
body.assignees = assignees;
|
||||
}
|
||||
|
||||
if (taskStatus) {
|
||||
body.status = taskStatus;
|
||||
}
|
||||
|
||||
if (tags.length) {
|
||||
body.tags = tags;
|
||||
}
|
||||
|
||||
if (priority) {
|
||||
body.priority = priority;
|
||||
}
|
||||
|
||||
if (dueDate) {
|
||||
body.due_date = dueDate;
|
||||
}
|
||||
|
||||
if (startDate) {
|
||||
body.start_date = startDate;
|
||||
}
|
||||
|
||||
if (markdownContent) {
|
||||
body.markdown_description = taskDescription;
|
||||
} else {
|
||||
body.description = taskDescription;
|
||||
}
|
||||
|
||||
const { data } = await $.http.post(`/v2/list/${listId}/task`, body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
@@ -1,82 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Find task by id',
|
||||
key: 'findTaskById',
|
||||
description: 'Finds a task using id.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Task ID',
|
||||
key: 'taskId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Use Custom ID',
|
||||
key: 'useCustomId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'True',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: 'False',
|
||||
value: false,
|
||||
},
|
||||
],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listFieldsWhenUsingCustomId',
|
||||
},
|
||||
{
|
||||
name: 'parameters.useCustomId',
|
||||
value: '{parameters.useCustomId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Include Subtasks?',
|
||||
key: 'includeSubtasks',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'True',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: 'False',
|
||||
value: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const { taskId, useCustomId, includeSubtasks } = $.step.parameters;
|
||||
|
||||
const params = {
|
||||
custom_task_ids: useCustomId || false,
|
||||
include_subtasks: includeSubtasks,
|
||||
};
|
||||
|
||||
const { data } = await $.http.get(`/v2/task/${taskId}`, { params });
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
@@ -1,6 +0,0 @@
|
||||
import createFolder from './create-folder/index.js';
|
||||
import createList from './create-list/index.js';
|
||||
import createTask from './create-task/index.js';
|
||||
import findTaskById from './find-task-by-id/index.js';
|
||||
|
||||
export default [createFolder, createList, createTask, findTaskById];
|
@@ -1,27 +0,0 @@
|
||||
<svg width="185" height="185" viewBox="0 0 185 185" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d)">
|
||||
<rect x="30" y="20" width="125" height="125" rx="62.5" fill="white"/>
|
||||
<rect x="30" y="20" width="125" height="125" rx="62.5" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M55.8789 105.714L69.3974 95.3593C76.5762 104.732 84.1998 109.051 92.6948 109.051C101.143 109.051 108.557 104.781 115.414 95.4832L129.119 105.59C119.232 118.996 106.932 126.079 92.6948 126.079C78.5049 126.079 66.0907 119.046 55.8789 105.714Z" fill="url(#paint0_linear)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M92.6491 60.7078L68.5883 81.4406L57.4727 68.5407L92.6969 38.1885L127.647 68.5644L116.477 81.417L92.6491 60.7078Z" fill="url(#paint1_linear)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d" x="0" y="0" width="185" height="185" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||
<feOffset dy="10"/>
|
||||
<feGaussianBlur stdDeviation="15"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.117647 0 0 0 0 0.211765 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear" x1="55.8789" y1="116.251" x2="129.119" y2="116.251" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#8930FD"/>
|
||||
<stop offset="1" stop-color="#49CCF9"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="57.4727" y1="67.6025" x2="127.647" y2="67.6025" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF02F0"/>
|
||||
<stop offset="1" stop-color="#FFC800"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -1,21 +0,0 @@
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
export default async function generateAuthUrl($) {
|
||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||
(field) => field.key == 'oAuthRedirectUrl'
|
||||
);
|
||||
const redirectUri = oauthRedirectUrlField.value;
|
||||
const state = Math.random().toString();
|
||||
const searchParams = new URLSearchParams({
|
||||
client_id: $.auth.data.clientId,
|
||||
redirect_uri: redirectUri,
|
||||
state,
|
||||
});
|
||||
|
||||
const url = `https://app.clickup.com/api?${searchParams.toString()}`;
|
||||
|
||||
await $.auth.set({
|
||||
url,
|
||||
originalState: state,
|
||||
});
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
import generateAuthUrl from './generate-auth-url.js';
|
||||
import verifyCredentials from './verify-credentials.js';
|
||||
import isStillVerified from './is-still-verified.js';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'oAuthRedirectUrl',
|
||||
label: 'OAuth Redirect URL',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: true,
|
||||
value: '{WEB_APP_URL}/app/clickup/connections/add',
|
||||
placeholder: null,
|
||||
description:
|
||||
'When asked to input a redirect URL in ClickUp, enter the URL above.',
|
||||
clickToCopy: true,
|
||||
},
|
||||
{
|
||||
key: 'clientId',
|
||||
label: 'Client ID',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'clientSecret',
|
||||
label: 'Client Secret',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
],
|
||||
|
||||
generateAuthUrl,
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
};
|
@@ -1,8 +0,0 @@
|
||||
import getCurrentUser from '../common/get-current-user.js';
|
||||
|
||||
const isStillVerified = async ($) => {
|
||||
const currentUser = await getCurrentUser($);
|
||||
return !!currentUser.id;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
@@ -1,31 +0,0 @@
|
||||
import getCurrentUser from '../common/get-current-user.js';
|
||||
|
||||
const verifyCredentials = async ($) => {
|
||||
if ($.auth.data.originalState !== $.auth.data.state) {
|
||||
throw new Error(`The 'state' parameter does not match.`);
|
||||
}
|
||||
|
||||
const { data } = await $.http.post('/v2/oauth/token', {
|
||||
client_id: $.auth.data.clientId,
|
||||
client_secret: $.auth.data.clientSecret,
|
||||
code: $.auth.data.code,
|
||||
});
|
||||
|
||||
await $.auth.set({
|
||||
accessToken: data.access_token,
|
||||
tokenType: data.token_type,
|
||||
});
|
||||
|
||||
const currentUser = await getCurrentUser($);
|
||||
const screenName = [currentUser.username, currentUser.email]
|
||||
.filter(Boolean)
|
||||
.join(' @ ');
|
||||
|
||||
await $.auth.set({
|
||||
clientId: $.auth.data.clientId,
|
||||
clientSecret: $.auth.data.clientSecret,
|
||||
screenName,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
@@ -1,9 +0,0 @@
|
||||
const addAuthHeader = ($, requestConfig) => {
|
||||
if ($.auth.data?.accessToken) {
|
||||
requestConfig.headers.Authorization = `${$.auth.data.tokenType} ${$.auth.data.accessToken}`;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
@@ -1,6 +0,0 @@
|
||||
const getCurrentUser = async ($) => {
|
||||
const { data } = await $.http.get('/v2/user');
|
||||
return data.user;
|
||||
};
|
||||
|
||||
export default getCurrentUser;
|
@@ -1,19 +0,0 @@
|
||||
import listAssignees from './list-assignees/index.js';
|
||||
import listFolders from './list-folders/index.js';
|
||||
import listLists from './list-lists/index.js';
|
||||
import listSpaces from './list-spaces/index.js';
|
||||
import listStatuses from './list-statuses/index.js';
|
||||
import listTags from './list-tags/index.js';
|
||||
import listTasks from './list-tasks/index.js';
|
||||
import listWorkspaces from './list-workspaces/index.js';
|
||||
|
||||
export default [
|
||||
listAssignees,
|
||||
listFolders,
|
||||
listLists,
|
||||
listSpaces,
|
||||
listStatuses,
|
||||
listTags,
|
||||
listTasks,
|
||||
listWorkspaces,
|
||||
];
|
@@ -1,28 +0,0 @@
|
||||
export default {
|
||||
name: 'List assignees',
|
||||
key: 'listAssignees',
|
||||
|
||||
async run($) {
|
||||
const assignees = {
|
||||
data: [],
|
||||
};
|
||||
const listId = $.step.parameters.listId;
|
||||
|
||||
if (!listId) {
|
||||
return assignees;
|
||||
}
|
||||
|
||||
const { data } = await $.http.get(`/v2/list/${listId}/member`);
|
||||
|
||||
if (data.members) {
|
||||
for (const member of data.members) {
|
||||
assignees.data.push({
|
||||
value: member.id,
|
||||
name: member.username,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return assignees;
|
||||
},
|
||||
};
|
@@ -1,28 +0,0 @@
|
||||
export default {
|
||||
name: 'List folders',
|
||||
key: 'listFolders',
|
||||
|
||||
async run($) {
|
||||
const folders = {
|
||||
data: [],
|
||||
};
|
||||
const spaceId = $.step.parameters.spaceId;
|
||||
|
||||
if (!spaceId) {
|
||||
return folders;
|
||||
}
|
||||
|
||||
const { data } = await $.http.get(`/v2/space/${spaceId}/folder`);
|
||||
|
||||
if (data.folders) {
|
||||
for (const folder of data.folders) {
|
||||
folders.data.push({
|
||||
value: folder.id,
|
||||
name: folder.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return folders;
|
||||
},
|
||||
};
|
@@ -1,28 +0,0 @@
|
||||
export default {
|
||||
name: 'List lists',
|
||||
key: 'listLists',
|
||||
|
||||
async run($) {
|
||||
const lists = {
|
||||
data: [],
|
||||
};
|
||||
const folderId = $.step.parameters.folderId;
|
||||
|
||||
if (!folderId) {
|
||||
return lists;
|
||||
}
|
||||
|
||||
const { data } = await $.http.get(`/v2/folder/${folderId}/list`);
|
||||
|
||||
if (data.lists) {
|
||||
for (const list of data.lists) {
|
||||
lists.data.push({
|
||||
value: list.id,
|
||||
name: list.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return lists;
|
||||
},
|
||||
};
|
@@ -1,28 +0,0 @@
|
||||
export default {
|
||||
name: 'List spaces',
|
||||
key: 'listSpaces',
|
||||
|
||||
async run($) {
|
||||
const spaces = {
|
||||
data: [],
|
||||
};
|
||||
const workspaceId = $.step.parameters.workspaceId;
|
||||
|
||||
if (!workspaceId) {
|
||||
return spaces;
|
||||
}
|
||||
|
||||
const { data } = await $.http.get(`/v2/team/${workspaceId}/space`);
|
||||
|
||||
if (data.spaces) {
|
||||
for (const space of data.spaces) {
|
||||
spaces.data.push({
|
||||
value: space.id,
|
||||
name: space.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return spaces;
|
||||
},
|
||||
};
|
@@ -1,28 +0,0 @@
|
||||
export default {
|
||||
name: 'List statuses',
|
||||
key: 'listStatuses',
|
||||
|
||||
async run($) {
|
||||
const statuses = {
|
||||
data: [],
|
||||
};
|
||||
const listId = $.step.parameters.listId;
|
||||
|
||||
if (!listId) {
|
||||
return statuses;
|
||||
}
|
||||
|
||||
const { data } = await $.http.get(`/v2/list/${listId}`);
|
||||
|
||||
if (data.statuses) {
|
||||
for (const status of data.statuses) {
|
||||
statuses.data.push({
|
||||
value: status.status,
|
||||
name: status.status,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return statuses;
|
||||
},
|
||||
};
|
@@ -1,28 +0,0 @@
|
||||
export default {
|
||||
name: 'List tags',
|
||||
key: 'listTags',
|
||||
|
||||
async run($) {
|
||||
const tags = {
|
||||
data: [],
|
||||
};
|
||||
const spaceId = $.step.parameters.spaceId;
|
||||
|
||||
if (!spaceId) {
|
||||
return spaceId;
|
||||
}
|
||||
|
||||
const { data } = await $.http.get(`v2/space/${spaceId}/tag`);
|
||||
|
||||
if (data.tags) {
|
||||
for (const tag of data.tags) {
|
||||
tags.data.push({
|
||||
value: tag.name,
|
||||
name: tag.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
},
|
||||
};
|
@@ -1,41 +0,0 @@
|
||||
export default {
|
||||
name: 'List tasks',
|
||||
key: 'listTasks',
|
||||
|
||||
async run($) {
|
||||
const tasks = {
|
||||
data: [],
|
||||
};
|
||||
const listId = $.step.parameters.listId;
|
||||
let next = false;
|
||||
|
||||
if (!listId) {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
const params = {
|
||||
order_by: 'created',
|
||||
reverse: true,
|
||||
};
|
||||
|
||||
do {
|
||||
const { data } = await $.http.get(`/v2/list/${listId}/task`, { params });
|
||||
if (data.last_page) {
|
||||
next = false;
|
||||
} else {
|
||||
next = true;
|
||||
}
|
||||
|
||||
if (data.tasks) {
|
||||
for (const task of data.tasks) {
|
||||
tasks.data.push({
|
||||
value: task.id,
|
||||
name: task.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
} while (next);
|
||||
|
||||
return tasks;
|
||||
},
|
||||
};
|
@@ -1,23 +0,0 @@
|
||||
export default {
|
||||
name: 'List workspaces',
|
||||
key: 'listWorkspaces',
|
||||
|
||||
async run($) {
|
||||
const workspaces = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
const { data } = await $.http.get('/v2/team');
|
||||
|
||||
if (data.teams) {
|
||||
for (const workspace of data.teams) {
|
||||
workspaces.data.push({
|
||||
value: workspace.id,
|
||||
name: workspace.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return workspaces;
|
||||
},
|
||||
};
|
@@ -1,3 +0,0 @@
|
||||
import useCustomId from './use-custom-id/index.js';
|
||||
|
||||
export default [useCustomId];
|
@@ -1,29 +0,0 @@
|
||||
export default {
|
||||
name: 'List workspaces when using custom id',
|
||||
key: 'listFieldsWhenUsingCustomId',
|
||||
|
||||
async run($) {
|
||||
if ($.step.parameters.useCustomId) {
|
||||
return [
|
||||
{
|
||||
label: 'Workspace',
|
||||
key: 'workspaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorkspaces',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
};
|
@@ -1,24 +0,0 @@
|
||||
import defineApp from '../../helpers/define-app.js';
|
||||
import addAuthHeader from './common/add-auth-header.js';
|
||||
import auth from './auth/index.js';
|
||||
import triggers from './triggers/index.js';
|
||||
import dynamicData from './dynamic-data/index.js';
|
||||
import actions from './actions/index.js';
|
||||
import dynamicFields from './dynamic-fields/index.js';
|
||||
|
||||
export default defineApp({
|
||||
name: 'ClickUp',
|
||||
key: 'clickup',
|
||||
baseUrl: 'https://clickup.com',
|
||||
apiBaseUrl: 'https://api.clickup.com/api',
|
||||
iconUrl: '{BASE_URL}/apps/clickup/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/clickup/connection',
|
||||
primaryColor: '#FD71AF',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
dynamicData,
|
||||
actions,
|
||||
dynamicFields,
|
||||
});
|
@@ -1,6 +0,0 @@
|
||||
import newFolders from './new-folders/index.js';
|
||||
import newLists from './new-lists/index.js';
|
||||
import newTasks from './new-tasks/index.js';
|
||||
import updatedTask from './updated-task/index.js';
|
||||
|
||||
export default [newFolders, newLists, newTasks, updatedTask];
|
@@ -1,105 +0,0 @@
|
||||
import Crypto from 'crypto';
|
||||
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New folders',
|
||||
key: 'newFolder',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new folder is created.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Workspace',
|
||||
key: 'workspaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorkspaces',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Space',
|
||||
key: 'spaceId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.workspaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpaces',
|
||||
},
|
||||
{
|
||||
name: 'parameters.workspaceId',
|
||||
value: '{parameters.workspaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: $.request.body.folder_id,
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const sampleEventData = {
|
||||
event: 'folderCreated',
|
||||
folder_id: '90180382912',
|
||||
webhook_id: Crypto.randomUUID(),
|
||||
};
|
||||
|
||||
const dataItem = {
|
||||
raw: sampleEventData,
|
||||
meta: {
|
||||
internalId: '',
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const { workspaceId, spaceId } = $.step.parameters;
|
||||
|
||||
const payload = {
|
||||
name: $.flow.id,
|
||||
endpoint: $.webhookUrl,
|
||||
events: ['folderCreated'],
|
||||
};
|
||||
|
||||
if (spaceId) {
|
||||
payload.space_id = spaceId;
|
||||
}
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/v2/team/${workspaceId}/webhook`,
|
||||
payload
|
||||
);
|
||||
|
||||
await $.flow.setRemoteWebhookId(data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -1,129 +0,0 @@
|
||||
import Crypto from 'crypto';
|
||||
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New lists',
|
||||
key: 'newLists',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new list is created.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Workspace',
|
||||
key: 'workspaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorkspaces',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Space',
|
||||
key: 'spaceId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.workspaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpaces',
|
||||
},
|
||||
{
|
||||
name: 'parameters.workspaceId',
|
||||
value: '{parameters.workspaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Folder',
|
||||
key: 'folderId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.spaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listFolders',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spaceId',
|
||||
value: '{parameters.spaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: $.request.body.list_id,
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const sampleEventData = {
|
||||
event: 'listCreated',
|
||||
list_id: '901800588812',
|
||||
webhook_id: Crypto.randomUUID(),
|
||||
};
|
||||
|
||||
const dataItem = {
|
||||
raw: sampleEventData,
|
||||
meta: {
|
||||
internalId: sampleEventData.webhook_id,
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const { workspaceId, spaceId, folderId } = $.step.parameters;
|
||||
|
||||
const payload = {
|
||||
name: $.flow.id,
|
||||
endpoint: $.webhookUrl,
|
||||
events: ['listCreated'],
|
||||
space_id: spaceId,
|
||||
};
|
||||
|
||||
if (folderId) {
|
||||
payload.folder_id = folderId;
|
||||
}
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/v2/team/${workspaceId}/webhook`,
|
||||
payload
|
||||
);
|
||||
|
||||
await $.flow.setRemoteWebhookId(data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -1,186 +0,0 @@
|
||||
import Crypto from 'crypto';
|
||||
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New tasks',
|
||||
key: 'newTasks',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new task is created.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Workspace',
|
||||
key: 'workspaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorkspaces',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Space',
|
||||
key: 'spaceId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.workspaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpaces',
|
||||
},
|
||||
{
|
||||
name: 'parameters.workspaceId',
|
||||
value: '{parameters.workspaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Folder',
|
||||
key: 'folderId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.spaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listFolders',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spaceId',
|
||||
value: '{parameters.spaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'List',
|
||||
key: 'listId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.folderId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listLists',
|
||||
},
|
||||
{
|
||||
name: 'parameters.folderId',
|
||||
value: '{parameters.folderId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Task',
|
||||
key: 'taskId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.listId'],
|
||||
description:
|
||||
'Choose an optional task to determine when this flow should be activated. In this scenario, only subtasks will initiate this flow.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listTasks',
|
||||
},
|
||||
{
|
||||
name: 'parameters.listId',
|
||||
value: '{parameters.listId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: $.request.body.task_id,
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const sampleEventData = {
|
||||
event: 'taskCreated',
|
||||
task_id: '86enn7pg7',
|
||||
webhook_id: Crypto.randomUUID(),
|
||||
history_items: [],
|
||||
};
|
||||
|
||||
const dataItem = {
|
||||
raw: sampleEventData,
|
||||
meta: {
|
||||
internalId: sampleEventData.webhook_id,
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const { workspaceId, spaceId, folderId, listId, taskId } =
|
||||
$.step.parameters;
|
||||
|
||||
const payload = {
|
||||
name: $.flow.id,
|
||||
endpoint: $.webhookUrl,
|
||||
events: ['taskCreated'],
|
||||
space_id: spaceId,
|
||||
};
|
||||
|
||||
if (folderId) {
|
||||
payload.folder_id = folderId;
|
||||
}
|
||||
|
||||
if (listId) {
|
||||
payload.list_id = listId;
|
||||
}
|
||||
|
||||
if (taskId) {
|
||||
payload.task_id = taskId;
|
||||
}
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/v2/team/${workspaceId}/webhook`,
|
||||
payload
|
||||
);
|
||||
|
||||
await $.flow.setRemoteWebhookId(data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -1,172 +0,0 @@
|
||||
import Crypto from 'crypto';
|
||||
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'Updated task',
|
||||
key: 'updatedTask',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a task is updated.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Workspace',
|
||||
key: 'workspaceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorkspaces',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Space',
|
||||
key: 'spaceId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.workspaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpaces',
|
||||
},
|
||||
{
|
||||
name: 'parameters.workspaceId',
|
||||
value: '{parameters.workspaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Folder',
|
||||
key: 'folderId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.spaceId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listFolders',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spaceId',
|
||||
value: '{parameters.spaceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'List',
|
||||
key: 'listId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.folderId'],
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listLists',
|
||||
},
|
||||
{
|
||||
name: 'parameters.folderId',
|
||||
value: '{parameters.folderId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'What Changed?',
|
||||
key: 'whatChanged',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Status', value: 'taskStatusUpdated' },
|
||||
{ label: 'Assignee Added', value: 'taskAssigneeUpdated' },
|
||||
{ label: 'Priority', value: 'taskPriorityUpdated' },
|
||||
{ label: 'Tag Added', value: 'taskTagUpdated' },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const sampleEventData = {
|
||||
event: 'taskUpdated',
|
||||
task_id: '86enn7pg7',
|
||||
webhook_id: Crypto.randomUUID(),
|
||||
history_items: [],
|
||||
};
|
||||
|
||||
const dataItem = {
|
||||
raw: sampleEventData,
|
||||
meta: {
|
||||
internalId: sampleEventData.webhook_id,
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const { workspaceId, spaceId, folderId, listId, whatChanged } =
|
||||
$.step.parameters;
|
||||
|
||||
const payload = {
|
||||
name: $.flow.id,
|
||||
endpoint: $.webhookUrl,
|
||||
space_id: spaceId,
|
||||
};
|
||||
|
||||
payload.events = [whatChanged || 'taskUpdated'];
|
||||
|
||||
if (folderId) {
|
||||
payload.folder_id = folderId;
|
||||
}
|
||||
|
||||
if (listId) {
|
||||
payload.list_id = listId;
|
||||
}
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/v2/team/${workspaceId}/webhook`,
|
||||
payload
|
||||
);
|
||||
|
||||
await $.flow.setRemoteWebhookId(data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -1,3 +0,0 @@
|
||||
import runJavascript from './run-javascript/index.js';
|
||||
|
||||
export default [runJavascript];
|
@@ -1,84 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Run Javascript',
|
||||
key: 'runJavascript',
|
||||
description:
|
||||
'Run browser Javascript code. You can not use NodeJS specific features and npm packages.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Inputs',
|
||||
key: 'inputs',
|
||||
type: 'dynamic',
|
||||
required: false,
|
||||
description:
|
||||
'To be able to use data from previous steps, you need to expose them as input entries. You can access these input values in your code by using the `inputs` argument.',
|
||||
value: [
|
||||
{
|
||||
key: '',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
label: 'Key',
|
||||
key: 'key',
|
||||
type: 'string',
|
||||
required: true,
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Value',
|
||||
key: 'value',
|
||||
type: 'string',
|
||||
required: true,
|
||||
variables: true,
|
||||
valueType: 'parse',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Code Snippet',
|
||||
key: 'codeSnippet',
|
||||
type: 'code',
|
||||
required: true,
|
||||
variables: false,
|
||||
value:
|
||||
'const code = async (inputs) => { \n // E.g. if you have an input called username,\n // you can access its value by calling inputs.username\n // Return value will be used as output of this step.\n\n return true;\n};',
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const { inputs = [], codeSnippet } = $.step.parameters;
|
||||
|
||||
const objectifiedInput = {};
|
||||
for (const input of inputs) {
|
||||
if (input.key) {
|
||||
objectifiedInput[input.key] = input.value;
|
||||
}
|
||||
}
|
||||
|
||||
const ivm = (await import('isolated-vm')).default;
|
||||
const isolate = new ivm.Isolate({ memoryLimit: 128 });
|
||||
|
||||
try {
|
||||
const context = await isolate.createContext();
|
||||
await context.global.set(
|
||||
'inputs',
|
||||
new ivm.ExternalCopy(objectifiedInput).copyInto()
|
||||
);
|
||||
|
||||
const compiledCodeSnippet = await isolate.compileScript(
|
||||
`${codeSnippet}; code(inputs);`
|
||||
);
|
||||
const codeFunction = await compiledCodeSnippet.run(context, {
|
||||
reference: true,
|
||||
promise: true,
|
||||
});
|
||||
|
||||
$.setActionItem({ raw: { output: await codeFunction.copy() } });
|
||||
} finally {
|
||||
isolate.dispose();
|
||||
}
|
||||
},
|
||||
});
|
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800px" height="800px" viewBox="0 0 512 512">
|
||||
<polyline points="160 368 32 256 160 144" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||
<polyline points="352 368 480 256 352 144" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||
<line x1="304" y1="96" x2="208" y2="416" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 519 B |
@@ -1,14 +0,0 @@
|
||||
import defineApp from '../../helpers/define-app.js';
|
||||
import actions from './actions/index.js';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Code',
|
||||
key: 'code',
|
||||
baseUrl: '',
|
||||
apiBaseUrl: '',
|
||||
iconUrl: '{BASE_URL}/apps/code/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/code/connection',
|
||||
primaryColor: '#000000',
|
||||
supportsConnections: false,
|
||||
actions,
|
||||
});
|
@@ -9,6 +9,6 @@ export default defineApp({
|
||||
supportsConnections: false,
|
||||
baseUrl: '',
|
||||
apiBaseUrl: '',
|
||||
primaryColor: '#001F52',
|
||||
primaryColor: '001F52',
|
||||
actions,
|
||||
});
|
||||
|
@@ -9,6 +9,6 @@ export default defineApp({
|
||||
supportsConnections: false,
|
||||
baseUrl: '',
|
||||
apiBaseUrl: '',
|
||||
primaryColor: '#001F52',
|
||||
primaryColor: '001F52',
|
||||
actions,
|
||||
});
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://deepl.com',
|
||||
apiBaseUrl: 'https://api.deepl.com',
|
||||
primaryColor: '#0d2d45',
|
||||
primaryColor: '0d2d45',
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
actions,
|
||||
|
@@ -9,6 +9,6 @@ export default defineApp({
|
||||
supportsConnections: false,
|
||||
baseUrl: '',
|
||||
apiBaseUrl: '',
|
||||
primaryColor: '#001F52',
|
||||
primaryColor: '001F52',
|
||||
actions,
|
||||
});
|
||||
|
@@ -14,7 +14,7 @@ export default defineApp({
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://discord.com',
|
||||
apiBaseUrl: 'https://discord.com/api',
|
||||
primaryColor: '#5865f2',
|
||||
primaryColor: '5865f2',
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
dynamicData,
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://disqus.com/api',
|
||||
iconUrl: '{BASE_URL}/apps/disqus/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/disqus/connection',
|
||||
primaryColor: '#2E9FFF',
|
||||
primaryColor: '2E9FFF',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://dropbox.com',
|
||||
apiBaseUrl: 'https://api.dropboxapi.com',
|
||||
primaryColor: '#0061ff',
|
||||
primaryColor: '0061ff',
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
actions,
|
||||
|
@@ -9,6 +9,6 @@ export default defineApp({
|
||||
supportsConnections: false,
|
||||
baseUrl: '',
|
||||
apiBaseUrl: '',
|
||||
primaryColor: '#001F52',
|
||||
primaryColor: '001F52',
|
||||
actions,
|
||||
});
|
||||
|
@@ -10,7 +10,7 @@ export default defineApp({
|
||||
iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/flickr/connection',
|
||||
docUrl: 'https://automatisch.io/docs/flickr',
|
||||
primaryColor: '#000000',
|
||||
primaryColor: '000000',
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://www.flickr.com/',
|
||||
apiBaseUrl: 'https://www.flickr.com/services',
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://flowers-software.com',
|
||||
apiBaseUrl: 'https://webapp.flowers-software.com/api',
|
||||
primaryColor: '#02AFC7',
|
||||
primaryColor: '02AFC7',
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
|
@@ -10,7 +10,7 @@ export default defineApp({
|
||||
supportsConnections: false,
|
||||
baseUrl: '',
|
||||
apiBaseUrl: '',
|
||||
primaryColor: '#001F52',
|
||||
primaryColor: '001F52',
|
||||
actions,
|
||||
dynamicFields,
|
||||
});
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
apiBaseUrl: '',
|
||||
iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/ghost/connection',
|
||||
primaryColor: '#15171A',
|
||||
primaryColor: '15171A',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
|
@@ -10,7 +10,7 @@ export default defineAction({
|
||||
label: 'Repo',
|
||||
key: 'repo',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
required: false,
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://api.github.com',
|
||||
iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/github/connection',
|
||||
primaryColor: '#000000',
|
||||
primaryColor: '000000',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://gitlab.com',
|
||||
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/gitlab/connection',
|
||||
primaryColor: '#FC6D26',
|
||||
primaryColor: 'FC6D26',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://www.googleapis.com/calendar',
|
||||
iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/google-calendar/connection',
|
||||
primaryColor: '#448AFF',
|
||||
primaryColor: '448AFF',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://www.googleapis.com/drive',
|
||||
iconUrl: '{BASE_URL}/apps/google-drive/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/google-drive/connection',
|
||||
primaryColor: '#1FA463',
|
||||
primaryColor: '1FA463',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://forms.googleapis.com',
|
||||
iconUrl: '{BASE_URL}/apps/google-forms/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/google-forms/connection',
|
||||
primaryColor: '#673AB7',
|
||||
primaryColor: '673AB7',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
|
@@ -1,175 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Find worksheet',
|
||||
key: 'findWorksheet',
|
||||
description:
|
||||
'Finds a worksheet by title. Optionally, create a worksheet if none are found.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Drive',
|
||||
key: 'driveId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
description:
|
||||
'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listDrives',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Spreadsheet',
|
||||
key: 'spreadsheetId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
dependsOn: ['parameters.driveId'],
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpreadsheets',
|
||||
},
|
||||
{
|
||||
name: 'parameters.driveId',
|
||||
value: '{parameters.driveId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Title',
|
||||
key: 'title',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description:
|
||||
'The worksheet title needs to match exactly, and the search is case-sensitive.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Create worksheet if none are found.',
|
||||
key: 'createWorksheet',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
options: [
|
||||
{ label: 'Yes', value: true },
|
||||
{ label: 'No', value: false },
|
||||
],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listCreateWorksheetFields',
|
||||
},
|
||||
{
|
||||
name: 'parameters.createWorksheet',
|
||||
value: '{parameters.createWorksheet}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const createWorksheet = $.step.parameters.createWorksheet;
|
||||
|
||||
async function findWorksheet() {
|
||||
const {
|
||||
data: { sheets },
|
||||
} = await $.http.get(`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`);
|
||||
|
||||
const selectedSheet = sheets.find(
|
||||
(sheet) => sheet.properties.title === $.step.parameters.title
|
||||
);
|
||||
|
||||
return selectedSheet;
|
||||
}
|
||||
|
||||
const selectedSheet = await findWorksheet();
|
||||
|
||||
if (selectedSheet) {
|
||||
$.setActionItem({
|
||||
raw: selectedSheet,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (createWorksheet) {
|
||||
const headers = $.step.parameters.headers;
|
||||
const headerValues = headers.map((entry) => entry.header);
|
||||
|
||||
const body = {
|
||||
requests: [
|
||||
{
|
||||
addSheet: {
|
||||
properties: {
|
||||
title: $.step.parameters.title,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}:batchUpdate`,
|
||||
body
|
||||
);
|
||||
|
||||
if (headerValues.length) {
|
||||
const body = {
|
||||
requests: [
|
||||
{
|
||||
updateCells: {
|
||||
rows: [
|
||||
{
|
||||
values: headerValues.map((header) => ({
|
||||
userEnteredValue: { stringValue: header },
|
||||
})),
|
||||
},
|
||||
],
|
||||
fields: '*',
|
||||
start: {
|
||||
sheetId:
|
||||
data.replies[data.replies.length - 1].addSheet.properties
|
||||
.sheetId,
|
||||
rowIndex: 0,
|
||||
columnIndex: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
await $.http.post(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}:batchUpdate`,
|
||||
body
|
||||
);
|
||||
|
||||
const createdSheet = await findWorksheet();
|
||||
|
||||
$.setActionItem({
|
||||
raw: createdSheet,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$.setActionItem({
|
||||
raw: null,
|
||||
});
|
||||
},
|
||||
});
|
@@ -1,11 +1,5 @@
|
||||
import createSpreadsheet from './create-spreadsheet/index.js';
|
||||
import createSpreadsheetRow from './create-spreadsheet-row/index.js';
|
||||
import createWorksheet from './create-worksheet/index.js';
|
||||
import findWorksheet from './find-worksheet/index.js';
|
||||
|
||||
export default [
|
||||
createSpreadsheet,
|
||||
createSpreadsheetRow,
|
||||
createWorksheet,
|
||||
findWorksheet,
|
||||
];
|
||||
export default [createSpreadsheet, createSpreadsheetRow, createWorksheet];
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import listSheetHeaders from './list-sheet-headers/index.js';
|
||||
import listCreateWorksheetFields from './list-create-worksheet-fields/index.js';
|
||||
|
||||
export default [listSheetHeaders, listCreateWorksheetFields];
|
||||
export default [listSheetHeaders];
|
||||
|
@@ -1,26 +0,0 @@
|
||||
export default {
|
||||
name: 'List create worksheet fields',
|
||||
key: 'listCreateWorksheetFields',
|
||||
|
||||
async run($) {
|
||||
if ($.step.parameters.createWorksheet) {
|
||||
return [
|
||||
{
|
||||
label: 'Headers',
|
||||
key: 'headers',
|
||||
type: 'dynamic',
|
||||
required: false,
|
||||
fields: [
|
||||
{
|
||||
label: 'Header',
|
||||
key: 'header',
|
||||
type: 'string',
|
||||
required: true,
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
};
|
@@ -13,7 +13,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://sheets.googleapis.com',
|
||||
iconUrl: '{BASE_URL}/apps/google-sheets/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/google-sheets/connection',
|
||||
primaryColor: '#0F9D58',
|
||||
primaryColor: '0F9D58',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://tasks.googleapis.com',
|
||||
iconUrl: '{BASE_URL}/apps/google-tasks/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/google-tasks/connection',
|
||||
primaryColor: '#0066DA',
|
||||
primaryColor: '0066DA',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://app.tryhelix.ai',
|
||||
iconUrl: '{BASE_URL}/apps/helix/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/helix/connection',
|
||||
primaryColor: '#000000',
|
||||
primaryColor: '000000',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
|
@@ -145,13 +145,6 @@ export default defineAction({
|
||||
responseData = Buffer.from(responseData).toString('base64');
|
||||
}
|
||||
|
||||
$.setActionItem({
|
||||
raw: {
|
||||
data: responseData,
|
||||
headers: response.headers,
|
||||
status: response.status,
|
||||
statusText: response.statusText
|
||||
}
|
||||
});
|
||||
$.setActionItem({ raw: { data: responseData } });
|
||||
},
|
||||
});
|
||||
|
@@ -9,6 +9,6 @@ export default defineApp({
|
||||
supportsConnections: false,
|
||||
baseUrl: '',
|
||||
apiBaseUrl: '',
|
||||
primaryColor: '#000000',
|
||||
primaryColor: '000000',
|
||||
actions,
|
||||
});
|
||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://www.hubspot.com',
|
||||
apiBaseUrl: 'https://api.hubapi.com',
|
||||
primaryColor: '#F95C35',
|
||||
primaryColor: 'F95C35',
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
actions,
|
||||
|
@@ -13,7 +13,7 @@ export default defineApp({
|
||||
apiBaseUrl: 'https://invoicing.co/api',
|
||||
iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/invoice-ninja/connection',
|
||||
primaryColor: '#000000',
|
||||
primaryColor: '000000',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
|
@@ -1 +0,0 @@
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" class="jff-logo-img" width="53" height="59" viewBox="0 0 53 59" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M14.4509 55.1332C15.5462 56.1951 14.7721 58.0143 13.2168 58.0143H3.4831C1.56265 58.0143 0 56.4995 0 54.6377V45.2017C0 43.6939 1.87664 42.9436 2.97195 44.0054L14.4509 55.1332Z" fill="#0A1551"></path><path d="M29.6655 55.8676C26.7843 53.0052 26.7843 48.3642 29.6655 45.5018L40.0638 35.1713C42.945 32.3089 47.6164 32.3089 50.4976 35.1713C53.3788 38.0338 53.3788 42.6747 50.4976 45.5371L40.0993 55.8676C37.2181 58.73 32.5468 58.73 29.6655 55.8676Z" fill="#FFB629"></path><path d="M2.1968 29.9101C-0.684414 27.0476 -0.684413 22.4067 2.1968 19.5443L19.696 2.14685C22.5772 -0.71559 27.2486 -0.715594 30.1298 2.14685C33.011 5.00929 33.011 9.65022 30.1298 12.5127L12.6306 29.9101C9.74937 32.7725 5.078 32.7725 2.1968 29.9101Z" fill="#0099FF"></path><path d="M16.5015 42.3095C13.6203 39.4471 13.6203 34.8062 16.5015 31.9437L40.1461 8.45322C43.0273 5.59079 47.6986 5.59079 50.5798 8.45322C53.4611 11.3157 53.4611 15.9566 50.5798 18.819L26.9353 42.3095C24.0541 45.1719 19.3827 45.1719 16.5015 42.3095Z" fill="#FF6100"></path></svg>
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,30 +0,0 @@
|
||||
import verifyCredentials from './verify-credentials.js';
|
||||
import isStillVerified from './is-still-verified.js';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'apiUrl',
|
||||
label: 'API URL',
|
||||
type: 'string',
|
||||
required: false,
|
||||
readOnly: false,
|
||||
value: 'https://api.jotform.com',
|
||||
placeholder: 'https://${subdomain}.jotform.com/api',
|
||||
clickToCopy: true,
|
||||
},
|
||||
{
|
||||
key: 'apiKey',
|
||||
label: 'API Key',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
],
|
||||
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
};
|
@@ -1,8 +0,0 @@
|
||||
import getCurrentUser from '../common/get-current-user.js';
|
||||
|
||||
const isStillVerified = async ($) => {
|
||||
const user = await getCurrentUser($);
|
||||
return !!user.username;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
@@ -1,12 +0,0 @@
|
||||
import getCurrentUser from '../common/get-current-user.js';
|
||||
|
||||
const verifyCredentials = async ($) => {
|
||||
const user = await getCurrentUser($);
|
||||
|
||||
await $.auth.set({
|
||||
screenName: user.name,
|
||||
apiKey: $.auth.data.apiKey,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
@@ -1,9 +0,0 @@
|
||||
const addAuthHeader = ($, requestConfig) => {
|
||||
if ($.auth.data?.apiKey) {
|
||||
requestConfig.headers['APIKEY'] = `${$.auth.data.apiKey}`;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
@@ -1,7 +0,0 @@
|
||||
const getCurrentUser = async ($) => {
|
||||
const response = await $.http.get('/user');
|
||||
const currentUser = response.data.content;
|
||||
return currentUser;
|
||||
};
|
||||
|
||||
export default getCurrentUser;
|
@@ -1,11 +0,0 @@
|
||||
const setBaseUrl = ($, requestConfig) => {
|
||||
if ($.auth.data.apiUrl) {
|
||||
requestConfig.baseURL = $.auth.data.apiUrl;
|
||||
} else if ($.app.apiBaseUrl) {
|
||||
requestConfig.baseURL = $.app.apiBaseUrl;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default setBaseUrl;
|
@@ -1,3 +0,0 @@
|
||||
import listForms from './list-forms/index.js';
|
||||
|
||||
export default [listForms];
|
@@ -1,41 +0,0 @@
|
||||
export default {
|
||||
name: 'List forms',
|
||||
key: 'listForms',
|
||||
|
||||
async run($) {
|
||||
const forms = {
|
||||
data: [],
|
||||
};
|
||||
let hasMore = false;
|
||||
|
||||
const params = {
|
||||
limit: 1000,
|
||||
offset: 0,
|
||||
orderby: 'created_at',
|
||||
};
|
||||
|
||||
do {
|
||||
const { data } = await $.http.get('/user/forms', { params });
|
||||
params.offset = params.offset + params.limit;
|
||||
|
||||
if (data.content?.length) {
|
||||
for (const form of data.content) {
|
||||
if (form.status === 'ENABLED') {
|
||||
forms.data.push({
|
||||
value: form.id,
|
||||
name: form.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data.resultSet.count >= data.resultSet.limit) {
|
||||
hasMore = true;
|
||||
} else {
|
||||
hasMore = false;
|
||||
}
|
||||
} while (hasMore);
|
||||
|
||||
return forms;
|
||||
},
|
||||
};
|
@@ -1,21 +0,0 @@
|
||||
import defineApp from '../../helpers/define-app.js';
|
||||
import addAuthHeader from './common/add-auth-header.js';
|
||||
import auth from './auth/index.js';
|
||||
import setBaseUrl from './common/set-base-url.js';
|
||||
import triggers from './triggers/index.js';
|
||||
import dynamicData from './dynamic-data/index.js';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Jotform',
|
||||
key: 'jotform',
|
||||
iconUrl: '{BASE_URL}/apps/jotform/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/jotform/connection',
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://www.jotform.com',
|
||||
apiBaseUrl: 'https://api.jotform.com',
|
||||
primaryColor: '#FF6100',
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
dynamicData,
|
||||
});
|
@@ -1,3 +0,0 @@
|
||||
import newSubmissions from './new-submissions/index.js';
|
||||
|
||||
export default [newSubmissions];
|
@@ -1,109 +0,0 @@
|
||||
import Crypto from 'crypto';
|
||||
import { URLSearchParams } from 'url';
|
||||
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New submissions',
|
||||
key: 'newSubmissions',
|
||||
type: 'webhook',
|
||||
description:
|
||||
'Triggers when a new submission has been added to a specific form.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Form',
|
||||
key: 'formId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listForms',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const sampleEventData = {
|
||||
ip: '127.0.0.1',
|
||||
type: 'WEB',
|
||||
appID: '',
|
||||
event: '',
|
||||
action: '',
|
||||
formID: Crypto.randomUUID(),
|
||||
parent: '',
|
||||
pretty: 'Name:test, E-mail:user@automatisch.io',
|
||||
teamID: '',
|
||||
unread: '',
|
||||
product: '',
|
||||
subject: '',
|
||||
isSilent: '',
|
||||
username: 'username',
|
||||
deviceIDs: 'Array',
|
||||
formTitle: 'Opt-In Form-Get Free Email Updates!',
|
||||
fromTable: '',
|
||||
customBody: '',
|
||||
documentID: '',
|
||||
rawRequest: '',
|
||||
webhookURL: '',
|
||||
customTitle: '',
|
||||
trackAction: 'Array',
|
||||
customParams: '',
|
||||
submissionID: Crypto.randomUUID(),
|
||||
customBodyParams: 'Array',
|
||||
customTitleParams: 'Array',
|
||||
};
|
||||
|
||||
const dataItem = {
|
||||
raw: sampleEventData,
|
||||
meta: {
|
||||
internalId: sampleEventData.submissionID,
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const formId = $.step.parameters.formId;
|
||||
|
||||
const params = new URLSearchParams({
|
||||
webhookURL: $.webhookUrl,
|
||||
});
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/form/${formId}/webhooks`,
|
||||
params.toString()
|
||||
);
|
||||
|
||||
await $.flow.setRemoteWebhookId(data.content[0]);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
const formId = $.step.parameters.formId;
|
||||
|
||||
const { data } = await $.http.get(`/form/${formId}/webhooks`);
|
||||
|
||||
const webhookURLs = Object.values(data.content);
|
||||
const webhookId = webhookURLs.findIndex((url) => url === $.webhookUrl);
|
||||
|
||||
await $.http.delete(`/form/${formId}/webhooks/${webhookId}`);
|
||||
},
|
||||
});
|
@@ -1,180 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create campaign',
|
||||
key: 'createCampaign',
|
||||
description: 'Creates a new campaign draft.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Campaign Name',
|
||||
key: 'campaignName',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Audience',
|
||||
key: 'audienceId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listAudiences',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Segment or Tag',
|
||||
key: 'segmentOrTagId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
dependsOn: ['parameters.audienceId'],
|
||||
description:
|
||||
'Choose the specific segment or tag to which you"d like to direct the campaign. If no segment or tag is chosen, the campaign will be distributed to the entire audience previously selected.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSegmentsOrTags',
|
||||
},
|
||||
{
|
||||
name: 'parameters.audienceId',
|
||||
value: '{parameters.audienceId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Email Subject',
|
||||
key: 'emailSubject',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Preview Text',
|
||||
key: 'previewText',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description:
|
||||
'The snippet will be visible in the inbox following the subject line.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'From Name',
|
||||
key: 'fromName',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'The "from" name on the campaign (not an email address).',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'From Email Address',
|
||||
key: 'fromEmailAddress',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'The reply-to email address for the campaign.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'To Name',
|
||||
key: 'toName',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description:
|
||||
'Supports *|MERGETAGS|* for recipient name, such as *|FNAME|*, *|LNAME|*, *|FNAME|* *|LNAME|*, etc.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Template',
|
||||
key: 'templateId',
|
||||
type: 'dropdown',
|
||||
required: false,
|
||||
description:
|
||||
'Select either a template or provide HTML email content, you cannot provide both. If both fields are left blank, the campaign draft will have no content.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listTemplates',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Email Content (HTML)',
|
||||
key: 'emailContent',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description:
|
||||
'Select either a template or provide HTML email content, you cannot provide both. If both fields are left blank, the campaign draft will have no content.',
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
campaignName,
|
||||
audienceId,
|
||||
segmentOrTagId,
|
||||
emailSubject,
|
||||
previewText,
|
||||
fromName,
|
||||
fromEmailAddress,
|
||||
toName,
|
||||
templateId,
|
||||
emailContent,
|
||||
} = $.step.parameters;
|
||||
|
||||
const body = {
|
||||
type: 'regular',
|
||||
recipients: {
|
||||
list_id: audienceId,
|
||||
segment_opts: {
|
||||
saved_segment_id: Number(segmentOrTagId),
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
subject_line: emailSubject,
|
||||
reply_to: fromEmailAddress,
|
||||
title: campaignName,
|
||||
preview_text: previewText,
|
||||
from_name: fromName,
|
||||
to_name: toName,
|
||||
},
|
||||
};
|
||||
|
||||
const { data: campaign } = await $.http.post('/3.0/campaigns', body);
|
||||
|
||||
const campaignBody = {
|
||||
template: {
|
||||
id: Number(templateId),
|
||||
},
|
||||
html: emailContent,
|
||||
};
|
||||
|
||||
const { data } = await $.http.put(
|
||||
`/3.0/campaigns/${campaign.id}/content`,
|
||||
campaignBody
|
||||
);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
@@ -1,4 +0,0 @@
|
||||
import createCampaign from './create-campaign/index.js';
|
||||
import sendCampaign from './send-campaign/index.js';
|
||||
|
||||
export default [createCampaign, sendCampaign];
|
@@ -1,39 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Send campaign',
|
||||
key: 'sendCampaign',
|
||||
description: 'Sends a campaign draft.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Campaign',
|
||||
key: 'campaignId',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listCampaigns',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const campaignId = $.step.parameters.campaignId;
|
||||
|
||||
await $.http.post(`/3.0/campaigns/${campaignId}/actions/send`);
|
||||
|
||||
$.setActionItem({
|
||||
raw: {
|
||||
output: 'sent',
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 5.0 KiB |
@@ -1,19 +0,0 @@
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
export default async function generateAuthUrl($) {
|
||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||
(field) => field.key == 'oAuthRedirectUrl'
|
||||
);
|
||||
const redirectUri = oauthRedirectUrlField.value;
|
||||
const searchParams = new URLSearchParams({
|
||||
response_type: 'code',
|
||||
client_id: $.auth.data.clientId,
|
||||
redirect_uri: redirectUri,
|
||||
});
|
||||
|
||||
const url = `https://login.mailchimp.com/oauth2/authorize?${searchParams.toString()}`;
|
||||
|
||||
await $.auth.set({
|
||||
url,
|
||||
});
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
import generateAuthUrl from './generate-auth-url.js';
|
||||
import verifyCredentials from './verify-credentials.js';
|
||||
import isStillVerified from './is-still-verified.js';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'oAuthRedirectUrl',
|
||||
label: 'OAuth Redirect URL',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: true,
|
||||
value: '{WEB_APP_URL}/app/mailchimp/connections/add',
|
||||
placeholder: null,
|
||||
description:
|
||||
'When asked to input a redirect URL in Mailchimp, enter the URL above.',
|
||||
clickToCopy: true,
|
||||
},
|
||||
{
|
||||
key: 'clientId',
|
||||
label: 'Client ID',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'clientSecret',
|
||||
label: 'Client Secret',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
],
|
||||
|
||||
generateAuthUrl,
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
};
|
@@ -1,8 +0,0 @@
|
||||
import getCurrentUser from '../common/get-current-user.js';
|
||||
|
||||
const isStillVerified = async ($) => {
|
||||
const currentUser = await getCurrentUser($);
|
||||
return !!currentUser.user_id;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
@@ -1,40 +0,0 @@
|
||||
import getCurrentUser from '../common/get-current-user.js';
|
||||
|
||||
const verifyCredentials = async ($) => {
|
||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||
(field) => field.key == 'oAuthRedirectUrl'
|
||||
);
|
||||
const redirectUri = oauthRedirectUrlField.value;
|
||||
const params = new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
client_id: $.auth.data.clientId,
|
||||
client_secret: $.auth.data.clientSecret,
|
||||
redirect_uri: redirectUri,
|
||||
code: $.auth.data.code,
|
||||
});
|
||||
|
||||
const { data } = await $.http.post(
|
||||
'https://login.mailchimp.com/oauth2/token',
|
||||
params.toString()
|
||||
);
|
||||
|
||||
await $.auth.set({
|
||||
accessToken: data.access_token,
|
||||
tokenType: data.token_type,
|
||||
});
|
||||
|
||||
const currentUser = await getCurrentUser($);
|
||||
|
||||
await $.auth.set({
|
||||
clientId: $.auth.data.clientId,
|
||||
clientSecret: $.auth.data.clientSecret,
|
||||
scope: $.auth.data.scope,
|
||||
idToken: data.id_token,
|
||||
expiresIn: data.expires_in,
|
||||
refreshToken: data.refresh_token,
|
||||
serverPrefix: currentUser.dc,
|
||||
screenName: currentUser.login.login_name,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
@@ -1,12 +0,0 @@
|
||||
const addAuthHeader = ($, requestConfig) => {
|
||||
if (
|
||||
!requestConfig.additionalProperties?.skipAddingAuthHeader &&
|
||||
$.auth.data?.accessToken
|
||||
) {
|
||||
requestConfig.headers.Authorization = `Bearer ${$.auth.data.accessToken}`;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user