Compare commits
205 Commits
formatter-
...
AUT-366
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2846dd2bdd | ||
![]() |
2fceaf2cf4 | ||
![]() |
d82b50fcdb | ||
![]() |
ab6e49bf4f | ||
![]() |
ee90422f56 | ||
![]() |
627184f124 | ||
![]() |
fa02edfefc | ||
![]() |
61afebc827 | ||
![]() |
a4c22799e7 | ||
![]() |
870a110a75 | ||
![]() |
8c859f9408 | ||
![]() |
0a36101da1 | ||
![]() |
c1bf063b12 | ||
![]() |
0da56a800d | ||
![]() |
4d2172d153 | ||
![]() |
d0fab0e1f1 | ||
![]() |
4cedbdbc60 | ||
![]() |
a82d34cbce | ||
![]() |
16d0c243c7 | ||
![]() |
855901bd9e | ||
![]() |
6be8a581d2 | ||
![]() |
655deb12c8 | ||
![]() |
31b1b9457b | ||
![]() |
c4394228f2 | ||
![]() |
98e6dbe141 | ||
![]() |
4fac1ef7c4 | ||
![]() |
034bc6a79e | ||
![]() |
94e64676af | ||
![]() |
3a638220af | ||
![]() |
0772308bf5 | ||
![]() |
9f5ea80731 | ||
![]() |
fb1f520096 | ||
![]() |
dd36609443 | ||
![]() |
4eace3fb7e | ||
![]() |
f13e93e2ce | ||
![]() |
da4f8ab529 | ||
![]() |
b6ff4ec992 | ||
![]() |
25f6cac69a | ||
![]() |
172a8934e3 | ||
![]() |
aead014bcf | ||
![]() |
59770c80db | ||
![]() |
6d6b77148d | ||
![]() |
c1e8f5765f | ||
![]() |
76e442940b | ||
![]() |
b2205097da | ||
![]() |
14886d42e8 | ||
![]() |
2f35403078 | ||
![]() |
961d55a1c6 | ||
![]() |
0fca0ef734 | ||
![]() |
cc3acd81bc | ||
![]() |
69a691c19e | ||
![]() |
e0a4f5c9c9 | ||
![]() |
cabf9b8fb8 | ||
![]() |
61e24da07d | ||
![]() |
648511dfad | ||
![]() |
dfc9efc31a | ||
![]() |
b58a22addc | ||
![]() |
e07a9eeda2 | ||
![]() |
f0de42fa63 | ||
![]() |
0121661ad0 | ||
![]() |
fb6e46bd69 | ||
![]() |
9bd041799b | ||
![]() |
9e191c4ed9 | ||
![]() |
794b4cf26a | ||
![]() |
2d8421943f | ||
![]() |
48dc2312d9 | ||
![]() |
cdf7a1adc4 | ||
![]() |
99ebd12081 | ||
![]() |
859337b5c1 | ||
![]() |
1e601559a0 | ||
![]() |
9314cba724 | ||
![]() |
25224f0308 | ||
![]() |
9a981d5373 | ||
![]() |
c7116361ab | ||
![]() |
1f17236c4f | ||
![]() |
67f415de35 | ||
![]() |
b890150817 | ||
![]() |
4de1fc49df | ||
![]() |
fb80d5d70d | ||
![]() |
eaa25e412a | ||
![]() |
706142f98e | ||
![]() |
36a72d0a32 | ||
![]() |
1d44d387ac | ||
![]() |
f93c41f2d8 | ||
![]() |
5b13f880c8 | ||
![]() |
c4af873036 | ||
![]() |
fe820fb4fe | ||
![]() |
82ad0735d2 | ||
![]() |
8b0a421924 | ||
![]() |
d44cb3d92e | ||
![]() |
5f335ef5b3 | ||
![]() |
5831bf9653 | ||
![]() |
2480dfbb6d | ||
![]() |
162b352ea5 | ||
![]() |
9f30d7d7ba | ||
![]() |
27c296bb89 | ||
![]() |
ef67908451 | ||
![]() |
3dedc3bfc7 | ||
![]() |
65d509c97f | ||
![]() |
11f38c4d3a | ||
![]() |
3bca6497f7 | ||
![]() |
23d79b9265 | ||
![]() |
12c53a3d4d | ||
![]() |
1dfe58ec02 | ||
![]() |
7615e62bbc | ||
![]() |
53189a6487 | ||
![]() |
027b11c3fb | ||
![]() |
453ab7de66 | ||
![]() |
58f8ded161 | ||
![]() |
497ce2e84f | ||
![]() |
3794c6f508 | ||
![]() |
ee6c9fa5d4 | ||
![]() |
1369bb095f | ||
![]() |
c786d7549a | ||
![]() |
b59840cb77 | ||
![]() |
265d57d8b7 | ||
![]() |
5eed84f9e5 | ||
![]() |
0a334dff1d | ||
![]() |
5fff9bdc02 | ||
![]() |
a9fd261bab | ||
![]() |
ef087be4f0 | ||
![]() |
2099978b8f | ||
![]() |
712bee297a | ||
![]() |
57bba90091 | ||
![]() |
d877f5c764 | ||
![]() |
4c66cc1e33 | ||
![]() |
27a3edeb93 | ||
![]() |
f79fc29203 | ||
![]() |
174240a220 | ||
![]() |
60d8af5c16 | ||
![]() |
627a5892f1 | ||
![]() |
7767f6d9cc | ||
![]() |
9729fd6b15 | ||
![]() |
17916f29f6 | ||
![]() |
584b9323ec | ||
![]() |
82c1aadfa9 | ||
![]() |
bd497af89b | ||
![]() |
1683c5630a | ||
![]() |
b5df1a026a | ||
![]() |
b290c32aeb | ||
![]() |
a29b3c6db4 | ||
![]() |
ffb2f4f5db | ||
![]() |
24c95f4801 | ||
![]() |
1aaec2d555 | ||
![]() |
fedb198ae7 | ||
![]() |
add654ccac | ||
![]() |
5a578643a6 | ||
![]() |
f0712bd213 | ||
![]() |
f490632722 | ||
![]() |
2610b96762 | ||
![]() |
8d90cb834d | ||
![]() |
9d92509796 | ||
![]() |
04a78ee0ba | ||
![]() |
3703390268 | ||
![]() |
4ab6415f49 | ||
![]() |
9228722147 | ||
![]() |
0e5529b4ca | ||
![]() |
4d454ec932 | ||
![]() |
a9282ad118 | ||
![]() |
0e959641af | ||
![]() |
13263eea76 | ||
![]() |
1a3418de58 | ||
![]() |
4402995132 | ||
![]() |
4e33f9875b | ||
![]() |
ed2893e37f | ||
![]() |
c35be241ca | ||
![]() |
aad0b4ddfe | ||
![]() |
52f5c7ddb5 | ||
![]() |
a04b933161 | ||
![]() |
c77e12edbb | ||
![]() |
108bd04cf8 | ||
![]() |
a95b500e42 | ||
![]() |
c2744c5569 | ||
![]() |
a1dfd87bbe | ||
![]() |
221aa8687f | ||
![]() |
fa8ac0a8ba | ||
![]() |
cc1f9873cb | ||
![]() |
3cae9ee5d2 | ||
![]() |
f764914adb | ||
![]() |
991250c73f | ||
![]() |
af46cf5ce8 | ||
![]() |
dbb1c42c47 | ||
![]() |
991f593b2e | ||
![]() |
e43c083d50 | ||
![]() |
3cd9bdc1d4 | ||
![]() |
c0b8e6178d | ||
![]() |
410f9d0af5 | ||
![]() |
b1fedf28dc | ||
![]() |
b0df03dcd2 | ||
![]() |
2794e50a19 | ||
![]() |
365ae656f2 | ||
![]() |
98649dcba6 | ||
![]() |
213c8096d2 | ||
![]() |
398938f27e | ||
![]() |
6378e62645 | ||
![]() |
251885d4be | ||
![]() |
f53909355f | ||
![]() |
242b68889a | ||
![]() |
6a66b65f2a | ||
![]() |
f30ead6bcb | ||
![]() |
237ee72ca6 | ||
![]() |
3590d84ad6 | ||
![]() |
2dae8c162d | ||
![]() |
9a192b708e | ||
![]() |
337d22bbf4 |
48
.github/workflows/backend.yml
vendored
Normal file
48
.github/workflows/backend.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: Automatisch Backend Tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 60
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:14.5-alpine
|
||||
env:
|
||||
POSTGRES_DB: automatisch_test
|
||||
POSTGRES_USER: automatisch_test_user
|
||||
POSTGRES_PASSWORD: automatisch_test_user_password
|
||||
options: >-
|
||||
--health-cmd "pg_isready -U automatisch_test_user -d automatisch_test"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
redis:
|
||||
image: redis:7.0.4-alpine
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install dependencies
|
||||
run: cd packages/backend && yarn
|
||||
- name: Copy .env-example.test file to .env.test
|
||||
run: cd packages/backend && cp .env-example.test .env.test
|
||||
- name: Run tests
|
||||
run: cd packages/backend && yarn test
|
34
.github/workflows/playwright.yml
vendored
34
.github/workflows/playwright.yml
vendored
@@ -17,12 +17,13 @@ env:
|
||||
POSTGRES_PASSWORD: automatisch_password
|
||||
REDIS_HOST: localhost
|
||||
APP_ENV: production
|
||||
LICENSE_KEY: ${{ secrets.E2E_LICENSE_KEY }}
|
||||
LICENSE_KEY: dummy_license_key
|
||||
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:14.5-alpine
|
||||
@@ -67,22 +68,49 @@ jobs:
|
||||
- name: Seed user
|
||||
working-directory: ./packages/backend
|
||||
run: yarn db:seed:user &
|
||||
- name: Install certutils
|
||||
run: sudo apt install -y libnss3-tools
|
||||
- name: Install mkcert
|
||||
run: |
|
||||
curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64" \
|
||||
&& chmod +x mkcert-v*-linux-amd64 \
|
||||
&& sudo cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert
|
||||
- name: Install root certificate via mkcert
|
||||
run: mkcert -install
|
||||
- name: Create certificate
|
||||
run: mkcert automatisch.io "*.automatisch.io" localhost 127.0.0.1 ::1
|
||||
working-directory: ./packages/e2e-tests
|
||||
- name: Set CAROOT environment variable
|
||||
run: echo "NODE_EXTRA_CA_CERTS=$(mkcert -CAROOT)/rootCA.pem" >> "$GITHUB_ENV"
|
||||
- name: Override license server with local server
|
||||
run: sudo echo "127.0.0.1 license.automatisch.io" | sudo tee -a /etc/hosts
|
||||
- name: Run local license server
|
||||
working-directory: ./packages/e2e-tests
|
||||
run: sudo yarn start-mock-license-server &
|
||||
- name: Run Automatisch
|
||||
run: yarn start &
|
||||
working-directory: ./packages/backend
|
||||
- name: Run Automatisch worker
|
||||
run: node dist/src/worker.js &
|
||||
working-directory: ./packages/backend
|
||||
- name: Setup upterm session
|
||||
if: false
|
||||
uses: lhotari/action-upterm@v1
|
||||
with:
|
||||
limit-access-to-actor: true
|
||||
limit-access-to-users: barinali
|
||||
- name: Run Playwright tests
|
||||
working-directory: ./packages/e2e-tests
|
||||
env:
|
||||
LOGIN_EMAIL: user@automatisch.io
|
||||
LOGIN_PASSWORD: sample
|
||||
BASE_URL: http://localhost:3000
|
||||
GITHUB_CLIENT_ID: 1c0417daf898adfbd99a
|
||||
GITHUB_CLIENT_SECRET: 3328fa814dd582ccd03dbe785cfd683fb8da92b3
|
||||
run: yarn test
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: ./packages/e2e-tests/test-results/**/*
|
||||
path: packages/e2e-tests/test-results
|
||||
retention-days: 30
|
||||
|
@@ -3,14 +3,13 @@ HOST=localhost
|
||||
PROTOCOL=http
|
||||
PORT=3000
|
||||
LOG_LEVEL=debug
|
||||
WEBHOOK_SECRET_KEY=secret
|
||||
ENCRYPTION_KEY=sample_encryption_key
|
||||
WEBHOOK_SECRET_KEY=sample_webhook_secret_key
|
||||
APP_SECRET_KEY=sample_app_secret_key
|
||||
POSTGRES_HOST=localhost
|
||||
POSTGRES_DATABASE=automatisch_test
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_HOST=localhost
|
||||
POSTGRES_USERNAME=automatisch_test_user
|
||||
POSTGRES_PASSWORD=
|
||||
POSTGRES_ENABLE_SSL=false
|
||||
ENCRYPTION_KEY=secret
|
||||
APP_SECRET_KEY=secret
|
||||
REDIS_PORT=6379
|
||||
REDIS_HOST=127.0.0.1
|
||||
POSTGRES_PASSWORD=automatisch_test_user_password
|
||||
REDIS_HOST=localhost
|
||||
AUTOMATISCH_CLOUD=true
|
||||
|
@@ -1,5 +0,0 @@
|
||||
export default {
|
||||
require: ['ts-node/register', './src/config/app.ts'],
|
||||
files: ['**/*.test.ts'],
|
||||
extensions: ['ts'],
|
||||
};
|
7
packages/backend/jest.config.js
Normal file
7
packages/backend/jest.config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
setupFilesAfterEnv: ['./test/setup/global-hooks.ts'],
|
||||
globalTeardown: './test/setup/global-teardown.ts',
|
||||
};
|
@@ -1,6 +1,7 @@
|
||||
import { knexSnakeCaseMappers } from 'objection';
|
||||
import appConfig from './src/config/app';
|
||||
|
||||
const fileExtension = appConfig.isDev ? 'ts' : 'js';
|
||||
const fileExtension = appConfig.isDev || appConfig.isTest ? 'ts' : 'js';
|
||||
|
||||
const knexConfig = {
|
||||
client: 'pg',
|
||||
@@ -23,6 +24,7 @@ const knexConfig = {
|
||||
seeds: {
|
||||
directory: __dirname + '/src/db/seeds',
|
||||
},
|
||||
...(appConfig.isTest ? knexSnakeCaseMappers() : {}),
|
||||
};
|
||||
|
||||
export default knexConfig;
|
||||
|
@@ -10,7 +10,7 @@
|
||||
"build:watch": "nodemon --watch 'src/**/*.ts' --watch 'bin/**/*.ts' --exec yarn build --ext ts",
|
||||
"start": "node dist/src/server.js",
|
||||
"pretest": "APP_ENV=test ts-node ./test/setup/prepare-test-env.ts",
|
||||
"test": "APP_ENV=test ava",
|
||||
"test": "APP_ENV=test jest --verbose",
|
||||
"lint": "eslint . --ignore-path ../../.eslintignore",
|
||||
"db:create": "ts-node ./bin/database/create.ts",
|
||||
"db:seed:user": "ts-node ./bin/database/seed-user.ts",
|
||||
@@ -60,6 +60,7 @@
|
||||
"https-proxy-agent": "^7.0.1",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"knex": "^2.4.0",
|
||||
"libphonenumber-js": "^1.10.48",
|
||||
"lodash.get": "^4.4.2",
|
||||
"luxon": "2.5.2",
|
||||
"memory-cache": "^0.2.0",
|
||||
@@ -73,6 +74,7 @@
|
||||
"pg": "^8.7.1",
|
||||
"php-serialize": "^4.0.2",
|
||||
"pluralize": "^8.0.0",
|
||||
"raw-body": "^2.5.2",
|
||||
"showdown": "^2.1.0",
|
||||
"stripe": "^11.13.0",
|
||||
"winston": "^3.7.1",
|
||||
@@ -115,12 +117,14 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@automatisch/types": "^0.9.3",
|
||||
"@faker-js/faker": "^8.1.0",
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
"@types/bull": "^3.15.8",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/crypto-js": "^4.0.2",
|
||||
"@types/express": "^4.17.15",
|
||||
"@types/http-errors": "^1.8.1",
|
||||
"@types/jest": "^29.5.5",
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
"@types/lodash.get": "^4.4.6",
|
||||
"@types/memory-cache": "^0.2.2",
|
||||
@@ -132,9 +136,12 @@
|
||||
"@types/pino": "^7.0.5",
|
||||
"@types/pluralize": "^0.0.30",
|
||||
"@types/showdown": "^2.0.1",
|
||||
"ava": "^5.3.1",
|
||||
"@types/supertest": "^2.0.14",
|
||||
"jest": "^29.7.0",
|
||||
"nodemon": "^2.0.13",
|
||||
"sinon": "^11.1.2",
|
||||
"supertest": "^6.3.3",
|
||||
"ts-jest": "^29.1.1",
|
||||
"ts-node": "^10.2.1",
|
||||
"ts-node-dev": "^1.1.8"
|
||||
},
|
||||
|
@@ -33,6 +33,7 @@ injectBullBoardHandler(app, serverAdapter);
|
||||
appAssetsHandler(app);
|
||||
|
||||
app.use(morgan);
|
||||
|
||||
app.use(
|
||||
express.json({
|
||||
limit: appConfig.requestBodySizeLimit,
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import Crypto from 'crypto';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import webhookFilters from '../../common/webhook-filters';
|
||||
@@ -19,6 +20,17 @@ export default defineTrigger({
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import text from './text';
|
||||
import numbers from './numbers';
|
||||
import dateTime from './date-time';
|
||||
import utilities from './utilities';
|
||||
|
||||
export default [text, numbers, dateTime, utilities];
|
||||
export default [text, numbers, dateTime];
|
||||
|
@@ -3,11 +3,13 @@ import defineAction from '../../../../helpers/define-action';
|
||||
import performMathOperation from './transformers/perform-math-operation';
|
||||
import randomNumber from './transformers/random-number';
|
||||
import formatNumber from './transformers/format-number';
|
||||
import formatPhoneNumber from './transformers/format-phone-number';
|
||||
|
||||
const transformers = {
|
||||
performMathOperation,
|
||||
randomNumber,
|
||||
formatNumber,
|
||||
formatPhoneNumber,
|
||||
};
|
||||
|
||||
export default defineAction({
|
||||
@@ -26,6 +28,7 @@ export default defineAction({
|
||||
{ label: 'Perform Math Operation', value: 'performMathOperation' },
|
||||
{ label: 'Random Number', value: 'randomNumber' },
|
||||
{ label: 'Format Number', value: 'formatNumber' },
|
||||
{ label: 'Format Phone Number', value: 'formatPhoneNumber' },
|
||||
],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
|
@@ -0,0 +1,24 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import parsePhoneNumber, { CountryCode } from 'libphonenumber-js';
|
||||
|
||||
const formatPhoneNumber = ($: IGlobalVariable) => {
|
||||
const phoneNumber = $.step.parameters.phoneNumber as string;
|
||||
const toFormat = $.step.parameters.toFormat as string;
|
||||
const phoneNumberCountryCode = ($.step.parameters.phoneNumberCountryCode ||
|
||||
'US') as CountryCode;
|
||||
|
||||
const parsedPhoneNumber = parsePhoneNumber(
|
||||
phoneNumber,
|
||||
phoneNumberCountryCode
|
||||
);
|
||||
|
||||
if (toFormat === 'e164') {
|
||||
return parsedPhoneNumber.format('E.164');
|
||||
} else if (toFormat === 'international') {
|
||||
return parsedPhoneNumber.formatInternational();
|
||||
} else if (toFormat === 'national') {
|
||||
return parsedPhoneNumber.formatNational();
|
||||
}
|
||||
};
|
||||
|
||||
export default formatPhoneNumber;
|
@@ -1,54 +0,0 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
import findArrayItemByProperty from './transformers/find-array-item-by-property';
|
||||
|
||||
const transformers = {
|
||||
findArrayItemByProperty,
|
||||
};
|
||||
|
||||
export default defineAction({
|
||||
name: 'Utilities',
|
||||
key: 'utilities',
|
||||
description: 'Specific utilities to help you transform your data.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Transform',
|
||||
key: 'transform',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Find Array Item By Property',
|
||||
value: 'findArrayItemByProperty',
|
||||
},
|
||||
],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listTransformOptions',
|
||||
},
|
||||
{
|
||||
name: 'parameters.transform',
|
||||
value: '{parameters.transform}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const transformerName = $.step.parameters
|
||||
.transform as keyof typeof transformers;
|
||||
const output = transformers[transformerName]($);
|
||||
|
||||
$.setActionItem({
|
||||
raw: {
|
||||
output,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
@@ -1,13 +0,0 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import { find } from 'lodash';
|
||||
|
||||
const findArrayItemByProperty = ($: IGlobalVariable) => {
|
||||
const value = JSON.parse($.step.parameters.value as string);
|
||||
const propertyName = $.step.parameters.propertyName as string;
|
||||
const propertyValue = $.step.parameters.propertyValue as string;
|
||||
|
||||
const foundItem = find(value, { [propertyName]: propertyValue });
|
||||
return foundItem;
|
||||
};
|
||||
|
||||
export default findArrayItemByProperty;
|
@@ -0,0 +1,249 @@
|
||||
const phoneNumberCountryCodes = [
|
||||
{ label: 'Ascension Island', value: 'AC' },
|
||||
{ label: 'Andorra', value: 'AD' },
|
||||
{ label: 'United Arab Emirates', value: 'AE' },
|
||||
{ label: 'Afghanistan', value: 'AF' },
|
||||
{ label: 'Antigua & Barbuda', value: 'AG' },
|
||||
{ label: 'Anguilla', value: 'AI' },
|
||||
{ label: 'Albania', value: 'AL' },
|
||||
{ label: 'Armenia', value: 'AM' },
|
||||
{ label: 'Angola', value: 'AO' },
|
||||
{ label: 'Argentina', value: 'AR' },
|
||||
{ label: 'American Samoa', value: 'AS' },
|
||||
{ label: 'Austria', value: 'AT' },
|
||||
{ label: 'Australia', value: 'AU' },
|
||||
{ label: 'Aruba', value: 'AW' },
|
||||
{ label: 'Åland Islands', value: 'AX' },
|
||||
{ label: 'Azerbaijan', value: 'AZ' },
|
||||
{ label: 'Bosnia & Herzegovina', value: 'BA' },
|
||||
{ label: 'Barbados', value: 'BB' },
|
||||
{ label: 'Bangladesh', value: 'BD' },
|
||||
{ label: 'Belgium', value: 'BE' },
|
||||
{ label: 'Burkina Faso', value: 'BF' },
|
||||
{ label: 'Bulgaria', value: 'BG' },
|
||||
{ label: 'Bahrain', value: 'BH' },
|
||||
{ label: 'Burundi', value: 'BI' },
|
||||
{ label: 'Benin', value: 'BJ' },
|
||||
{ label: 'St. Barthélemy', value: 'BL' },
|
||||
{ label: 'Bermuda', value: 'BM' },
|
||||
{ label: 'Brunei', value: 'BN' },
|
||||
{ label: 'Bolivia', value: 'BO' },
|
||||
{ label: 'Caribbean Netherlands', value: 'BQ' },
|
||||
{ label: 'Brazil', value: 'BR' },
|
||||
{ label: 'Bahamas', value: 'BS' },
|
||||
{ label: 'Bhutan', value: 'BT' },
|
||||
{ label: 'Botswana', value: 'BW' },
|
||||
{ label: 'Belarus', value: 'BY' },
|
||||
{ label: 'Belize', value: 'BZ' },
|
||||
{ label: 'Canada', value: 'CA' },
|
||||
{ label: 'Cocos (Keeling) Islands', value: 'CC' },
|
||||
{ label: 'Congo - Kinshasa', value: 'CD' },
|
||||
{ label: 'Central African Republic', value: 'CF' },
|
||||
{ label: 'Congo - Brazzaville', value: 'CG' },
|
||||
{ label: 'Switzerland', value: 'CH' },
|
||||
{ label: 'Côte d’Ivoire', value: 'CI' },
|
||||
{ label: 'Cook Islands', value: 'CK' },
|
||||
{ label: 'Chile', value: 'CL' },
|
||||
{ label: 'Cameroon', value: 'CM' },
|
||||
{ label: 'China', value: 'CN' },
|
||||
{ label: 'Colombia', value: 'CO' },
|
||||
{ label: 'Costa Rica', value: 'CR' },
|
||||
{ label: 'Cuba', value: 'CU' },
|
||||
{ label: 'Cape Verde', value: 'CV' },
|
||||
{ label: 'Curaçao', value: 'CW' },
|
||||
{ label: 'Christmas Island', value: 'CX' },
|
||||
{ label: 'Cyprus', value: 'CY' },
|
||||
{ label: 'Czechia', value: 'CZ' },
|
||||
{ label: 'Germany', value: 'DE' },
|
||||
{ label: 'Djibouti', value: 'DJ' },
|
||||
{ label: 'Denmark', value: 'DK' },
|
||||
{ label: 'Dominica', value: 'DM' },
|
||||
{ label: 'Dominican Republic', value: 'DO' },
|
||||
{ label: 'Algeria', value: 'DZ' },
|
||||
{ label: 'Ecuador', value: 'EC' },
|
||||
{ label: 'Estonia', value: 'EE' },
|
||||
{ label: 'Egypt', value: 'EG' },
|
||||
{ label: 'Western Sahara', value: 'EH' },
|
||||
{ label: 'Eritrea', value: 'ER' },
|
||||
{ label: 'Spain', value: 'ES' },
|
||||
{ label: 'Ethiopia', value: 'ET' },
|
||||
{ label: 'Finland', value: 'FI' },
|
||||
{ label: 'Fiji', value: 'FJ' },
|
||||
{ label: 'Falkland Islands (Islas Malvinas)', value: 'FK' },
|
||||
{ label: 'Micronesia', value: 'FM' },
|
||||
{ label: 'Faroe Islands', value: 'FO' },
|
||||
{ label: 'France', value: 'FR' },
|
||||
{ label: 'Gabon', value: 'GA' },
|
||||
{ label: 'United Kingdom', value: 'GB' },
|
||||
{ label: 'Grenada', value: 'GD' },
|
||||
{ label: 'Georgia', value: 'GE' },
|
||||
{ label: 'French Guiana', value: 'GF' },
|
||||
{ label: 'Guernsey', value: 'GG' },
|
||||
{ label: 'Ghana', value: 'GH' },
|
||||
{ label: 'Gibraltar', value: 'GI' },
|
||||
{ label: 'Greenland', value: 'GL' },
|
||||
{ label: 'Gambia', value: 'GM' },
|
||||
{ label: 'Guinea', value: 'GN' },
|
||||
{ label: 'Guadeloupe', value: 'GP' },
|
||||
{ label: 'Equatorial Guinea', value: 'GQ' },
|
||||
{ label: 'Greece', value: 'GR' },
|
||||
{ label: 'Guatemala', value: 'GT' },
|
||||
{ label: 'Guam', value: 'GU' },
|
||||
{ label: 'Guinea-Bissau', value: 'GW' },
|
||||
{ label: 'Guyana', value: 'GY' },
|
||||
{ label: 'Hong Kong', value: 'HK' },
|
||||
{ label: 'Honduras', value: 'HN' },
|
||||
{ label: 'Croatia', value: 'HR' },
|
||||
{ label: 'Haiti', value: 'HT' },
|
||||
{ label: 'Hungary', value: 'HU' },
|
||||
{ label: 'Indonesia', value: 'ID' },
|
||||
{ label: 'Ireland', value: 'IE' },
|
||||
{ label: 'Israel', value: 'IL' },
|
||||
{ label: 'Isle of Man', value: 'IM' },
|
||||
{ label: 'India', value: 'IN' },
|
||||
{ label: 'British Indian Ocean Territory', value: 'IO' },
|
||||
{ label: 'Iraq', value: 'IQ' },
|
||||
{ label: 'Iran', value: 'IR' },
|
||||
{ label: 'Iceland', value: 'IS' },
|
||||
{ label: 'Italy', value: 'IT' },
|
||||
{ label: 'Jersey', value: 'JE' },
|
||||
{ label: 'Jamaica', value: 'JM' },
|
||||
{ label: 'Jordan', value: 'JO' },
|
||||
{ label: 'Japan', value: 'JP' },
|
||||
{ label: 'Kenya', value: 'KE' },
|
||||
{ label: 'Kyrgyzstan', value: 'KG' },
|
||||
{ label: 'Cambodia', value: 'KH' },
|
||||
{ label: 'Kiribati', value: 'KI' },
|
||||
{ label: 'Comoros', value: 'KM' },
|
||||
{ label: 'St. Kitts & Nevis', value: 'KN' },
|
||||
{ label: 'North Korea', value: 'KP' },
|
||||
{ label: 'South Korea', value: 'KR' },
|
||||
{ label: 'Kuwait', value: 'KW' },
|
||||
{ label: 'Cayman Islands', value: 'KY' },
|
||||
{ label: 'Kazakhstan', value: 'KZ' },
|
||||
{ label: 'Laos', value: 'LA' },
|
||||
{ label: 'Lebanon', value: 'LB' },
|
||||
{ label: 'St. Lucia', value: 'LC' },
|
||||
{ label: 'Liechtenstein', value: 'LI' },
|
||||
{ label: 'Sri Lanka', value: 'LK' },
|
||||
{ label: 'Liberia', value: 'LR' },
|
||||
{ label: 'Lesotho', value: 'LS' },
|
||||
{ label: 'Lithuania', value: 'LT' },
|
||||
{ label: 'Luxembourg', value: 'LU' },
|
||||
{ label: 'Latvia', value: 'LV' },
|
||||
{ label: 'Libya', value: 'LY' },
|
||||
{ label: 'Morocco', value: 'MA' },
|
||||
{ label: 'Monaco', value: 'MC' },
|
||||
{ label: 'Moldova', value: 'MD' },
|
||||
{ label: 'Montenegro', value: 'ME' },
|
||||
{ label: 'St. Martin', value: 'MF' },
|
||||
{ label: 'Madagascar', value: 'MG' },
|
||||
{ label: 'Marshall Islands', value: 'MH' },
|
||||
{ label: 'North Macedonia', value: 'MK' },
|
||||
{ label: 'Mali', value: 'ML' },
|
||||
{ label: 'Myanmar (Burma)', value: 'MM' },
|
||||
{ label: 'Mongolia', value: 'MN' },
|
||||
{ label: 'Macao', value: 'MO' },
|
||||
{ label: 'Northern Mariana Islands', value: 'MP' },
|
||||
{ label: 'Martinique', value: 'MQ' },
|
||||
{ label: 'Mauritania', value: 'MR' },
|
||||
{ label: 'Montserrat', value: 'MS' },
|
||||
{ label: 'Malta', value: 'MT' },
|
||||
{ label: 'Mauritius', value: 'MU' },
|
||||
{ label: 'Maldives', value: 'MV' },
|
||||
{ label: 'Malawi', value: 'MW' },
|
||||
{ label: 'Mexico', value: 'MX' },
|
||||
{ label: 'Malaysia', value: 'MY' },
|
||||
{ label: 'Mozambique', value: 'MZ' },
|
||||
{ label: 'Namibia', value: 'NA' },
|
||||
{ label: 'New Caledonia', value: 'NC' },
|
||||
{ label: 'Niger', value: 'NE' },
|
||||
{ label: 'Norfolk Island', value: 'NF' },
|
||||
{ label: 'Nigeria', value: 'NG' },
|
||||
{ label: 'Nicaragua', value: 'NI' },
|
||||
{ label: 'Netherlands', value: 'NL' },
|
||||
{ label: 'Norway', value: 'NO' },
|
||||
{ label: 'Nepal', value: 'NP' },
|
||||
{ label: 'Nauru', value: 'NR' },
|
||||
{ label: 'Niue', value: 'NU' },
|
||||
{ label: 'New Zealand', value: 'NZ' },
|
||||
{ label: 'Oman', value: 'OM' },
|
||||
{ label: 'Panama', value: 'PA' },
|
||||
{ label: 'Peru', value: 'PE' },
|
||||
{ label: 'French Polynesia', value: 'PF' },
|
||||
{ label: 'Papua New Guinea', value: 'PG' },
|
||||
{ label: 'Philippines', value: 'PH' },
|
||||
{ label: 'Pakistan', value: 'PK' },
|
||||
{ label: 'Poland', value: 'PL' },
|
||||
{ label: 'St. Pierre & Miquelon', value: 'PM' },
|
||||
{ label: 'Puerto Rico', value: 'PR' },
|
||||
{ label: 'Palestine', value: 'PS' },
|
||||
{ label: 'Portugal', value: 'PT' },
|
||||
{ label: 'Palau', value: 'PW' },
|
||||
{ label: 'Paraguay', value: 'PY' },
|
||||
{ label: 'Qatar', value: 'QA' },
|
||||
{ label: 'Réunion', value: 'RE' },
|
||||
{ label: 'Romania', value: 'RO' },
|
||||
{ label: 'Serbia', value: 'RS' },
|
||||
{ label: 'Russia', value: 'RU' },
|
||||
{ label: 'Rwanda', value: 'RW' },
|
||||
{ label: 'Saudi Arabia', value: 'SA' },
|
||||
{ label: 'Solomon Islands', value: 'SB' },
|
||||
{ label: 'Seychelles', value: 'SC' },
|
||||
{ label: 'Sudan', value: 'SD' },
|
||||
{ label: 'Sweden', value: 'SE' },
|
||||
{ label: 'Singapore', value: 'SG' },
|
||||
{ label: 'St. Helena', value: 'SH' },
|
||||
{ label: 'Slovenia', value: 'SI' },
|
||||
{ label: 'Svalbard & Jan Mayen', value: 'SJ' },
|
||||
{ label: 'Slovakia', value: 'SK' },
|
||||
{ label: 'Sierra Leone', value: 'SL' },
|
||||
{ label: 'San Marino', value: 'SM' },
|
||||
{ label: 'Senegal', value: 'SN' },
|
||||
{ label: 'Somalia', value: 'SO' },
|
||||
{ label: 'Suriname', value: 'SR' },
|
||||
{ label: 'South Sudan', value: 'SS' },
|
||||
{ label: 'São Tomé & Príncipe', value: 'ST' },
|
||||
{ label: 'El Salvador', value: 'SV' },
|
||||
{ label: 'Sint Maarten', value: 'SX' },
|
||||
{ label: 'Syria', value: 'SY' },
|
||||
{ label: 'Eswatini', value: 'SZ' },
|
||||
{ label: 'Tristan da Cunha', value: 'TA' },
|
||||
{ label: 'Turks & Caicos Islands', value: 'TC' },
|
||||
{ label: 'Chad', value: 'TD' },
|
||||
{ label: 'Togo', value: 'TG' },
|
||||
{ label: 'Thailand', value: 'TH' },
|
||||
{ label: 'Tajikistan', value: 'TJ' },
|
||||
{ label: 'Tokelau', value: 'TK' },
|
||||
{ label: 'Timor-Leste', value: 'TL' },
|
||||
{ label: 'Turkmenistan', value: 'TM' },
|
||||
{ label: 'Tunisia', value: 'TN' },
|
||||
{ label: 'Tonga', value: 'TO' },
|
||||
{ label: 'Türkiye', value: 'TR' },
|
||||
{ label: 'Trinidad & Tobago', value: 'TT' },
|
||||
{ label: 'Tuvalu', value: 'TV' },
|
||||
{ label: 'Taiwan', value: 'TW' },
|
||||
{ label: 'Tanzania', value: 'TZ' },
|
||||
{ label: 'Ukraine', value: 'UA' },
|
||||
{ label: 'Uganda', value: 'UG' },
|
||||
{ label: 'United States', value: 'US' },
|
||||
{ label: 'Uruguay', value: 'UY' },
|
||||
{ label: 'Uzbekistan', value: 'UZ' },
|
||||
{ label: 'Vatican City', value: 'VA' },
|
||||
{ label: 'St. Vincent & Grenadines', value: 'VC' },
|
||||
{ label: 'Venezuela', value: 'VE' },
|
||||
{ label: 'British Virgin Islands', value: 'VG' },
|
||||
{ label: 'U.S. Virgin Islands', value: 'VI' },
|
||||
{ label: 'Vietnam', value: 'VN' },
|
||||
{ label: 'Vanuatu', value: 'VU' },
|
||||
{ label: 'Wallis & Futuna', value: 'WF' },
|
||||
{ label: 'Samoa', value: 'WS' },
|
||||
{ label: 'Kosovo', value: 'XK' },
|
||||
{ label: 'Yemen', value: 'YE' },
|
||||
{ label: 'Mayotte', value: 'YT' },
|
||||
{ label: 'South Africa', value: 'ZA' },
|
||||
{ label: 'Zambia', value: 'ZM' },
|
||||
{ label: 'Zimbabwe', value: 'ZW' },
|
||||
];
|
||||
|
||||
export default phoneNumberCountryCodes;
|
@@ -2,35 +2,35 @@ import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
import capitalize from './text/capitalize';
|
||||
import extractEmailAddress from './text/extract-email-address';
|
||||
import extractNumber from './text/extract-number';
|
||||
import findArrayItemByProperty from './utilities/find-array-item-by-property';
|
||||
import formatDateTime from './date-time/format-date-time';
|
||||
import formatNumber from './numbers/format-number';
|
||||
import htmlToMarkdown from './text/html-to-markdown';
|
||||
import lowercase from './text/lowercase';
|
||||
import markdownToHtml from './text/markdown-to-html';
|
||||
import performMathOperation from './numbers/perform-math-operation';
|
||||
import pluralize from './text/pluralize';
|
||||
import randomNumber from './numbers/random-number';
|
||||
import replace from './text/replace';
|
||||
import trimWhitespace from './text/trim-whitespace';
|
||||
import useDefaultValue from './text/use-default-value';
|
||||
import performMathOperation from './numbers/perform-math-operation';
|
||||
import randomNumber from './numbers/random-number';
|
||||
import formatNumber from './numbers/format-number';
|
||||
import formatPhoneNumber from './numbers/format-phone-number';
|
||||
import formatDateTime from './date-time/format-date-time';
|
||||
|
||||
const options: IJSONObject = {
|
||||
capitalize,
|
||||
extractEmailAddress,
|
||||
extractNumber,
|
||||
findArrayItemByProperty,
|
||||
formatDateTime,
|
||||
formatNumber,
|
||||
htmlToMarkdown,
|
||||
lowercase,
|
||||
markdownToHtml,
|
||||
performMathOperation,
|
||||
pluralize,
|
||||
randomNumber,
|
||||
replace,
|
||||
trimWhitespace,
|
||||
useDefaultValue,
|
||||
performMathOperation,
|
||||
randomNumber,
|
||||
formatNumber,
|
||||
formatPhoneNumber,
|
||||
formatDateTime,
|
||||
};
|
||||
|
||||
export default {
|
||||
|
@@ -0,0 +1,36 @@
|
||||
import phoneNumberCountryCodes from '../../../common/phone-number-country-codes';
|
||||
|
||||
const formatPhoneNumber = [
|
||||
{
|
||||
label: 'Phone Number',
|
||||
key: 'phoneNumber',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'The phone number you want to format.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'To Format',
|
||||
key: 'toFormat',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The format you want to convert the number to.',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: '+491632223344 (E164)', value: 'e164' },
|
||||
{ label: '+49 163 2223344 (International)', value: 'international' },
|
||||
{ label: '0163 2223344 (National)', value: 'national' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Phone Number Country Code',
|
||||
key: 'phoneNumberCountryCode',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The country code of the phone number. The default is US.',
|
||||
variables: true,
|
||||
options: phoneNumberCountryCodes,
|
||||
},
|
||||
];
|
||||
|
||||
export default formatPhoneNumber;
|
@@ -1,28 +0,0 @@
|
||||
const findArrayItemByProperty = [
|
||||
{
|
||||
label: 'Value',
|
||||
key: 'value',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Array of objects that will be searched.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Property Name',
|
||||
key: 'propertyName',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Property name that will be searched.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Property Value',
|
||||
key: 'propertyValue',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Property value that will be matched.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default findArrayItemByProperty;
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -19,6 +20,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.confidential_issues_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_issues_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -19,6 +20,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.confidential_note_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_note_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.deployment_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.deployment_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.feature_flag_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.feature_flag_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.issues_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.issues_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -17,6 +18,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.job_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.job_events),
|
||||
unregisterHook,
|
||||
|
@@ -22,6 +22,17 @@ export const projectArgumentDescriptor = {
|
||||
},
|
||||
};
|
||||
|
||||
export const getRunFn = async ($: IGlobalVariable) => {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
};
|
||||
|
||||
export const getTestRunFn =
|
||||
(eventData: IJSONObject) => ($: IGlobalVariable) => {
|
||||
/*
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.merge_requests_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.merge_requests_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.note_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.note_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.pipeline_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.pipeline_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -54,6 +55,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
branchFilterStrategyArgumentDescriptor,
|
||||
pushEventsBranchFilterArgumentDescriptor,
|
||||
],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.push_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -17,6 +18,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.releases_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.releases_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.tag_push_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.tag_push_events),
|
||||
unregisterHook,
|
||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getRunFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
||||
key: GITLAB_EVENT_TYPE.wiki_page_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
run: ($) => getRunFn($),
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.wiki_page_events),
|
||||
unregisterHook,
|
||||
|
27
packages/backend/src/apps/google-calendar/assets/favicon.svg
Normal file
27
packages/backend/src/apps/google-calendar/assets/favicon.svg
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
|
||||
<g>
|
||||
<g transform="translate(3.75 3.75)">
|
||||
<path fill="#FFFFFF" d="M148.882,43.618l-47.368-5.263l-57.895,5.263L38.355,96.25l5.263,52.632l52.632,6.579l52.632-6.579
|
||||
l5.263-53.947L148.882,43.618z"/>
|
||||
<path fill="#1A73E8" d="M65.211,125.276c-3.934-2.658-6.658-6.539-8.145-11.671l9.132-3.763c0.829,3.158,2.276,5.605,4.342,7.342
|
||||
c2.053,1.737,4.553,2.592,7.474,2.592c2.987,0,5.553-0.908,7.697-2.724s3.224-4.132,3.224-6.934c0-2.868-1.132-5.211-3.395-7.026
|
||||
s-5.105-2.724-8.5-2.724h-5.276v-9.039H76.5c2.921,0,5.382-0.789,7.382-2.368c2-1.579,3-3.737,3-6.487
|
||||
c0-2.447-0.895-4.395-2.684-5.855s-4.053-2.197-6.803-2.197c-2.684,0-4.816,0.711-6.395,2.145s-2.724,3.197-3.447,5.276
|
||||
l-9.039-3.763c1.197-3.395,3.395-6.395,6.618-8.987c3.224-2.592,7.342-3.895,12.342-3.895c3.697,0,7.026,0.711,9.974,2.145
|
||||
c2.947,1.434,5.263,3.421,6.934,5.947c1.671,2.539,2.5,5.382,2.5,8.539c0,3.224-0.776,5.947-2.329,8.184
|
||||
c-1.553,2.237-3.461,3.947-5.724,5.145v0.539c2.987,1.25,5.421,3.158,7.342,5.724c1.908,2.566,2.868,5.632,2.868,9.211
|
||||
s-0.908,6.776-2.724,9.579c-1.816,2.803-4.329,5.013-7.513,6.618c-3.197,1.605-6.789,2.421-10.776,2.421
|
||||
C73.408,129.263,69.145,127.934,65.211,125.276z"/>
|
||||
<path fill="#1A73E8" d="M121.25,79.961l-9.974,7.25l-5.013-7.605l17.987-12.974h6.895v61.197h-9.895L121.25,79.961z"/>
|
||||
<path fill="#EA4335" d="M148.882,196.25l47.368-47.368l-23.684-10.526l-23.684,10.526l-10.526,23.684L148.882,196.25z"/>
|
||||
<path fill="#34A853" d="M33.092,172.566l10.526,23.684h105.263v-47.368H43.618L33.092,172.566z"/>
|
||||
<path fill="#4285F4" d="M12.039-3.75C3.316-3.75-3.75,3.316-3.75,12.039v136.842l23.684,10.526l23.684-10.526V43.618h105.263
|
||||
l10.526-23.684L148.882-3.75H12.039z"/>
|
||||
<path fill="#188038" d="M-3.75,148.882v31.579c0,8.724,7.066,15.789,15.789,15.789h31.579v-47.368H-3.75z"/>
|
||||
<path fill="#FBBC04" d="M148.882,43.618v105.263h47.368V43.618l-23.684-10.526L148.882,43.618z"/>
|
||||
<path fill="#1967D2" d="M196.25,43.618V12.039c0-8.724-7.066-15.789-15.789-15.789h-31.579v47.368H196.25z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,24 @@
|
||||
import { IField, IGlobalVariable } from '@automatisch/types';
|
||||
import { URLSearchParams } from 'url';
|
||||
import authScope from '../common/auth-scope';
|
||||
|
||||
export default async function generateAuthUrl($: IGlobalVariable) {
|
||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
||||
);
|
||||
const redirectUri = oauthRedirectUrlField.value as string;
|
||||
const searchParams = new URLSearchParams({
|
||||
client_id: $.auth.data.clientId as string,
|
||||
redirect_uri: redirectUri,
|
||||
prompt: 'select_account',
|
||||
scope: authScope.join(' '),
|
||||
response_type: 'code',
|
||||
access_type: 'offline',
|
||||
});
|
||||
|
||||
const url = `https://accounts.google.com/o/oauth2/v2/auth?${searchParams.toString()}`;
|
||||
|
||||
await $.auth.set({
|
||||
url,
|
||||
});
|
||||
}
|
48
packages/backend/src/apps/google-calendar/auth/index.ts
Normal file
48
packages/backend/src/apps/google-calendar/auth/index.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import generateAuthUrl from './generate-auth-url';
|
||||
import verifyCredentials from './verify-credentials';
|
||||
import refreshToken from './refresh-token';
|
||||
import isStillVerified from './is-still-verified';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'oAuthRedirectUrl',
|
||||
label: 'OAuth Redirect URL',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: true,
|
||||
value: '{WEB_APP_URL}/app/google-calendar/connections/add',
|
||||
placeholder: null,
|
||||
description:
|
||||
'When asked to input a redirect URL in Google Cloud, enter the URL above.',
|
||||
clickToCopy: true,
|
||||
},
|
||||
{
|
||||
key: 'clientId',
|
||||
label: 'Client ID',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'clientSecret',
|
||||
label: 'Client Secret',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
],
|
||||
|
||||
generateAuthUrl,
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
refreshToken,
|
||||
};
|
@@ -0,0 +1,9 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import getCurrentUser from '../common/get-current-user';
|
||||
|
||||
const isStillVerified = async ($: IGlobalVariable) => {
|
||||
const currentUser = await getCurrentUser($);
|
||||
return !!currentUser.resourceName;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
@@ -0,0 +1,26 @@
|
||||
import { URLSearchParams } from 'node:url';
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import authScope from '../common/auth-scope';
|
||||
|
||||
const refreshToken = async ($: IGlobalVariable) => {
|
||||
const params = new URLSearchParams({
|
||||
client_id: $.auth.data.clientId as string,
|
||||
client_secret: $.auth.data.clientSecret as string,
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: $.auth.data.refreshToken as string,
|
||||
});
|
||||
|
||||
const { data } = await $.http.post(
|
||||
'https://oauth2.googleapis.com/token',
|
||||
params.toString()
|
||||
);
|
||||
|
||||
await $.auth.set({
|
||||
accessToken: data.access_token,
|
||||
expiresIn: data.expires_in,
|
||||
scope: authScope.join(' '),
|
||||
tokenType: data.token_type,
|
||||
});
|
||||
};
|
||||
|
||||
export default refreshToken;
|
@@ -0,0 +1,57 @@
|
||||
import { IField, IGlobalVariable } from '@automatisch/types';
|
||||
import getCurrentUser from '../common/get-current-user';
|
||||
|
||||
type TUser = {
|
||||
displayName: string;
|
||||
metadata: {
|
||||
primary: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
type TEmailAddress = {
|
||||
value: string;
|
||||
metadata: {
|
||||
primary: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
const verifyCredentials = async ($: IGlobalVariable) => {
|
||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
||||
);
|
||||
const redirectUri = oauthRedirectUrlField.value as string;
|
||||
const { data } = await $.http.post(`https://oauth2.googleapis.com/token`, {
|
||||
client_id: $.auth.data.clientId,
|
||||
client_secret: $.auth.data.clientSecret,
|
||||
code: $.auth.data.code,
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri: redirectUri,
|
||||
});
|
||||
|
||||
await $.auth.set({
|
||||
accessToken: data.access_token,
|
||||
tokenType: data.token_type,
|
||||
});
|
||||
|
||||
const currentUser = await getCurrentUser($);
|
||||
|
||||
const { displayName } = currentUser.names.find(
|
||||
(name: TUser) => name.metadata.primary
|
||||
);
|
||||
const { value: email } = currentUser.emailAddresses.find(
|
||||
(emailAddress: TEmailAddress) => emailAddress.metadata.primary
|
||||
);
|
||||
|
||||
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,
|
||||
resourceName: currentUser.resourceName,
|
||||
screenName: `${displayName} - ${email}`,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
@@ -0,0 +1,11 @@
|
||||
import { TBeforeRequest } from '@automatisch/types';
|
||||
|
||||
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
||||
if ($.auth.data?.accessToken) {
|
||||
requestConfig.headers.Authorization = `${$.auth.data.tokenType} ${$.auth.data.accessToken}`;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
@@ -0,0 +1,7 @@
|
||||
const authScope: string[] = [
|
||||
'https://www.googleapis.com/auth/calendar',
|
||||
'https://www.googleapis.com/auth/userinfo.email',
|
||||
'https://www.googleapis.com/auth/userinfo.profile',
|
||||
];
|
||||
|
||||
export default authScope;
|
@@ -0,0 +1,10 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const getCurrentUser = async ($: IGlobalVariable) => {
|
||||
const { data: currentUser } = await $.http.get(
|
||||
'https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses'
|
||||
);
|
||||
return currentUser;
|
||||
};
|
||||
|
||||
export default getCurrentUser;
|
@@ -0,0 +1,3 @@
|
||||
import listCalendars from './list-calendars';
|
||||
|
||||
export default [listCalendars];
|
@@ -0,0 +1,36 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
export default {
|
||||
name: 'List calendars',
|
||||
key: 'listCalendars',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
const drives: {
|
||||
data: IJSONObject[];
|
||||
} = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
const params = {
|
||||
pageToken: undefined as unknown as string,
|
||||
};
|
||||
|
||||
do {
|
||||
const { data } = await $.http.get(`/v3/users/me/calendarList`, {
|
||||
params,
|
||||
});
|
||||
params.pageToken = data.nextPageToken;
|
||||
|
||||
if (data.items) {
|
||||
for (const calendar of data.items) {
|
||||
drives.data.push({
|
||||
value: calendar.id,
|
||||
name: calendar.summary,
|
||||
});
|
||||
}
|
||||
}
|
||||
} while (params.pageToken);
|
||||
|
||||
return drives;
|
||||
},
|
||||
};
|
0
packages/backend/src/apps/google-calendar/index.d.ts
vendored
Normal file
0
packages/backend/src/apps/google-calendar/index.d.ts
vendored
Normal file
20
packages/backend/src/apps/google-calendar/index.ts
Normal file
20
packages/backend/src/apps/google-calendar/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import defineApp from '../../helpers/define-app';
|
||||
import addAuthHeader from './common/add-auth-header';
|
||||
import auth from './auth';
|
||||
import triggers from './triggers';
|
||||
import dynamicData from './dynamic-data';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Google Calendar',
|
||||
key: 'google-calendar',
|
||||
baseUrl: 'https://calendar.google.com',
|
||||
apiBaseUrl: 'https://www.googleapis.com/calendar',
|
||||
iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg',
|
||||
authDocUrl: 'https://automatisch.io/docs/apps/google-calendar/connection',
|
||||
primaryColor: '448AFF',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
dynamicData,
|
||||
});
|
@@ -0,0 +1,4 @@
|
||||
import newCalendar from './new-calendar';
|
||||
import newEvent from './new-event';
|
||||
|
||||
export default [newCalendar, newEvent];
|
@@ -0,0 +1,34 @@
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New calendar',
|
||||
key: 'newCalendar',
|
||||
pollInterval: 15,
|
||||
description: 'Triggers when a new calendar is created.',
|
||||
arguments: [],
|
||||
|
||||
async run($) {
|
||||
const params: Record<string, unknown> = {
|
||||
pageToken: undefined as unknown as string,
|
||||
maxResults: 250,
|
||||
};
|
||||
|
||||
do {
|
||||
const { data } = await $.http.get('/v3/users/me/calendarList', {
|
||||
params,
|
||||
});
|
||||
params.pageToken = data.nextPageToken;
|
||||
|
||||
if (data.items?.length) {
|
||||
for (const calendar of data.items.reverse()) {
|
||||
$.pushTriggerItem({
|
||||
raw: calendar,
|
||||
meta: {
|
||||
internalId: calendar.etag,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
} while (params.pageToken);
|
||||
},
|
||||
});
|
@@ -0,0 +1,55 @@
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New event',
|
||||
key: 'newEvent',
|
||||
pollInterval: 15,
|
||||
description: 'Triggers when a new event is created.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Calendar',
|
||||
key: 'calendarId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: '',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listCalendars',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const calendarId = $.step.parameters.calendarId;
|
||||
|
||||
const params: Record<string, unknown> = {
|
||||
pageToken: undefined as unknown as string,
|
||||
orderBy: 'updated',
|
||||
};
|
||||
|
||||
do {
|
||||
const { data } = await $.http.get(`/v3/calendars/${calendarId}/events`, {
|
||||
params,
|
||||
});
|
||||
params.pageToken = data.nextPageToken;
|
||||
|
||||
if (data.items?.length) {
|
||||
for (const event of data.items.reverse()) {
|
||||
$.pushTriggerItem({
|
||||
raw: event,
|
||||
meta: {
|
||||
internalId: event.etag,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
} while (params.pageToken);
|
||||
},
|
||||
});
|
@@ -0,0 +1,639 @@
|
||||
export const fields = [
|
||||
{
|
||||
label: 'Client Name',
|
||||
key: 'clientName',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Contact First Name',
|
||||
key: 'contactFirstName',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Contact Last Name',
|
||||
key: 'contactLastName',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Contact Email',
|
||||
key: 'contactEmail',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Contact Phone',
|
||||
key: 'contactPhone',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Language Code',
|
||||
key: 'languageCode',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{ value: 1, label: 'English - United States' },
|
||||
{ value: 2, label: 'Italian' },
|
||||
{ value: 3, label: 'German' },
|
||||
{ value: 4, label: 'French' },
|
||||
{ value: 5, label: 'Portuguese - Brazilian' },
|
||||
{ value: 6, label: 'Dutch' },
|
||||
{ value: 7, label: 'Spanish' },
|
||||
{ value: 8, label: 'Norwegian' },
|
||||
{ value: 9, label: 'Danish' },
|
||||
{ value: 10, label: 'Japanese' },
|
||||
{ value: 11, label: 'Swedish' },
|
||||
{ value: 12, label: 'Spanish - Spain' },
|
||||
{ value: 13, label: 'French - Canada' },
|
||||
{ value: 14, label: 'Lithuanian' },
|
||||
{ value: 15, label: 'Polish' },
|
||||
{ value: 16, label: 'Czech' },
|
||||
{ value: 17, label: 'Croatian' },
|
||||
{ value: 18, label: 'Albanian' },
|
||||
{ value: 19, label: 'Greek' },
|
||||
{ value: 20, label: 'English - United Kingdom' },
|
||||
{ value: 21, label: 'Portuguese - Portugal' },
|
||||
{ value: 22, label: 'Slovenian' },
|
||||
{ value: 23, label: 'Finnish' },
|
||||
{ value: 24, label: 'Romanian' },
|
||||
{ value: 25, label: 'Turkish - Turkey' },
|
||||
{ value: 26, label: 'Thai' },
|
||||
{ value: 27, label: 'Macedonian' },
|
||||
{ value: 28, label: 'Chinese - Taiwan' },
|
||||
{ value: 29, label: 'Russian (Russia)' },
|
||||
{ value: 30, label: 'Arabic' },
|
||||
{ value: 31, label: 'Persian' },
|
||||
{ value: 32, label: 'Latvian' },
|
||||
{ value: 33, label: 'Serbian' },
|
||||
{ value: 34, label: 'Slovak' },
|
||||
{ value: 35, label: 'Estonian' },
|
||||
{ value: 36, label: 'Bulgarian' },
|
||||
{ value: 37, label: 'Hebrew' },
|
||||
{ value: 38, label: 'Khmer' },
|
||||
{ value: 39, label: 'Hungarian' },
|
||||
{ value: 40, label: 'French - Swiss' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Currency Code',
|
||||
key: 'currencyCode',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{ value: 1, label: 'US Dollar' },
|
||||
{ value: 2, label: 'British Pound' },
|
||||
{ value: 3, label: 'Euro' },
|
||||
{ value: 4, label: 'South African Rand' },
|
||||
{ value: 5, label: 'Danish Krone' },
|
||||
{ value: 6, label: 'Israeli Shekel' },
|
||||
{ value: 7, label: 'Swedish Krona' },
|
||||
{ value: 8, label: 'Kenyan Shilling' },
|
||||
{ value: 9, label: 'Canadian Dollar' },
|
||||
{ value: 10, label: 'Philippine Peso' },
|
||||
{ value: 11, label: 'Indian Rupee' },
|
||||
{ value: 12, label: 'Australian Dollar' },
|
||||
{ value: 13, label: 'Singapore Dollar' },
|
||||
{ value: 14, label: 'Norske Kroner' },
|
||||
{ value: 15, label: 'New Zealand Dollar' },
|
||||
{ value: 16, label: 'Vietnamese Dong' },
|
||||
{ value: 17, label: 'Swiss Franc' },
|
||||
{ value: 18, label: 'Guatemalan Quetzal' },
|
||||
{ value: 19, label: 'Malaysian Ringgit' },
|
||||
{ value: 20, label: 'Brazilian Real' },
|
||||
{ value: 21, label: 'Thai Baht' },
|
||||
{ value: 22, label: 'Nigerian Naira' },
|
||||
{ value: 23, label: 'Argentine Peso' },
|
||||
{ value: 24, label: 'Bangladeshi Taka' },
|
||||
{ value: 25, label: 'United Arab Emirates Dirham' },
|
||||
{ value: 26, label: 'Hong Kong Dollar' },
|
||||
{ value: 27, label: 'Indonesian Rupiah' },
|
||||
{ value: 28, label: 'Mexican Peso' },
|
||||
{ value: 29, label: 'Egyptian Pound' },
|
||||
{ value: 30, label: 'Colombian Peso' },
|
||||
{ value: 31, label: 'West African Franc' },
|
||||
{ value: 32, label: 'Chinese Renminbi' },
|
||||
{ value: 33, label: 'Rwandan Franc' },
|
||||
{ value: 34, label: 'Tanzanian Shilling' },
|
||||
{ value: 35, label: 'Netherlands Antillean Guilder' },
|
||||
{ value: 36, label: 'Trinidad and Tobago Dollar' },
|
||||
{ value: 37, label: 'East Caribbean Dollar' },
|
||||
{ value: 38, label: 'Ghanaian Cedi' },
|
||||
{ value: 39, label: 'Bulgarian Lev' },
|
||||
{ value: 40, label: 'Aruban Florin' },
|
||||
{ value: 41, label: 'Turkish Lira' },
|
||||
{ value: 42, label: 'Romanian New Leu' },
|
||||
{ value: 43, label: 'Croatian Kuna' },
|
||||
{ value: 44, label: 'Saudi Riyal' },
|
||||
{ value: 45, label: 'Japanese Yen' },
|
||||
{ value: 46, label: 'Maldivian Rufiyaa' },
|
||||
{ value: 47, label: 'Costa Rican Colón' },
|
||||
{ value: 48, label: 'Pakistani Rupee' },
|
||||
{ value: 49, label: 'Polish Zloty' },
|
||||
{ value: 50, label: 'Sri Lankan Rupee' },
|
||||
{ value: 51, label: 'Czech Koruna' },
|
||||
{ value: 52, label: 'Uruguayan Peso' },
|
||||
{ value: 53, label: 'Namibian Dollar' },
|
||||
{ value: 54, label: 'Tunisian Dinar' },
|
||||
{ value: 55, label: 'Russian Ruble' },
|
||||
{ value: 56, label: 'Mozambican Metical' },
|
||||
{ value: 57, label: 'Omani Rial' },
|
||||
{ value: 58, label: 'Ukrainian Hryvnia' },
|
||||
{ value: 59, label: 'Macanese Pataca' },
|
||||
{ value: 60, label: 'Taiwan New Dollar' },
|
||||
{ value: 61, label: 'Dominican Peso' },
|
||||
{ value: 62, label: 'Chilean Peso' },
|
||||
{ value: 63, label: 'Icelandic Króna' },
|
||||
{ value: 64, label: 'Papua New Guinean Kina' },
|
||||
{ value: 65, label: 'Jordanian Dinar' },
|
||||
{ value: 66, label: 'Myanmar Kyat' },
|
||||
{ value: 67, label: 'Peruvian Sol' },
|
||||
{ value: 68, label: 'Botswana Pula' },
|
||||
{ value: 69, label: 'Hungarian Forint' },
|
||||
{ value: 70, label: 'Ugandan Shilling' },
|
||||
{ value: 71, label: 'Barbadian Dollar' },
|
||||
{ value: 72, label: 'Brunei Dollar' },
|
||||
{ value: 73, label: 'Georgian Lari' },
|
||||
{ value: 74, label: 'Qatari Riyal' },
|
||||
{ value: 75, label: 'Honduran Lempira' },
|
||||
{ value: 76, label: 'Surinamese Dollar' },
|
||||
{ value: 77, label: 'Bahraini Dinar' },
|
||||
{ value: 78, label: 'Venezuelan Bolivars' },
|
||||
{ value: 79, label: 'South Korean Won' },
|
||||
{ value: 80, label: 'Moroccan Dirham' },
|
||||
{ value: 81, label: 'Jamaican Dollar' },
|
||||
{ value: 82, label: 'Angolan Kwanza' },
|
||||
{ value: 83, label: 'Haitian Gourde' },
|
||||
{ value: 84, label: 'Zambian Kwacha' },
|
||||
{ value: 85, label: 'Nepalese Rupee' },
|
||||
{ value: 86, label: 'CFP Franc' },
|
||||
{ value: 87, label: 'Mauritian Rupee' },
|
||||
{ value: 88, label: 'Cape Verdean Escudo' },
|
||||
{ value: 89, label: 'Kuwaiti Dinar' },
|
||||
{ value: 90, label: 'Algerian Dinar' },
|
||||
{ value: 91, label: 'Macedonian Denar' },
|
||||
{ value: 92, label: 'Fijian Dollar' },
|
||||
{ value: 93, label: 'Bolivian Boliviano' },
|
||||
{ value: 94, label: 'Albanian Lek' },
|
||||
{ value: 95, label: 'Serbian Dinar' },
|
||||
{ value: 96, label: 'Lebanese Pound' },
|
||||
{ value: 97, label: 'Armenian Dram' },
|
||||
{ value: 98, label: 'Azerbaijan Manat' },
|
||||
{ value: 99, label: 'Bosnia and Herzegovina Convertible Mark' },
|
||||
{ value: 100, label: 'Belarusian Ruble' },
|
||||
{ value: 101, label: 'Gibraltar Pound' },
|
||||
{ value: 102, label: 'Moldovan Leu' },
|
||||
{ value: 103, label: 'Kazakhstani Tenge' },
|
||||
{ value: 104, label: 'Ethiopian Birr' },
|
||||
{ value: 105, label: 'Gambia Dalasi' },
|
||||
{ value: 106, label: 'Paraguayan Guarani' },
|
||||
{ value: 107, label: 'Malawi Kwacha' },
|
||||
{ value: 108, label: 'Zimbabwean Dollar' },
|
||||
{ value: 109, label: 'Cambodian Riel' },
|
||||
{ value: 110, label: 'Vanuatu Vatu' },
|
||||
{ value: 111, label: 'Cuban Peso' },
|
||||
{ value: 112, label: 'Cayman Island Dollar' },
|
||||
{ value: 113, label: 'Swazi lilangeni' },
|
||||
{ value: 114, label: 'BZ Dollar' },
|
||||
{ value: 115, label: 'Libyan Dinar' },
|
||||
{ value: 116, label: 'Silver Troy Ounce' },
|
||||
{ value: 117, label: 'Gold Troy Ounce' },
|
||||
{ value: 118, label: 'Nicaraguan Córdoba' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Id Number',
|
||||
key: 'idNumber',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Vat Number',
|
||||
key: 'vatNumber',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Street Address',
|
||||
key: 'streetAddress',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Apt/Suite',
|
||||
key: 'aptSuite',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'City',
|
||||
key: 'city',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'State/Province',
|
||||
key: 'stateProvince',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Postal Code',
|
||||
key: 'postalCode',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Country Code',
|
||||
key: 'countryCode',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{ value: 4, label: 'Afghanistan' },
|
||||
{ value: 8, label: 'Albania' },
|
||||
{ value: 12, label: 'Algeria' },
|
||||
{ value: 16, label: 'American Samoa' },
|
||||
{ value: 20, label: 'Andorra' },
|
||||
{ value: 24, label: 'Angola' },
|
||||
{ value: 660, label: 'Anguilla' },
|
||||
{ value: 10, label: 'Antarctica' },
|
||||
{ value: 28, label: 'Antigua and Barbuda' },
|
||||
{ value: 32, label: 'Argentina' },
|
||||
{ value: 51, label: 'Armenia' },
|
||||
{ value: 533, label: 'Aruba' },
|
||||
{ value: 36, label: 'Australia' },
|
||||
{ value: 40, label: 'Austria' },
|
||||
{ value: 31, label: 'Azerbaijan' },
|
||||
{ value: 44, label: 'Bahamas' },
|
||||
{ value: 48, label: 'Bahrain' },
|
||||
{ value: 50, label: 'Bangladesh' },
|
||||
{ value: 52, label: 'Barbados' },
|
||||
{ value: 112, label: 'Belarus' },
|
||||
{ value: 56, label: 'Belgium' },
|
||||
{ value: 84, label: 'Belize' },
|
||||
{ value: 204, label: 'Benin' },
|
||||
{ value: 60, label: 'Bermuda' },
|
||||
{ value: 64, label: 'Bhutan' },
|
||||
{ value: 68, label: 'Bolivia, Plurinational State of' },
|
||||
{ value: 535, label: 'Bonaire, Sint Eustatius and Saba' },
|
||||
{ value: 70, label: 'Bosnia and Herzegovina' },
|
||||
{ value: 72, label: 'Botswana' },
|
||||
{ value: 74, label: 'Bouvet Island' },
|
||||
{ value: 76, label: 'Brazil' },
|
||||
{ value: 86, label: 'British Indian Ocean Territory' },
|
||||
{ value: 96, label: 'Brunei Darussalam' },
|
||||
{ value: 100, label: 'Bulgaria' },
|
||||
{ value: 854, label: 'Burkina Faso' },
|
||||
{ value: 108, label: 'Burundi' },
|
||||
{ value: 116, label: 'Cambodia' },
|
||||
{ value: 120, label: 'Cameroon' },
|
||||
{ value: 124, label: 'Canada' },
|
||||
{ value: 132, label: 'Cape Verde' },
|
||||
{ value: 136, label: 'Cayman Islands' },
|
||||
{ value: 140, label: 'Central African Republic' },
|
||||
{ value: 148, label: 'Chad' },
|
||||
{ value: 152, label: 'Chile' },
|
||||
{ value: 156, label: 'China' },
|
||||
{ value: 162, label: 'Christmas Island' },
|
||||
{ value: 166, label: 'Cocos (Keeling) Islands' },
|
||||
{ value: 170, label: 'Colombia' },
|
||||
{ value: 174, label: 'Comoros' },
|
||||
{ value: 178, label: 'Congo' },
|
||||
{ value: 180, label: 'Congo, the Democratic Republic of the' },
|
||||
{ value: 184, label: 'Cook Islands' },
|
||||
{ value: 188, label: 'Costa Rica' },
|
||||
{ value: 191, label: 'Croatia' },
|
||||
{ value: 192, label: 'Cuba' },
|
||||
{ value: 531, label: 'Curaçao' },
|
||||
{ value: 196, label: 'Cyprus' },
|
||||
{ value: 203, label: 'Czech Republic' },
|
||||
{ value: 384, label: "Côte d'Ivoire" },
|
||||
{ value: 208, label: 'Denmark' },
|
||||
{ value: 262, label: 'Djibouti' },
|
||||
{ value: 212, label: 'Dominica' },
|
||||
{ value: 214, label: 'Dominican Republic' },
|
||||
{ value: 218, label: 'Ecuador' },
|
||||
{ value: 818, label: 'Egypt' },
|
||||
{ value: 222, label: 'El Salvador' },
|
||||
{ value: 226, label: 'Equatorial Guinea' },
|
||||
{ value: 232, label: 'Eritrea' },
|
||||
{ value: 233, label: 'Estonia' },
|
||||
{ value: 231, label: 'Ethiopia' },
|
||||
{ value: 238, label: 'Falkland Islands (Malvinas)' },
|
||||
{ value: 234, label: 'Faroe Islands' },
|
||||
{ value: 242, label: 'Fiji' },
|
||||
{ value: 246, label: 'Finland' },
|
||||
{ value: 250, label: 'France' },
|
||||
{ value: 254, label: 'French Guiana' },
|
||||
{ value: 258, label: 'French Polynesia' },
|
||||
{ value: 260, label: 'French Southern Territories' },
|
||||
{ value: 266, label: 'Gabon' },
|
||||
{ value: 270, label: 'Gambia' },
|
||||
{ value: 268, label: 'Georgia' },
|
||||
{ value: 276, label: 'Germany' },
|
||||
{ value: 288, label: 'Ghana' },
|
||||
{ value: 292, label: 'Gibraltar' },
|
||||
{ value: 300, label: 'Greece' },
|
||||
{ value: 304, label: 'Greenland' },
|
||||
{ value: 308, label: 'Grenada' },
|
||||
{ value: 312, label: 'Guadeloupe' },
|
||||
{ value: 316, label: 'Guam' },
|
||||
{ value: 320, label: 'Guatemala' },
|
||||
{ value: 831, label: 'Guernsey' },
|
||||
{ value: 324, label: 'Guinea' },
|
||||
{ value: 624, label: 'Guinea-Bissau' },
|
||||
{ value: 328, label: 'Guyana' },
|
||||
{ value: 332, label: 'Haiti' },
|
||||
{ value: 334, label: 'Heard Island and McDonald Islands' },
|
||||
{ value: 336, label: 'Holy See (Vatican City State)' },
|
||||
{ value: 340, label: 'Honduras' },
|
||||
{ value: 344, label: 'Hong Kong' },
|
||||
{ value: 348, label: 'Hungary' },
|
||||
{ value: 352, label: 'Iceland' },
|
||||
{ value: 356, label: 'India' },
|
||||
{ value: 360, label: 'Indonesia' },
|
||||
{ value: 364, label: 'Iran, Islamic Republic of' },
|
||||
{ value: 368, label: 'Iraq' },
|
||||
{ value: 372, label: 'Ireland' },
|
||||
{ value: 833, label: 'Isle of Man' },
|
||||
{ value: 376, label: 'Israel' },
|
||||
{ value: 380, label: 'Italy' },
|
||||
{ value: 388, label: 'Jamaica' },
|
||||
{ value: 392, label: 'Japan' },
|
||||
{ value: 832, label: 'Jersey' },
|
||||
{ value: 400, label: 'Jordan' },
|
||||
{ value: 398, label: 'Kazakhstan' },
|
||||
{ value: 404, label: 'Kenya' },
|
||||
{ value: 296, label: 'Kiribati' },
|
||||
{ value: 408, label: "Korea, Democratic People's Republic of" },
|
||||
{ value: 410, label: 'Korea, Republic of' },
|
||||
{ value: 414, label: 'Kuwait' },
|
||||
{ value: 417, label: 'Kyrgyzstan' },
|
||||
{ value: 418, label: "Lao People's Democratic Republic" },
|
||||
{ value: 428, label: 'Latvia' },
|
||||
{ value: 422, label: 'Lebanon' },
|
||||
{ value: 426, label: 'Lesotho' },
|
||||
{ value: 430, label: 'Liberia' },
|
||||
{ value: 434, label: 'Libya' },
|
||||
{ value: 438, label: 'Liechtenstein' },
|
||||
{ value: 440, label: 'Lithuania' },
|
||||
{ value: 442, label: 'Luxembourg' },
|
||||
{ value: 446, label: 'Macao' },
|
||||
{ value: 807, label: 'Macedonia, the former Yugoslav Republic of' },
|
||||
{ value: 450, label: 'Madagascar' },
|
||||
{ value: 454, label: 'Malawi' },
|
||||
{ value: 458, label: 'Malaysia' },
|
||||
{ value: 462, label: 'Maldives' },
|
||||
{ value: 466, label: 'Mali' },
|
||||
{ value: 470, label: 'Malta' },
|
||||
{ value: 584, label: 'Marshall Islands' },
|
||||
{ value: 474, label: 'Martinique' },
|
||||
{ value: 478, label: 'Mauritania' },
|
||||
{ value: 480, label: 'Mauritius' },
|
||||
{ value: 175, label: 'Mayotte' },
|
||||
{ value: 484, label: 'Mexico' },
|
||||
{ value: 583, label: 'Micronesia, Federated States of' },
|
||||
{ value: 498, label: 'Moldova, Republic of' },
|
||||
{ value: 492, label: 'Monaco' },
|
||||
{ value: 496, label: 'Mongolia' },
|
||||
{ value: 499, label: 'Montenegro' },
|
||||
{ value: 500, label: 'Montserrat' },
|
||||
{ value: 504, label: 'Morocco' },
|
||||
{ value: 508, label: 'Mozambique' },
|
||||
{ value: 104, label: 'Myanmar' },
|
||||
{ value: 516, label: 'Namibia' },
|
||||
{ value: 520, label: 'Nauru' },
|
||||
{ value: 524, label: 'Nepal' },
|
||||
{ value: 528, label: 'Netherlands' },
|
||||
{ value: 540, label: 'New Caledonia' },
|
||||
{ value: 554, label: 'New Zealand' },
|
||||
{ value: 558, label: 'Nicaragua' },
|
||||
{ value: 562, label: 'Niger' },
|
||||
{ value: 566, label: 'Nigeria' },
|
||||
{ value: 570, label: 'Niue' },
|
||||
{ value: 574, label: 'Norfolk Island' },
|
||||
{ value: 580, label: 'Northern Mariana Islands' },
|
||||
{ value: 578, label: 'Norway' },
|
||||
{ value: 512, label: 'Oman' },
|
||||
{ value: 586, label: 'Pakistan' },
|
||||
{ value: 585, label: 'Palau' },
|
||||
{ value: 275, label: 'Palestine' },
|
||||
{ value: 591, label: 'Panama' },
|
||||
{ value: 598, label: 'Papua New Guinea' },
|
||||
{ value: 600, label: 'Paraguay' },
|
||||
{ value: 604, label: 'Peru' },
|
||||
{ value: 608, label: 'Philippines' },
|
||||
{ value: 612, label: 'Pitcairn' },
|
||||
{ value: 616, label: 'Poland' },
|
||||
{ value: 620, label: 'Portugal' },
|
||||
{ value: 630, label: 'Puerto Rico' },
|
||||
{ value: 634, label: 'Qatar' },
|
||||
{ value: 642, label: 'Romania' },
|
||||
{ value: 643, label: 'Russian Federation' },
|
||||
{ value: 646, label: 'Rwanda' },
|
||||
{ value: 638, label: 'Réunion' },
|
||||
{ value: 652, label: 'Saint Barthélemy' },
|
||||
{ value: 654, label: 'Saint Helena, Ascension and Tristan da Cunha' },
|
||||
{ value: 659, label: 'Saint Kitts and Nevis' },
|
||||
{ value: 662, label: 'Saint Lucia' },
|
||||
{ value: 663, label: 'Saint Martin (French part)' },
|
||||
{ value: 666, label: 'Saint Pierre and Miquelon' },
|
||||
{ value: 670, label: 'Saint Vincent and the Grenadines' },
|
||||
{ value: 882, label: 'Samoa' },
|
||||
{ value: 674, label: 'San Marino' },
|
||||
{ value: 678, label: 'Sao Tome and Principe' },
|
||||
{ value: 682, label: 'Saudi Arabia' },
|
||||
{ value: 686, label: 'Senegal' },
|
||||
{ value: 688, label: 'Serbia' },
|
||||
{ value: 690, label: 'Seychelles' },
|
||||
{ value: 694, label: 'Sierra Leone' },
|
||||
{ value: 702, label: 'Singapore' },
|
||||
{ value: 534, label: 'Sint Maarten (Dutch part)' },
|
||||
{ value: 703, label: 'Slovakia' },
|
||||
{ value: 705, label: 'Slovenia' },
|
||||
{ value: 90, label: 'Solomon Islands' },
|
||||
{ value: 706, label: 'Somalia' },
|
||||
{ value: 710, label: 'South Africa' },
|
||||
{ value: 239, label: 'South Georgia and the South Sandwich Islands' },
|
||||
{ value: 728, label: 'South Sudan' },
|
||||
{ value: 724, label: 'Spain' },
|
||||
{ value: 144, label: 'Sri Lanka' },
|
||||
{ value: 729, label: 'Sudan' },
|
||||
{ value: 740, label: 'Suriname' },
|
||||
{ value: 744, label: 'Svalbard and Jan Mayen' },
|
||||
{ value: 748, label: 'Swaziland' },
|
||||
{ value: 752, label: 'Sweden' },
|
||||
{ value: 756, label: 'Switzerland' },
|
||||
{ value: 760, label: 'Syrian Arab Republic' },
|
||||
{ value: 158, label: 'Taiwan, Province of China' },
|
||||
{ value: 762, label: 'Tajikistan' },
|
||||
{ value: 834, label: 'Tanzania, United Republic of' },
|
||||
{ value: 764, label: 'Thailand' },
|
||||
{ value: 626, label: 'Timor-Leste' },
|
||||
{ value: 768, label: 'Togo' },
|
||||
{ value: 772, label: 'Tokelau' },
|
||||
{ value: 776, label: 'Tonga' },
|
||||
{ value: 780, label: 'Trinidad and Tobago' },
|
||||
{ value: 788, label: 'Tunisia' },
|
||||
{ value: 792, label: 'Turkey' },
|
||||
{ value: 795, label: 'Turkmenistan' },
|
||||
{ value: 796, label: 'Turks and Caicos Islands' },
|
||||
{ value: 798, label: 'Tuvalu' },
|
||||
{ value: 800, label: 'Uganda' },
|
||||
{ value: 804, label: 'Ukraine' },
|
||||
{ value: 784, label: 'United Arab Emirates' },
|
||||
{ value: 826, label: 'United Kingdom' },
|
||||
{ value: 840, label: 'United States' },
|
||||
{ value: 581, label: 'United States Minor Outlying Islands' },
|
||||
{ value: 858, label: 'Uruguay' },
|
||||
{ value: 860, label: 'Uzbekistan' },
|
||||
{ value: 548, label: 'Vanuatu' },
|
||||
{ value: 862, label: 'Venezuela, Bolivarian Republic of' },
|
||||
{ value: 704, label: 'Viet Nam' },
|
||||
{ value: 92, label: 'Virgin Islands, British' },
|
||||
{ value: 850, label: 'Virgin Islands, U.S.' },
|
||||
{ value: 876, label: 'Wallis and Futuna' },
|
||||
{ value: 732, label: 'Western Sahara' },
|
||||
{ value: 887, label: 'Yemen' },
|
||||
{ value: 894, label: 'Zambia' },
|
||||
{ value: 716, label: 'Zimbabwe' },
|
||||
{ value: 248, label: 'Åland Islands' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Shipping Street Address',
|
||||
key: 'shippingStreetAddress',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Shipping Apt/Suite',
|
||||
key: 'shippingAptSuite',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Shipping City',
|
||||
key: 'shippingCity',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Shipping State/Province',
|
||||
key: 'shippingStateProvince',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Shipping Postal Code',
|
||||
key: 'shippingPostalCode',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Shipping Country Code',
|
||||
key: 'shippingCountryCode',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Private Notes',
|
||||
key: 'privateNotes',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Public Notes',
|
||||
key: 'publicNotes',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Website',
|
||||
key: 'website',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Value 1',
|
||||
key: 'customValue1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Value 2',
|
||||
key: 'customValue2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Value 3',
|
||||
key: 'customValue3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Value 4',
|
||||
key: 'customValue4',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
];
|
@@ -0,0 +1,84 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
import { fields } from './fields';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create client',
|
||||
key: 'createClient',
|
||||
description: 'Creates a new client.',
|
||||
arguments: fields,
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
clientName,
|
||||
contactFirstName,
|
||||
contactLastName,
|
||||
contactEmail,
|
||||
contactPhone,
|
||||
languageCode,
|
||||
currencyCode,
|
||||
idNumber,
|
||||
vatNumber,
|
||||
streetAddress,
|
||||
aptSuite,
|
||||
city,
|
||||
stateProvince,
|
||||
postalCode,
|
||||
countryCode,
|
||||
shippingStreetAddress,
|
||||
shippingAptSuite,
|
||||
shippingCity,
|
||||
shippingStateProvince,
|
||||
shippingPostalCode,
|
||||
shippingCountryCode,
|
||||
privateNotes,
|
||||
publicNotes,
|
||||
website,
|
||||
customValue1,
|
||||
customValue2,
|
||||
customValue3,
|
||||
customValue4,
|
||||
} = $.step.parameters;
|
||||
|
||||
const bodyFields = {
|
||||
name: clientName,
|
||||
contacts: {
|
||||
first_name: contactFirstName,
|
||||
last_name: contactLastName,
|
||||
email: contactEmail,
|
||||
phone: contactPhone,
|
||||
},
|
||||
settings: {
|
||||
language_id: languageCode,
|
||||
currency_id: currencyCode,
|
||||
},
|
||||
id_number: idNumber,
|
||||
vat_number: vatNumber,
|
||||
address1: streetAddress,
|
||||
address2: aptSuite,
|
||||
city: city,
|
||||
state: stateProvince,
|
||||
postal_code: postalCode,
|
||||
country_id: countryCode,
|
||||
shipping_address1: shippingStreetAddress,
|
||||
shipping_address2: shippingAptSuite,
|
||||
shipping_city: shippingCity,
|
||||
shipping_state: shippingStateProvince,
|
||||
shipping_postal_code: shippingPostalCode,
|
||||
shipping_country_id: shippingCountryCode,
|
||||
private_notes: privateNotes,
|
||||
public_notes: publicNotes,
|
||||
website: website,
|
||||
custom_value1: customValue1,
|
||||
custom_value2: customValue2,
|
||||
custom_value3: customValue3,
|
||||
custom_value4: customValue4,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(bodyFields);
|
||||
|
||||
const response = await $.http.post('/v1/clients', body);
|
||||
|
||||
$.setActionItem({ raw: response.data.data });
|
||||
},
|
||||
});
|
@@ -0,0 +1,407 @@
|
||||
export const fields = [
|
||||
{
|
||||
label: 'Client ID',
|
||||
key: 'clientId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The ID of the client, not the name or email address.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listClients',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Send Email',
|
||||
key: 'sendEmail',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'False', value: 'false' },
|
||||
{ label: 'True', value: 'true' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Mark Sent',
|
||||
key: 'markSent',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: 'Setting this to true creates the invoice as sent.',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'False', value: 'false' },
|
||||
{ label: 'True', value: 'true' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Paid',
|
||||
key: 'paid',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: 'Setting this to true creates the invoice as paid.',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'False', value: 'false' },
|
||||
{ label: 'True', value: 'true' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Amount Paid',
|
||||
key: 'amountPaid',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description:
|
||||
'If this value is greater than zero a payment will be created along with the invoice.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Number',
|
||||
key: 'number',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description:
|
||||
'The invoice number - is a unique alpha numeric number per invoice per company',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Discount',
|
||||
key: 'discount',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'PO Number',
|
||||
key: 'poNumber',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'The purchase order associated with this invoice',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Date',
|
||||
key: 'date',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Due Date',
|
||||
key: 'dueDate',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Rate 1',
|
||||
key: 'taxRate1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Name 1',
|
||||
key: 'taxName1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Rate 2',
|
||||
key: 'taxRate2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Name 2',
|
||||
key: 'taxName2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Rate 3',
|
||||
key: 'taxRate3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Name 3',
|
||||
key: 'taxName3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Field 1',
|
||||
key: 'customField1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Field 2',
|
||||
key: 'customField2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Field 3',
|
||||
key: 'customField3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Field 4',
|
||||
key: 'customField4',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Surcharge 1',
|
||||
key: 'customSurcharge1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Surcharge 2',
|
||||
key: 'customSurcharge2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Surcharge 3',
|
||||
key: 'customSurcharge3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Surcharge 4',
|
||||
key: 'customSurcharge4',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Is Amount Discount',
|
||||
key: 'isAmountDiscount',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'By default the discount is applied as a percentage, enabling this applies the discount as a fixed amount.',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'False', value: 'false' },
|
||||
{ label: 'True', value: 'true' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Partial/Deposit',
|
||||
key: 'partialDeposit',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Partial Due Date',
|
||||
key: 'partialDueDate',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Cost',
|
||||
key: 'lineItemCost',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Quatity',
|
||||
key: 'lineItemQuantity',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Product',
|
||||
key: 'lineItemProduct',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Discount',
|
||||
key: 'lineItemDiscount',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Description',
|
||||
key: 'lineItemDescription',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Tax Rate 1',
|
||||
key: 'lineItemTaxRate1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Tax Name 1',
|
||||
key: 'lineItemTaxName1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Tax Rate 2',
|
||||
key: 'lineItemTaxRate2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Tax Name 2',
|
||||
key: 'lineItemTaxName2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Tax Rate 3',
|
||||
key: 'lineItemTaxRate3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Tax Name 3',
|
||||
key: 'lineItemTaxName3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Custom Field 1',
|
||||
key: 'lineItemCustomField1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Custom Field 2',
|
||||
key: 'lineItemCustomField2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Custom Field 3',
|
||||
key: 'lineItemCustomField3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Custom Field 4',
|
||||
key: 'lineItemCustomField4',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Line Item Product Cost',
|
||||
key: 'lineItemProductCost',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Public Notes',
|
||||
key: 'publicNotes',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Private Notes',
|
||||
key: 'privateNotes',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Terms',
|
||||
key: 'terms',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Footer',
|
||||
key: 'footer',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
];
|
@@ -0,0 +1,127 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
import { fields } from './fields';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create invoice',
|
||||
key: 'createInvoice',
|
||||
description: 'Creates a new invoice.',
|
||||
arguments: fields,
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
clientId,
|
||||
sendEmail,
|
||||
markSent,
|
||||
paid,
|
||||
amountPaid,
|
||||
number,
|
||||
discount,
|
||||
poNumber,
|
||||
date,
|
||||
dueDate,
|
||||
taxRate1,
|
||||
taxName1,
|
||||
taxRate2,
|
||||
taxName2,
|
||||
taxRate3,
|
||||
taxName3,
|
||||
customField1,
|
||||
customField2,
|
||||
customField3,
|
||||
customField4,
|
||||
customSurcharge1,
|
||||
customSurcharge2,
|
||||
customSurcharge3,
|
||||
customSurcharge4,
|
||||
isAmountDiscount,
|
||||
partialDeposit,
|
||||
partialDueDate,
|
||||
lineItemCost,
|
||||
lineItemQuantity,
|
||||
lineItemProduct,
|
||||
lineItemDiscount,
|
||||
lineItemDescription,
|
||||
lineItemTaxRate1,
|
||||
lineItemTaxName1,
|
||||
lineItemTaxRate2,
|
||||
lineItemTaxName2,
|
||||
lineItemTaxRate3,
|
||||
lineItemTaxName3,
|
||||
lineItemCustomField1,
|
||||
lineItemCustomField2,
|
||||
lineItemCustomField3,
|
||||
lineItemCustomField4,
|
||||
lineItemProductCost,
|
||||
publicNotes,
|
||||
privateNotes,
|
||||
terms,
|
||||
footer,
|
||||
} = $.step.parameters;
|
||||
|
||||
const paramFields = {
|
||||
send_email: sendEmail,
|
||||
mark_sent: markSent,
|
||||
paid: paid,
|
||||
amount_paid: amountPaid,
|
||||
};
|
||||
|
||||
const params = filterProvidedFields(paramFields);
|
||||
|
||||
const bodyFields = {
|
||||
client_id: clientId,
|
||||
number: number,
|
||||
discount: discount,
|
||||
po_number: poNumber,
|
||||
date: date,
|
||||
due_date: dueDate,
|
||||
tax_rate1: taxRate1,
|
||||
tax_name1: taxName1,
|
||||
tax_rate2: taxRate2,
|
||||
tax_name2: taxName2,
|
||||
tax_rate3: taxRate3,
|
||||
tax_name3: taxName3,
|
||||
custom_value1: customField1,
|
||||
custom_value2: customField2,
|
||||
custom_value3: customField3,
|
||||
custom_value4: customField4,
|
||||
custom_surcharge1: customSurcharge1,
|
||||
custom_surcharge2: customSurcharge2,
|
||||
custom_surcharge3: customSurcharge3,
|
||||
custom_surcharge4: customSurcharge4,
|
||||
is_amount_discount: Boolean(isAmountDiscount),
|
||||
partial: partialDeposit,
|
||||
partial_due_date: partialDueDate,
|
||||
line_items: [
|
||||
{
|
||||
cost: lineItemCost,
|
||||
quantity: lineItemQuantity,
|
||||
product_key: lineItemProduct,
|
||||
discount: lineItemDiscount,
|
||||
notes: lineItemDescription,
|
||||
tax_rate1: lineItemTaxRate1,
|
||||
tax_name1: lineItemTaxName1,
|
||||
tax_rate2: lineItemTaxRate2,
|
||||
tax_name2: lineItemTaxName2,
|
||||
tax_rate3: lineItemTaxRate3,
|
||||
tax_name3: lineItemTaxName3,
|
||||
custom_value1: lineItemCustomField1,
|
||||
custom_value2: lineItemCustomField2,
|
||||
custom_value3: lineItemCustomField3,
|
||||
custom_value4: lineItemCustomField4,
|
||||
product_cost: lineItemProductCost,
|
||||
},
|
||||
],
|
||||
public_notes: publicNotes,
|
||||
private_notes: privateNotes,
|
||||
terms: terms,
|
||||
footer: footer,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(bodyFields);
|
||||
|
||||
const response = await $.http.post('/v1/invoices', body, { params });
|
||||
|
||||
$.setActionItem({ raw: response.data.data });
|
||||
},
|
||||
});
|
@@ -0,0 +1,111 @@
|
||||
export const fields = [
|
||||
{
|
||||
label: 'Client ID',
|
||||
key: 'clientId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The ID of the client, not the name or email address.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listClients',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Payment Date',
|
||||
key: 'paymentDate',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Invoice',
|
||||
key: 'invoiceId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listInvoices',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Invoice Amount',
|
||||
key: 'invoiceAmount',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Payment Type',
|
||||
key: 'paymentType',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Bank Transfer', value: '1' },
|
||||
{ label: 'Cash', value: '2' },
|
||||
{ label: 'Debit', value: '3' },
|
||||
{ label: 'ACH', value: '4' },
|
||||
{ label: 'Visa Card', value: '5' },
|
||||
{ label: 'MasterCard', value: '6' },
|
||||
{ label: 'American Express', value: '7' },
|
||||
{ label: 'Discover Card', value: '8' },
|
||||
{ label: 'Diners Card', value: '9' },
|
||||
{ label: 'EuroCard', value: '10' },
|
||||
{ label: 'Nova', value: '11' },
|
||||
{ label: 'Credit Card Other', value: '12' },
|
||||
{ label: 'PayPal', value: '13' },
|
||||
{ label: 'Google Wallet', value: '14' },
|
||||
{ label: 'Check', value: '15' },
|
||||
{ label: 'Carte Blanche', value: '16' },
|
||||
{ label: 'UnionPay', value: '17' },
|
||||
{ label: 'JCB', value: '18' },
|
||||
{ label: 'Laser', value: '19' },
|
||||
{ label: 'Maestro', value: '20' },
|
||||
{ label: 'Solo', value: '21' },
|
||||
{ label: 'Switch', value: '22' },
|
||||
{ label: 'iZettle', value: '23' },
|
||||
{ label: 'Swish', value: '24' },
|
||||
{ label: 'Venmo', value: '25' },
|
||||
{ label: 'Money Order', value: '26' },
|
||||
{ label: 'Alipay', value: '27' },
|
||||
{ label: 'Sofort', value: '28' },
|
||||
{ label: 'SEPA', value: '29' },
|
||||
{ label: 'GoCardless', value: '30' },
|
||||
{ label: 'Bitcoin', value: '31' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Transfer Reference',
|
||||
key: 'transferReference',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Private Notes',
|
||||
key: 'privateNotes',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
];
|
@@ -0,0 +1,42 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
import { fields } from './fields';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create payment',
|
||||
key: 'createPayment',
|
||||
description: 'Creates a new payment.',
|
||||
arguments: fields,
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
clientId,
|
||||
paymentDate,
|
||||
invoiceId,
|
||||
invoiceAmount,
|
||||
paymentType,
|
||||
transferReference,
|
||||
privateNotes,
|
||||
} = $.step.parameters;
|
||||
|
||||
const bodyFields = {
|
||||
client_id: clientId,
|
||||
date: paymentDate,
|
||||
invoices: [
|
||||
{
|
||||
invoice_id: invoiceId,
|
||||
amount: invoiceAmount,
|
||||
},
|
||||
],
|
||||
type_id: paymentType,
|
||||
transaction_reference: transferReference,
|
||||
private_notes: privateNotes,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(bodyFields);
|
||||
|
||||
const response = await $.http.post('/v1/payments', body);
|
||||
|
||||
$.setActionItem({ raw: response.data.data });
|
||||
},
|
||||
});
|
@@ -0,0 +1,114 @@
|
||||
export const fields = [
|
||||
{
|
||||
label: 'Product Key',
|
||||
key: 'productKey',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Notes',
|
||||
key: 'notes',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Price',
|
||||
key: 'price',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Quantity',
|
||||
key: 'quantity',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Rate 1',
|
||||
key: 'taxRate1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Name 1',
|
||||
key: 'taxName1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Rate 2',
|
||||
key: 'taxRate2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Name 2',
|
||||
key: 'taxName2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Rate 3',
|
||||
key: 'taxRate3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Tax Name 3',
|
||||
key: 'taxName3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Value 1',
|
||||
key: 'customValue1',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Value 2',
|
||||
key: 'customValue2',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Value 3',
|
||||
key: 'customValue3',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Custom Value 4',
|
||||
key: 'customValue4',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
];
|
@@ -0,0 +1,52 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
import { fields } from './fields';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create product',
|
||||
key: 'createProduct',
|
||||
description: 'Creates a new product.',
|
||||
arguments: fields,
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
productKey,
|
||||
notes,
|
||||
price,
|
||||
quantity,
|
||||
taxRate1,
|
||||
taxName1,
|
||||
taxRate2,
|
||||
taxName2,
|
||||
taxRate3,
|
||||
taxName3,
|
||||
customValue1,
|
||||
customValue2,
|
||||
customValue3,
|
||||
customValue4,
|
||||
} = $.step.parameters;
|
||||
|
||||
const bodyFields = {
|
||||
product_key: productKey,
|
||||
notes: notes,
|
||||
price: price,
|
||||
quantity: quantity,
|
||||
tax_rate1: taxRate1,
|
||||
tax_name1: taxName1,
|
||||
tax_rate2: taxRate2,
|
||||
tax_name2: taxName2,
|
||||
tax_rate3: taxRate3,
|
||||
tax_name3: taxName3,
|
||||
custom_value1: customValue1,
|
||||
custom_value2: customValue2,
|
||||
custom_value3: customValue3,
|
||||
custom_value4: customValue4,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(bodyFields);
|
||||
|
||||
const response = await $.http.post('/v1/products', body);
|
||||
|
||||
$.setActionItem({ raw: response.data.data });
|
||||
},
|
||||
});
|
6
packages/backend/src/apps/invoice-ninja/actions/index.ts
Normal file
6
packages/backend/src/apps/invoice-ninja/actions/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import createClient from './create-client';
|
||||
import createInvoice from './create-invoice';
|
||||
import createPayment from './create-payment';
|
||||
import createProduct from './create-product';
|
||||
|
||||
export default [createClient, createInvoice, createPayment, createProduct];
|
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" role="img" xmlns="http://www.w3.org/2000/svg"><path d="M16.247 10.326a1.164 1.164 0 11-2.328 0 1.164 1.164 0 012.328 0zm-6.288 0a1.164 1.164 0 11-2.329 0 1.164 1.164 0 012.329 0zm-.14 13.52c-4.712-.98-8.227-4.257-9.482-8.842-.421-1.537-.421-4.49 0-6.027C1.506 4.709 4.73 1.485 8.997.316c1.538-.421 4.49-.421 6.028 0 4.267 1.169 7.492 4.393 8.66 8.66.24.874.294 1.43.294 3.014 0 1.584-.054 2.14-.293 3.014-1.17 4.271-4.439 7.536-8.661 8.65-1.391.367-3.916.46-5.206.192zm6.64-9.315c-3.047-1.348-4.054-1.737-4.5-1.737-.446 0-1.433.38-4.38 1.684-2.091.926-3.828 1.76-3.86 1.79h16.663zm-9.873-.361c1.621-.729 3.06-1.387 3.196-1.464.258-.145.337-.09-5.285-3.682-.56-.358-1.023-.698-1.025-.65V15.564a790.1 790.1 0 003.114-1.394zm14.078-2.194V8.417c0-.11-1.676.993-3.496 2.12-3 1.854-3.281 2.06-3.004 2.185 1.345.611 6.42 2.862 6.5 2.872zm-8.169.11c.545.125.643.104 1.226-.263.349-.22.655-.419.681-.442.026-.024-.05-.181-.167-.35-.118-.168-.215-.5-.215-.739V9.86l-.569.21c-.726.267-2.28.27-3 .005l-.556-.205.013.452c.007.26-.088.563-.225.715-.232.256-.22.276.45.726.64.432.725.455 1.23.327a2.349 2.349 0 011.132-.002zm-4.23-2.65c-.105-.113-2.97-.954-3.033-.891-.03.03.504.414 1.186.854l1.24.8.34-.344c.186-.188.307-.377.268-.42zm9.76-.373c.473-.306.8-.555.728-.555-.155 0-2.877.804-3.027.894-.057.034.033.229.2.433l.304.37.47-.293c.257-.162.854-.544 1.326-.85zm-1.636-.555c2.11-.59 3.867-1.102 3.904-1.139H3.59c.187.187 7.779 2.195 8.323 2.202.41.005 2.014-.376 4.476-1.063z"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
33
packages/backend/src/apps/invoice-ninja/auth/index.ts
Normal file
33
packages/backend/src/apps/invoice-ninja/auth/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import verifyCredentials from './verify-credentials';
|
||||
import isStillVerified from './is-still-verified';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'apiToken',
|
||||
label: 'API Token',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description:
|
||||
'Tokens can be created in the v5 app on Settings > Account Management',
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'instanceUrl',
|
||||
label: 'Invoice Ninja instance URL (optional)',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: "Leave this field blank if you're using hosted platform.",
|
||||
clickToCopy: true,
|
||||
},
|
||||
],
|
||||
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
};
|
@@ -0,0 +1,10 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import verifyCredentials from './verify-credentials';
|
||||
|
||||
const isStillVerified = async ($: IGlobalVariable) => {
|
||||
await verifyCredentials($);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
@@ -0,0 +1,15 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const verifyCredentials = async ($: IGlobalVariable) => {
|
||||
const { data } = await $.http.get('/v1/ping');
|
||||
|
||||
const screenName = [data.user_name, data.company_name]
|
||||
.filter(Boolean)
|
||||
.join(' @ ');
|
||||
|
||||
await $.auth.set({
|
||||
screenName,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
@@ -0,0 +1,20 @@
|
||||
import { TBeforeRequest } from '@automatisch/types';
|
||||
|
||||
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
||||
const { instanceUrl } = $.auth.data;
|
||||
|
||||
if (instanceUrl) {
|
||||
requestConfig.baseURL = instanceUrl as string;
|
||||
}
|
||||
|
||||
requestConfig.headers['X-API-TOKEN'] = $.auth.data.apiToken as string;
|
||||
|
||||
requestConfig.headers['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
requestConfig.headers['Content-Type'] =
|
||||
requestConfig.headers['Content-Type'] || 'application/json';
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
@@ -0,0 +1,18 @@
|
||||
import isObject from 'lodash/isObject';
|
||||
|
||||
export function filterProvidedFields(body: Record<string, unknown>) {
|
||||
return Object.keys(body).reduce<Record<string, unknown>>((result, key) => {
|
||||
const value = body[key];
|
||||
if (isObject(value)) {
|
||||
const filteredNestedObj = filterProvidedFields(
|
||||
value as Record<string, unknown>
|
||||
);
|
||||
if (Object.keys(filteredNestedObj).length > 0) {
|
||||
result[key] = filteredNestedObj;
|
||||
}
|
||||
} else if (body[key]) {
|
||||
result[key] = value;
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
import { TBeforeRequest } from '@automatisch/types';
|
||||
|
||||
const setBaseUrl: TBeforeRequest = ($, requestConfig) => {
|
||||
const instanceUrl = $.auth.data.instanceUrl as string;
|
||||
|
||||
if (instanceUrl) {
|
||||
requestConfig.baseURL = instanceUrl;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default setBaseUrl;
|
@@ -0,0 +1,4 @@
|
||||
import listClients from './list-clients';
|
||||
import listInvoices from './list-invoices';
|
||||
|
||||
export default [listClients, listInvoices];
|
@@ -0,0 +1,35 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
export default {
|
||||
name: 'List clients',
|
||||
key: 'listClients',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
const clients: {
|
||||
data: IJSONObject[];
|
||||
} = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
const params = {
|
||||
sort: 'created_at|desc',
|
||||
};
|
||||
|
||||
const {
|
||||
data: { data },
|
||||
} = await $.http.get('/v1/clients', { params });
|
||||
|
||||
if (!data?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const client of data) {
|
||||
clients.data.push({
|
||||
value: client.id,
|
||||
name: client.name,
|
||||
});
|
||||
}
|
||||
|
||||
return clients;
|
||||
},
|
||||
};
|
@@ -0,0 +1,35 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
export default {
|
||||
name: 'List invoices',
|
||||
key: 'listInvoices',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
const invoices: {
|
||||
data: IJSONObject[];
|
||||
} = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
const params = {
|
||||
sort: 'created_at|desc',
|
||||
};
|
||||
|
||||
const {
|
||||
data: { data },
|
||||
} = await $.http.get('/v1/invoices', { params });
|
||||
|
||||
if (!data?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const invoice of data) {
|
||||
invoices.data.push({
|
||||
value: invoice.id,
|
||||
name: invoice.number,
|
||||
});
|
||||
}
|
||||
|
||||
return invoices;
|
||||
},
|
||||
};
|
0
packages/backend/src/apps/invoice-ninja/index.d.ts
vendored
Normal file
0
packages/backend/src/apps/invoice-ninja/index.d.ts
vendored
Normal file
23
packages/backend/src/apps/invoice-ninja/index.ts
Normal file
23
packages/backend/src/apps/invoice-ninja/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import defineApp from '../../helpers/define-app';
|
||||
import setBaseUrl from './common/set-base-url';
|
||||
import addAuthHeader from './common/add-auth-header';
|
||||
import auth from './auth';
|
||||
import triggers from './triggers';
|
||||
import actions from './actions';
|
||||
import dynamicData from './dynamic-data';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Invoice Ninja',
|
||||
key: 'invoice-ninja',
|
||||
baseUrl: 'https://invoiceninja.com',
|
||||
apiBaseUrl: 'https://invoicing.co/api',
|
||||
iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg',
|
||||
authDocUrl: 'https://automatisch.io/docs/apps/invoice-ninja/connection',
|
||||
primaryColor: '000000',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
actions,
|
||||
dynamicData,
|
||||
});
|
15
packages/backend/src/apps/invoice-ninja/triggers/index.ts
Normal file
15
packages/backend/src/apps/invoice-ninja/triggers/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import newClients from './new-clients';
|
||||
import newCredits from './new-credits';
|
||||
import newInvoices from './new-invoices';
|
||||
import newPayments from './new-payments';
|
||||
import newProjects from './new-projects';
|
||||
import newQuotes from './new-quotes';
|
||||
|
||||
export default [
|
||||
newClients,
|
||||
newCredits,
|
||||
newInvoices,
|
||||
newPayments,
|
||||
newProjects,
|
||||
newQuotes,
|
||||
];
|
@@ -0,0 +1,65 @@
|
||||
import Crypto from 'crypto';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
|
||||
type Response = {
|
||||
data: {
|
||||
data: {
|
||||
id: string;
|
||||
event_id: string;
|
||||
target_url: string;
|
||||
format: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New clients',
|
||||
key: 'newClients',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new client is added.',
|
||||
arguments: [],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const CREATE_CLIENT_EVENT_ID = '1';
|
||||
|
||||
const payload = {
|
||||
target_url: $.webhookUrl,
|
||||
event_id: CREATE_CLIENT_EVENT_ID,
|
||||
format: 'JSON',
|
||||
rest_method: 'post',
|
||||
};
|
||||
|
||||
const response: Response = await $.http.post('/v1/webhooks', payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(response.data.data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v1/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -0,0 +1,65 @@
|
||||
import Crypto from 'crypto';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
|
||||
type Response = {
|
||||
data: {
|
||||
data: {
|
||||
id: string;
|
||||
event_id: string;
|
||||
target_url: string;
|
||||
format: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New credits',
|
||||
key: 'newCredits',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new credit is added.',
|
||||
arguments: [],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const CREATE_CREDIT_EVENT_ID = '27';
|
||||
|
||||
const payload = {
|
||||
target_url: $.webhookUrl,
|
||||
event_id: CREATE_CREDIT_EVENT_ID,
|
||||
format: 'JSON',
|
||||
rest_method: 'post',
|
||||
};
|
||||
|
||||
const response: Response = await $.http.post('/v1/webhooks', payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(response.data.data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v1/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -0,0 +1,65 @@
|
||||
import Crypto from 'crypto';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
|
||||
type Response = {
|
||||
data: {
|
||||
data: {
|
||||
id: string;
|
||||
event_id: string;
|
||||
target_url: string;
|
||||
format: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New invoices',
|
||||
key: 'newInvoices',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new invoice is added.',
|
||||
arguments: [],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const CREATE_INVOICE_EVENT_ID = '2';
|
||||
|
||||
const payload = {
|
||||
target_url: $.webhookUrl,
|
||||
event_id: CREATE_INVOICE_EVENT_ID,
|
||||
format: 'JSON',
|
||||
rest_method: 'post',
|
||||
};
|
||||
|
||||
const response: Response = await $.http.post('/v1/webhooks', payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(response.data.data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v1/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -0,0 +1,65 @@
|
||||
import Crypto from 'crypto';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
|
||||
type Response = {
|
||||
data: {
|
||||
data: {
|
||||
id: string;
|
||||
event_id: string;
|
||||
target_url: string;
|
||||
format: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New payments',
|
||||
key: 'newPayments',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new payment is added.',
|
||||
arguments: [],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const CREATE_PAYMENT_EVENT_ID = '4';
|
||||
|
||||
const payload = {
|
||||
target_url: $.webhookUrl,
|
||||
event_id: CREATE_PAYMENT_EVENT_ID,
|
||||
format: 'JSON',
|
||||
rest_method: 'post',
|
||||
};
|
||||
|
||||
const response: Response = await $.http.post('/v1/webhooks', payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(response.data.data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v1/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -0,0 +1,65 @@
|
||||
import Crypto from 'crypto';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
|
||||
type Response = {
|
||||
data: {
|
||||
data: {
|
||||
id: string;
|
||||
event_id: string;
|
||||
target_url: string;
|
||||
format: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New projects',
|
||||
key: 'newProjects',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new project is added.',
|
||||
arguments: [],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const CREATE_PROJECT_EVENT_ID = '25';
|
||||
|
||||
const payload = {
|
||||
target_url: $.webhookUrl,
|
||||
event_id: CREATE_PROJECT_EVENT_ID,
|
||||
format: 'JSON',
|
||||
rest_method: 'post',
|
||||
};
|
||||
|
||||
const response: Response = await $.http.post('/v1/webhooks', payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(response.data.data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v1/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
@@ -0,0 +1,65 @@
|
||||
import Crypto from 'crypto';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
|
||||
type Response = {
|
||||
data: {
|
||||
data: {
|
||||
id: string;
|
||||
event_id: string;
|
||||
target_url: string;
|
||||
format: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New quotes',
|
||||
key: 'newQuotes',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new quote is added.',
|
||||
arguments: [],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const CREATE_QUOTE_EVENT_ID = '3';
|
||||
|
||||
const payload = {
|
||||
target_url: $.webhookUrl,
|
||||
event_id: CREATE_QUOTE_EVENT_ID,
|
||||
format: 'JSON',
|
||||
rest_method: 'post',
|
||||
};
|
||||
|
||||
const response: Response = await $.http.post('/v1/webhooks', payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(response.data.data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/v1/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
116
packages/backend/src/apps/miro/actions/copy-board/index.ts
Normal file
116
packages/backend/src/apps/miro/actions/copy-board/index.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Copy board',
|
||||
key: 'copyBoard',
|
||||
description: 'Creates a copy of an existing board.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Original board',
|
||||
key: 'originalBoard',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The board that you want to copy.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listBoards',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Title',
|
||||
key: 'title',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Title for the board.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Description',
|
||||
key: 'description',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'Description of the board.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Team Access',
|
||||
key: 'teamAccess',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Team access to the board. Can be private, view, comment or edit. Default: private.',
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Private - nobody in the team can find and access the board',
|
||||
value: 'private',
|
||||
},
|
||||
{
|
||||
label: 'View - any team member can find and view the board',
|
||||
value: 'view',
|
||||
},
|
||||
{
|
||||
label: 'Comment - any team member can find and comment the board',
|
||||
value: 'comment',
|
||||
},
|
||||
{
|
||||
label: 'Edit - any team member can find and edit the board',
|
||||
value: 'edit',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Access Via Link',
|
||||
key: 'accessViaLink',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Access to the board by link. Can be private, view, comment. Default: private.',
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Private - only you have access to the board',
|
||||
value: 'private',
|
||||
},
|
||||
{
|
||||
label: 'View - can view, no sign-in required',
|
||||
value: 'view',
|
||||
},
|
||||
{
|
||||
label: 'Comment - can comment, no sign-in required',
|
||||
value: 'comment',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const params = {
|
||||
copy_from: $.step.parameters.originalBoard,
|
||||
};
|
||||
|
||||
const body = {
|
||||
name: $.step.parameters.title,
|
||||
description: $.step.parameters.description,
|
||||
policy: {
|
||||
sharingPolicy: {
|
||||
access: $.step.parameters.accessViaLink || 'private',
|
||||
teamAccess: $.step.parameters.teamAccess || 'private',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const { data } = await $.http.put('/v2/boards', body, { params });
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
94
packages/backend/src/apps/miro/actions/create-board/index.ts
Normal file
94
packages/backend/src/apps/miro/actions/create-board/index.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create board',
|
||||
key: 'createBoard',
|
||||
description: 'Creates a new board.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Title',
|
||||
key: 'title',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Title for the board.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Description',
|
||||
key: 'description',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'Description of the board.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Team Access',
|
||||
key: 'teamAccess',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Team access to the board. Can be private, view, comment or edit. Default: private.',
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Private - nobody in the team can find and access the board',
|
||||
value: 'private',
|
||||
},
|
||||
{
|
||||
label: 'View - any team member can find and view the board',
|
||||
value: 'view',
|
||||
},
|
||||
{
|
||||
label: 'Comment - any team member can find and comment the board',
|
||||
value: 'comment',
|
||||
},
|
||||
{
|
||||
label: 'Edit - any team member can find and edit the board',
|
||||
value: 'edit',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Access Via Link',
|
||||
key: 'accessViaLink',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Access to the board by link. Can be private, view, comment. Default: private.',
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Private - only you have access to the board',
|
||||
value: 'private',
|
||||
},
|
||||
{
|
||||
label: 'View - can view, no sign-in required',
|
||||
value: 'view',
|
||||
},
|
||||
{
|
||||
label: 'Comment - can comment, no sign-in required',
|
||||
value: 'comment',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const body = {
|
||||
name: $.step.parameters.title,
|
||||
description: $.step.parameters.description,
|
||||
policy: {
|
||||
sharingPolicy: {
|
||||
access: $.step.parameters.accessViaLink || 'private',
|
||||
teamAccess: $.step.parameters.teamAccess || 'private',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const { data } = await $.http.post('/v2/boards', body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
@@ -0,0 +1,168 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
type Body = {
|
||||
data: {
|
||||
title: string;
|
||||
description?: string;
|
||||
dueDate?: string;
|
||||
};
|
||||
style?: {
|
||||
cardTheme?: string;
|
||||
};
|
||||
parent: {
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create card widget',
|
||||
key: 'createCardWidget',
|
||||
description: 'Creates a new card widget on an existing board.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Board',
|
||||
key: 'boardId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listBoards',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Frame',
|
||||
key: 'frameId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
dependsOn: ['parameters.boardId'],
|
||||
description:
|
||||
'You need to create a frame prior to this step. Switch frame to grid mode to avoid cards overlap.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listFrames',
|
||||
},
|
||||
{
|
||||
name: 'parameters.boardId',
|
||||
value: '{parameters.boardId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Card Title',
|
||||
key: 'cardTitle',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Card Title Link',
|
||||
key: 'cardTitleLink',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Card Description',
|
||||
key: 'cardDescription',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Card Due Date',
|
||||
key: 'cardDueDate',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description:
|
||||
'format: date-time. Example value: 2023-10-12 22:00:55+00:00',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Card Border Color',
|
||||
key: 'cardBorderColor',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: 'In hex format. Default is blue (#2399F3).',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'white', value: '#FFFFFF' },
|
||||
{ label: 'yellow', value: '#FEF445' },
|
||||
{ label: 'orange', value: '#FAC710' },
|
||||
{ label: 'red', value: '#F24726' },
|
||||
{ label: 'bright red', value: '#DA0063' },
|
||||
{ label: 'light gray', value: '#E6E6E6' },
|
||||
{ label: 'gray', value: '#808080' },
|
||||
{ label: 'black', value: '#1A1A1A' },
|
||||
{ label: 'light green', value: '#CEE741' },
|
||||
{ label: 'green', value: '#8FD14F' },
|
||||
{ label: 'dark green', value: '#0CA789' },
|
||||
{ label: 'light blue', value: '#12CDD4' },
|
||||
{ label: 'blue', value: '#2D9BF0' },
|
||||
{ label: 'dark blue', value: '#414BB2' },
|
||||
{ label: 'purple', value: '#9510AC' },
|
||||
{ label: 'dark purple', value: '#652CB3' },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
boardId,
|
||||
frameId,
|
||||
cardTitle,
|
||||
cardTitleLink,
|
||||
cardDescription,
|
||||
cardDueDate,
|
||||
cardBorderColor,
|
||||
} = $.step.parameters;
|
||||
|
||||
let title;
|
||||
if (cardTitleLink) {
|
||||
title = `<a href='${cardTitleLink}'>${cardTitle}</a>`;
|
||||
} else {
|
||||
title = cardTitle;
|
||||
}
|
||||
|
||||
const body: Body = {
|
||||
data: {
|
||||
title: title as string,
|
||||
description: cardDescription as string,
|
||||
},
|
||||
style: {},
|
||||
parent: {
|
||||
id: frameId as string,
|
||||
},
|
||||
};
|
||||
|
||||
if (cardBorderColor) {
|
||||
body.style.cardTheme = cardBorderColor as string;
|
||||
}
|
||||
|
||||
if (cardDueDate) {
|
||||
body.data.dueDate = cardDueDate as string;
|
||||
}
|
||||
|
||||
const response = await $.http.post(`/v2/boards/${boardId}/cards`, body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: response.data,
|
||||
});
|
||||
},
|
||||
});
|
5
packages/backend/src/apps/miro/actions/index.ts
Normal file
5
packages/backend/src/apps/miro/actions/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import copyBoard from './copy-board';
|
||||
import createBoard from './create-board';
|
||||
import createCardWidget from './create-card-widget';
|
||||
|
||||
export default [copyBoard, createBoard, createCardWidget];
|
1
packages/backend/src/apps/miro/assets/favicon.svg
Normal file
1
packages/backend/src/apps/miro/assets/favicon.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" width="2500" height="2500"><path d="M0 0h48v48H0z" fill="#ffd02f"/><path d="M32.708 6.4h-5.124l4.549 7.05-9.617-7.05h-5.124l4.549 9.238L12.324 6.4H7.2l4.474 11.926L7.2 41.6h5.124l9.617-24.955L17.392 41.6h5.124l9.617-27.142-4.549 27.142h5.124L42.4 11.785z" fill="#050038"/></svg>
|
After Width: | Height: | Size: 338 B |
20
packages/backend/src/apps/miro/auth/generate-auth-url.ts
Normal file
20
packages/backend/src/apps/miro/auth/generate-auth-url.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { IField, IGlobalVariable } from '@automatisch/types';
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
export default async function generateAuthUrl($: IGlobalVariable) {
|
||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
||||
);
|
||||
const redirectUri = oauthRedirectUrlField.value as string;
|
||||
const searchParams = new URLSearchParams({
|
||||
response_type: 'code',
|
||||
client_id: $.auth.data.clientId as string,
|
||||
redirect_uri: redirectUri,
|
||||
});
|
||||
|
||||
const url = `https://miro.com/oauth/authorize?${searchParams.toString()}`;
|
||||
|
||||
await $.auth.set({
|
||||
url,
|
||||
});
|
||||
}
|
48
packages/backend/src/apps/miro/auth/index.ts
Normal file
48
packages/backend/src/apps/miro/auth/index.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import generateAuthUrl from './generate-auth-url';
|
||||
import verifyCredentials from './verify-credentials';
|
||||
import refreshToken from './refresh-token';
|
||||
import isStillVerified from './is-still-verified';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'oAuthRedirectUrl',
|
||||
label: 'OAuth Redirect URL',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: true,
|
||||
value: '{WEB_APP_URL}/app/miro/connections/add',
|
||||
placeholder: null,
|
||||
description:
|
||||
'When asked to input a redirect URL in Miro, enter the URL above.',
|
||||
clickToCopy: true,
|
||||
},
|
||||
{
|
||||
key: 'clientId',
|
||||
label: 'Client ID',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'clientSecret',
|
||||
label: 'Client Secret',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
clickToCopy: false,
|
||||
},
|
||||
],
|
||||
|
||||
generateAuthUrl,
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
refreshToken,
|
||||
};
|
9
packages/backend/src/apps/miro/auth/is-still-verified.ts
Normal file
9
packages/backend/src/apps/miro/auth/is-still-verified.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import getCurrentUser from '../common/get-current-user';
|
||||
|
||||
const isStillVerified = async ($: IGlobalVariable) => {
|
||||
const currentUser = await getCurrentUser($);
|
||||
return !!currentUser;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
23
packages/backend/src/apps/miro/auth/refresh-token.ts
Normal file
23
packages/backend/src/apps/miro/auth/refresh-token.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { URLSearchParams } from 'node:url';
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const refreshToken = async ($: IGlobalVariable) => {
|
||||
const params = new URLSearchParams({
|
||||
grant_type: 'refresh_token',
|
||||
client_id: $.auth.data.clientId as string,
|
||||
client_secret: $.auth.data.clientSecret as string,
|
||||
refresh_token: $.auth.data.refreshToken as string,
|
||||
});
|
||||
|
||||
const { data } = await $.http.post('/v1/oauth/token', params.toString());
|
||||
|
||||
await $.auth.set({
|
||||
accessToken: data.access_token,
|
||||
expiresIn: data.expires_in,
|
||||
refreshToken: data.refresh_token,
|
||||
scope: data.scope,
|
||||
tokenType: data.token_type,
|
||||
});
|
||||
};
|
||||
|
||||
export default refreshToken;
|
40
packages/backend/src/apps/miro/auth/verify-credentials.ts
Normal file
40
packages/backend/src/apps/miro/auth/verify-credentials.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { IField, IGlobalVariable } from '@automatisch/types';
|
||||
import getCurrentUser from '../common/get-current-user';
|
||||
|
||||
const verifyCredentials = async ($: IGlobalVariable) => {
|
||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
||||
);
|
||||
const redirectUri = oauthRedirectUrlField.value as string;
|
||||
const params = {
|
||||
grant_type: 'authorization_code',
|
||||
client_id: $.auth.data.clientId,
|
||||
client_secret: $.auth.data.clientSecret,
|
||||
code: $.auth.data.code,
|
||||
redirect_uri: redirectUri,
|
||||
};
|
||||
|
||||
const { data } = await $.http.post(`/v1/oauth/token`, null, {
|
||||
params,
|
||||
});
|
||||
|
||||
await $.auth.set({
|
||||
accessToken: data.access_token,
|
||||
tokenType: data.token_type,
|
||||
});
|
||||
|
||||
const currentUser = await getCurrentUser($);
|
||||
|
||||
await $.auth.set({
|
||||
userId: data.user_id,
|
||||
refreshToken: data.refresh_token,
|
||||
expiresIn: data.expires_in,
|
||||
teamId: data.team_id,
|
||||
scope: data.scope,
|
||||
clientId: $.auth.data.clientId,
|
||||
clientSecret: $.auth.data.clientSecret,
|
||||
screenName: currentUser.name,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
11
packages/backend/src/apps/miro/common/add-auth-header.ts
Normal file
11
packages/backend/src/apps/miro/common/add-auth-header.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TBeforeRequest } from '@automatisch/types';
|
||||
|
||||
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
||||
if ($.auth.data?.accessToken) {
|
||||
requestConfig.headers.Authorization = `${$.auth.data.tokenType} ${$.auth.data.accessToken}`;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
10
packages/backend/src/apps/miro/common/get-current-user.ts
Normal file
10
packages/backend/src/apps/miro/common/get-current-user.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const getCurrentUser = async ($: IGlobalVariable) => {
|
||||
const { data } = await $.http.get(
|
||||
`https://api.miro.com/v1/oauth-token?access_token=${$.auth.data.accessToken}`
|
||||
);
|
||||
return data.user;
|
||||
};
|
||||
|
||||
export default getCurrentUser;
|
4
packages/backend/src/apps/miro/dynamic-data/index.ts
Normal file
4
packages/backend/src/apps/miro/dynamic-data/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import listBoards from './list-boards';
|
||||
import listFrames from './list-frames';
|
||||
|
||||
export default [listBoards, listFrames];
|
@@ -0,0 +1,46 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
type ResponseBody = {
|
||||
data: {
|
||||
data: {
|
||||
id: number;
|
||||
name: string;
|
||||
}[];
|
||||
links: {
|
||||
next: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'List boards',
|
||||
key: 'listBoards',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
const boards: {
|
||||
data: IJSONObject[];
|
||||
} = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
let next;
|
||||
do {
|
||||
const {
|
||||
data: { data, links },
|
||||
}: ResponseBody = await $.http.get('/v2/boards');
|
||||
|
||||
next = links?.next;
|
||||
|
||||
if (data.length) {
|
||||
for (const board of data) {
|
||||
boards.data.push({
|
||||
value: board.id,
|
||||
name: board.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
} while (next);
|
||||
|
||||
return boards;
|
||||
},
|
||||
};
|
@@ -0,0 +1,44 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
export default {
|
||||
name: 'List frames',
|
||||
key: 'listFrames',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
const frames: {
|
||||
data: IJSONObject[];
|
||||
} = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
const boardId = $.step.parameters.boardId;
|
||||
|
||||
if (!boardId) {
|
||||
return { data: [] };
|
||||
}
|
||||
|
||||
let next;
|
||||
do {
|
||||
const {
|
||||
data: { data, links },
|
||||
} = await $.http.get(`/v2/boards/${boardId}/items`);
|
||||
|
||||
next = links?.next;
|
||||
|
||||
const allFrames = data.filter(
|
||||
(item: IJSONObject) => item.type === 'frame'
|
||||
);
|
||||
|
||||
if (allFrames.length) {
|
||||
for (const frame of allFrames) {
|
||||
frames.data.push({
|
||||
value: frame.id,
|
||||
name: frame.data.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
} while (next);
|
||||
|
||||
return frames;
|
||||
},
|
||||
};
|
0
packages/backend/src/apps/miro/index.d.ts
vendored
Normal file
0
packages/backend/src/apps/miro/index.d.ts
vendored
Normal file
20
packages/backend/src/apps/miro/index.ts
Normal file
20
packages/backend/src/apps/miro/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import defineApp from '../../helpers/define-app';
|
||||
import addAuthHeader from './common/add-auth-header';
|
||||
import auth from './auth';
|
||||
import actions from './actions';
|
||||
import dynamicData from './dynamic-data';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Miro',
|
||||
key: 'miro',
|
||||
baseUrl: 'https://miro.com',
|
||||
apiBaseUrl: 'https://api.miro.com',
|
||||
iconUrl: '{BASE_URL}/apps/miro/assets/favicon.svg',
|
||||
authDocUrl: 'https://automatisch.io/docs/apps/miro/connection',
|
||||
primaryColor: 'F2CA02',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
actions,
|
||||
dynamicData,
|
||||
});
|
@@ -0,0 +1,198 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create activity',
|
||||
key: 'createActivity',
|
||||
description: 'Creates a new activity.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Subject',
|
||||
key: 'subject',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Organization',
|
||||
key: 'organizationId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listOrganizations',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Assigned To',
|
||||
key: 'userId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'If omitted, the activity will be assigned to the user of the connected account.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listUsers',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Person',
|
||||
key: 'personId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listPersons',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Deal',
|
||||
key: 'dealId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listDeals',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Is done?',
|
||||
key: 'isDone',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
options: [
|
||||
{
|
||||
label: 'No',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: 'Yes',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Type',
|
||||
key: 'type',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listActivityTypes',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Due Date',
|
||||
key: 'dueDate',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'Format must be YYYY-MM-DD',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Due Time',
|
||||
key: 'dueTime',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'Format must be HH:MM',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Duration',
|
||||
key: 'duration',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'Format must be HH:MM',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Note',
|
||||
key: 'note',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'Accepts HTML format',
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
subject,
|
||||
organizationId,
|
||||
userId,
|
||||
personId,
|
||||
dealId,
|
||||
isDone,
|
||||
type,
|
||||
dueTime,
|
||||
dueDate,
|
||||
duration,
|
||||
note,
|
||||
} = $.step.parameters;
|
||||
|
||||
const fields = {
|
||||
subject: subject as string,
|
||||
org_id: organizationId as number,
|
||||
user_id: userId as number,
|
||||
person_id: personId as number,
|
||||
deal_id: dealId as number,
|
||||
done: isDone as number,
|
||||
type: type as string,
|
||||
due_time: dueTime as string,
|
||||
due_date: dueDate as string,
|
||||
duration: duration as string,
|
||||
note: note as string,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(fields);
|
||||
|
||||
const {
|
||||
data: { data },
|
||||
} = await $.http.post('/api/v1/activities', body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
237
packages/backend/src/apps/pipedrive/actions/create-deal/index.ts
Normal file
237
packages/backend/src/apps/pipedrive/actions/create-deal/index.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create deal',
|
||||
key: 'createDeal',
|
||||
description: 'Creates a new deal.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Title',
|
||||
key: 'title',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Creation Date',
|
||||
key: 'addTime',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Requires admin access to Pipedrive account. Format: YYYY-MM-DD HH:MM:SS',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Status',
|
||||
key: 'status',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
options: [
|
||||
{
|
||||
label: 'Open',
|
||||
value: 'open',
|
||||
},
|
||||
{
|
||||
label: 'Won',
|
||||
value: 'won',
|
||||
},
|
||||
{
|
||||
label: 'Lost',
|
||||
value: 'lost',
|
||||
},
|
||||
{
|
||||
label: 'Deleted',
|
||||
value: 'deleted',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Lost Reason',
|
||||
key: 'lostReason',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Stage',
|
||||
key: 'stageId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
value: '1',
|
||||
description:
|
||||
'The ID of the stage this deal will be added to. If omitted, the deal will be placed in the first stage of the default pipeline.',
|
||||
options: [
|
||||
{
|
||||
label: 'Qualified (Pipeline)',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: 'Contact Made (Pipeline)',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: 'Prospect Qualified (Pipeline)',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: 'Needs Defined (Pipeline)',
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
label: 'Proposal Made (Pipeline)',
|
||||
value: 5,
|
||||
},
|
||||
{
|
||||
label: 'Negotiations Started (Pipeline)',
|
||||
value: 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Owner',
|
||||
key: 'userId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Select user who will be marked as the owner of this deal. If omitted, the authorized user will be used.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listUsers',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Organization',
|
||||
key: 'organizationId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: 'Organization this deal will be associated with.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listOrganizations',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Person',
|
||||
key: 'personId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: 'Person this deal will be associated with.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listPersons',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Probability',
|
||||
key: 'probability',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description:
|
||||
'The success probability percentage of the deal. Used/shown only when deal_probability for the pipeline of the deal is enabled.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Expected Close Date',
|
||||
key: 'expectedCloseDate',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description:
|
||||
'The expected close date of the deal. In ISO 8601 format: YYYY-MM-DD.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Value',
|
||||
key: 'value',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'The value of the deal. If omitted, value will be set to 0.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Currency',
|
||||
key: 'currency',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'The currency of the deal. Accepts a 3-character currency code. If omitted, currency will be set to the default currency of the authorized user.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listCurrencies',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
title,
|
||||
addTime,
|
||||
status,
|
||||
lostReason,
|
||||
stageId,
|
||||
userId,
|
||||
organizationId,
|
||||
personId,
|
||||
probability,
|
||||
expectedCloseDate,
|
||||
value,
|
||||
currency,
|
||||
} = $.step.parameters;
|
||||
|
||||
const fields = {
|
||||
title: title as string,
|
||||
value: value as string,
|
||||
add_time: addTime as string,
|
||||
status: status as string,
|
||||
lost_reason: lostReason as string,
|
||||
stage_id: stageId as number,
|
||||
user_id: userId as number,
|
||||
org_id: organizationId as number,
|
||||
person_id: personId as number,
|
||||
probability: probability as number,
|
||||
expected_close_date: expectedCloseDate as string,
|
||||
currency: currency as string,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(fields);
|
||||
|
||||
const {
|
||||
data: { data },
|
||||
} = await $.http.post('/api/v1/deals', body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
185
packages/backend/src/apps/pipedrive/actions/create-lead/index.ts
Normal file
185
packages/backend/src/apps/pipedrive/actions/create-lead/index.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
|
||||
type LabelIds = { __id: string; leadLabelId: string }[];
|
||||
|
||||
type LabelValue = { amount?: number; currency?: string };
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create lead',
|
||||
key: 'createLead',
|
||||
description: 'Creates a new lead.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Title',
|
||||
key: 'title',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Person',
|
||||
key: 'personId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Lead must be associated with at least one person or organization.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listPersons',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Organization',
|
||||
key: 'organizationId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Lead must be associated with at least one person or organization.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listOrganizations',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Owner',
|
||||
key: 'ownerId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Select user who will be marked as the owner of this lead. If omitted, the authorized user will be used.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listUsers',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Lead Labels',
|
||||
key: 'labelIds',
|
||||
type: 'dynamic' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
fields: [
|
||||
{
|
||||
label: 'Label',
|
||||
key: 'leadLabelId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listLeadLabels',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Expected Close Date',
|
||||
key: 'expectedCloseDate',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'E.g. 2023-10-23',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Lead Value',
|
||||
key: 'value',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'E.g. 150',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Lead Value Currency',
|
||||
key: 'currency',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: 'This field is required if a Lead Value amount is provided.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listCurrencies',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
title,
|
||||
personId,
|
||||
organizationId,
|
||||
ownerId,
|
||||
labelIds,
|
||||
expectedCloseDate,
|
||||
value,
|
||||
currency,
|
||||
} = $.step.parameters;
|
||||
|
||||
const onlyLabelIds = (labelIds as LabelIds)
|
||||
.map((labelId) => labelId.leadLabelId)
|
||||
.filter(Boolean);
|
||||
|
||||
const labelValue: LabelValue = {};
|
||||
|
||||
if (value) {
|
||||
labelValue.amount = Number(value);
|
||||
}
|
||||
if (currency) {
|
||||
labelValue.currency = currency as string;
|
||||
}
|
||||
|
||||
const fields = {
|
||||
title: title as string,
|
||||
person_id: Number(personId),
|
||||
organization_id: Number(organizationId),
|
||||
owner_id: Number(ownerId),
|
||||
expected_close_date: expectedCloseDate as string,
|
||||
label_ids: onlyLabelIds,
|
||||
value: labelValue,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(fields);
|
||||
|
||||
const {
|
||||
data: { data },
|
||||
} = await $.http.post('/api/v1/leads', body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
198
packages/backend/src/apps/pipedrive/actions/create-note/index.ts
Normal file
198
packages/backend/src/apps/pipedrive/actions/create-note/index.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create note',
|
||||
key: 'createNote',
|
||||
description: 'Creates a new note.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Content',
|
||||
key: 'content',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Supports some HTML formatting.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Deal',
|
||||
key: 'dealId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Note must be associated with at least one deal, person, organization, or lead.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listDeals',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Pin note on specified deal?',
|
||||
key: 'pinnedDeal',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
options: [
|
||||
{
|
||||
label: 'No',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: 'Yes',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Person',
|
||||
key: 'personId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Note must be associated with at least one deal, person, organization, or lead.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listPersons',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Pin note on specified person?',
|
||||
key: 'pinnedPerson',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
options: [
|
||||
{
|
||||
label: 'No',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: 'Yes',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Organization',
|
||||
key: 'organizationId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Note must be associated with at least one deal, person, organization, or lead.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listOrganizations',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Pin note on specified organization?',
|
||||
key: 'pinnedOrganization',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
options: [
|
||||
{
|
||||
label: 'No',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: 'Yes',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Lead',
|
||||
key: 'leadId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'Note must be associated with at least one deal, person, organization, or lead.',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listLeads',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Pin note on specified lead?',
|
||||
key: 'pinnedLead',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
options: [
|
||||
{
|
||||
label: 'No',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: 'Yes',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
content,
|
||||
dealId,
|
||||
pinnedDeal,
|
||||
personId,
|
||||
pinnedPerson,
|
||||
organizationId,
|
||||
pinnedOrganization,
|
||||
leadId,
|
||||
pinnedLead,
|
||||
} = $.step.parameters;
|
||||
|
||||
const fields = {
|
||||
content: content as string,
|
||||
deal_id: dealId as number,
|
||||
pinned_to_deal_flag: pinnedDeal as number,
|
||||
person_id: personId as number,
|
||||
pinned_to_person_flag: pinnedPerson as number,
|
||||
org_id: organizationId as number,
|
||||
pinned_to_organization_flag: pinnedOrganization as number,
|
||||
lead_id: leadId as string,
|
||||
pinned_to_lead_flag: pinnedLead as number,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(fields);
|
||||
|
||||
const {
|
||||
data: { data },
|
||||
} = await $.http.post('/api/v1/notes', body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
@@ -0,0 +1,74 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create organization',
|
||||
key: 'createOrganization',
|
||||
description: 'Creates a new organization.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Name',
|
||||
key: 'name',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Owner',
|
||||
key: 'ownerId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listUsers',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Label',
|
||||
key: 'labelId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listOrganizationLabelField',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const { name, ownerId, labelId } = $.step.parameters;
|
||||
|
||||
const fields = {
|
||||
name: name,
|
||||
owner_id: ownerId,
|
||||
label: labelId,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(fields);
|
||||
|
||||
const {
|
||||
data: { data },
|
||||
} = await $.http.post('/api/v1/organizations', body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
@@ -0,0 +1,143 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
import { filterProvidedFields } from '../../common/filter-provided-fields';
|
||||
|
||||
type TEmail = {
|
||||
__id: string;
|
||||
email: string;
|
||||
}[];
|
||||
|
||||
type TPhone = {
|
||||
__id: string;
|
||||
phone: string;
|
||||
}[];
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create person',
|
||||
key: 'createPerson',
|
||||
description: 'Creates a new person.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Name',
|
||||
key: 'name',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Owner',
|
||||
key: 'ownerId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listUsers',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Organization',
|
||||
key: 'organizationId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listOrganizations',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Emails',
|
||||
key: 'emails',
|
||||
type: 'dynamic' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
fields: [
|
||||
{
|
||||
label: 'Email',
|
||||
key: 'email',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Phones',
|
||||
key: 'phones',
|
||||
type: 'dynamic' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
fields: [
|
||||
{
|
||||
label: 'Phone',
|
||||
key: 'phone',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Label',
|
||||
key: 'labelId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: '',
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listPersonLabelField',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const { name, ownerId, organizationId, labelId } = $.step.parameters;
|
||||
const emails = $.step.parameters.emails as TEmail;
|
||||
const emailValues = emails.map((entry) => entry.email);
|
||||
const phones = $.step.parameters.phones as TPhone;
|
||||
const phoneValues = phones.map((entry) => entry.phone);
|
||||
|
||||
const fields = {
|
||||
name: name,
|
||||
owner_id: ownerId,
|
||||
org_id: organizationId,
|
||||
email: emailValues,
|
||||
phone: phoneValues,
|
||||
label: labelId,
|
||||
};
|
||||
|
||||
const body = filterProvidedFields(fields);
|
||||
|
||||
const {
|
||||
data: { data },
|
||||
} = await $.http.post('/api/v1/persons', body);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
15
packages/backend/src/apps/pipedrive/actions/index.ts
Normal file
15
packages/backend/src/apps/pipedrive/actions/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import createActivity from './create-activity';
|
||||
import createDeal from './create-deal';
|
||||
import createLead from './create-lead';
|
||||
import createNote from './create-note';
|
||||
import createOrganization from './create-organization';
|
||||
import createPerson from './create-person';
|
||||
|
||||
export default [
|
||||
createActivity,
|
||||
createDeal,
|
||||
createLead,
|
||||
createNote,
|
||||
createOrganization,
|
||||
createPerson,
|
||||
];
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user