Compare commits
205 Commits
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
|
POSTGRES_PASSWORD: automatisch_password
|
||||||
REDIS_HOST: localhost
|
REDIS_HOST: localhost
|
||||||
APP_ENV: production
|
APP_ENV: production
|
||||||
LICENSE_KEY: ${{ secrets.E2E_LICENSE_KEY }}
|
LICENSE_KEY: dummy_license_key
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
runs-on: ubuntu-latest
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:14.5-alpine
|
image: postgres:14.5-alpine
|
||||||
@@ -67,22 +68,49 @@ jobs:
|
|||||||
- name: Seed user
|
- name: Seed user
|
||||||
working-directory: ./packages/backend
|
working-directory: ./packages/backend
|
||||||
run: yarn db:seed:user &
|
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
|
- name: Run Automatisch
|
||||||
run: yarn start &
|
run: yarn start &
|
||||||
working-directory: ./packages/backend
|
working-directory: ./packages/backend
|
||||||
- name: Run Automatisch worker
|
- name: Run Automatisch worker
|
||||||
run: node dist/src/worker.js &
|
run: node dist/src/worker.js &
|
||||||
working-directory: ./packages/backend
|
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
|
- name: Run Playwright tests
|
||||||
working-directory: ./packages/e2e-tests
|
working-directory: ./packages/e2e-tests
|
||||||
env:
|
env:
|
||||||
LOGIN_EMAIL: user@automatisch.io
|
LOGIN_EMAIL: user@automatisch.io
|
||||||
LOGIN_PASSWORD: sample
|
LOGIN_PASSWORD: sample
|
||||||
BASE_URL: http://localhost:3000
|
BASE_URL: http://localhost:3000
|
||||||
|
GITHUB_CLIENT_ID: 1c0417daf898adfbd99a
|
||||||
|
GITHUB_CLIENT_SECRET: 3328fa814dd582ccd03dbe785cfd683fb8da92b3
|
||||||
run: yarn test
|
run: yarn test
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: playwright-report
|
name: playwright-report
|
||||||
path: ./packages/e2e-tests/test-results/**/*
|
path: packages/e2e-tests/test-results
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
@@ -3,14 +3,13 @@ HOST=localhost
|
|||||||
PROTOCOL=http
|
PROTOCOL=http
|
||||||
PORT=3000
|
PORT=3000
|
||||||
LOG_LEVEL=debug
|
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_DATABASE=automatisch_test
|
||||||
POSTGRES_PORT=5432
|
POSTGRES_PORT=5432
|
||||||
POSTGRES_HOST=localhost
|
|
||||||
POSTGRES_USERNAME=automatisch_test_user
|
POSTGRES_USERNAME=automatisch_test_user
|
||||||
POSTGRES_PASSWORD=
|
POSTGRES_PASSWORD=automatisch_test_user_password
|
||||||
POSTGRES_ENABLE_SSL=false
|
REDIS_HOST=localhost
|
||||||
ENCRYPTION_KEY=secret
|
AUTOMATISCH_CLOUD=true
|
||||||
APP_SECRET_KEY=secret
|
|
||||||
REDIS_PORT=6379
|
|
||||||
REDIS_HOST=127.0.0.1
|
|
||||||
|
@@ -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';
|
import appConfig from './src/config/app';
|
||||||
|
|
||||||
const fileExtension = appConfig.isDev ? 'ts' : 'js';
|
const fileExtension = appConfig.isDev || appConfig.isTest ? 'ts' : 'js';
|
||||||
|
|
||||||
const knexConfig = {
|
const knexConfig = {
|
||||||
client: 'pg',
|
client: 'pg',
|
||||||
@@ -23,6 +24,7 @@ const knexConfig = {
|
|||||||
seeds: {
|
seeds: {
|
||||||
directory: __dirname + '/src/db/seeds',
|
directory: __dirname + '/src/db/seeds',
|
||||||
},
|
},
|
||||||
|
...(appConfig.isTest ? knexSnakeCaseMappers() : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default knexConfig;
|
export default knexConfig;
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
"build:watch": "nodemon --watch 'src/**/*.ts' --watch 'bin/**/*.ts' --exec yarn build --ext ts",
|
"build:watch": "nodemon --watch 'src/**/*.ts' --watch 'bin/**/*.ts' --exec yarn build --ext ts",
|
||||||
"start": "node dist/src/server.js",
|
"start": "node dist/src/server.js",
|
||||||
"pretest": "APP_ENV=test ts-node ./test/setup/prepare-test-env.ts",
|
"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",
|
"lint": "eslint . --ignore-path ../../.eslintignore",
|
||||||
"db:create": "ts-node ./bin/database/create.ts",
|
"db:create": "ts-node ./bin/database/create.ts",
|
||||||
"db:seed:user": "ts-node ./bin/database/seed-user.ts",
|
"db:seed:user": "ts-node ./bin/database/seed-user.ts",
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
"https-proxy-agent": "^7.0.1",
|
"https-proxy-agent": "^7.0.1",
|
||||||
"jsonwebtoken": "^9.0.0",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"knex": "^2.4.0",
|
"knex": "^2.4.0",
|
||||||
|
"libphonenumber-js": "^1.10.48",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"luxon": "2.5.2",
|
"luxon": "2.5.2",
|
||||||
"memory-cache": "^0.2.0",
|
"memory-cache": "^0.2.0",
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
"pg": "^8.7.1",
|
"pg": "^8.7.1",
|
||||||
"php-serialize": "^4.0.2",
|
"php-serialize": "^4.0.2",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
|
"raw-body": "^2.5.2",
|
||||||
"showdown": "^2.1.0",
|
"showdown": "^2.1.0",
|
||||||
"stripe": "^11.13.0",
|
"stripe": "^11.13.0",
|
||||||
"winston": "^3.7.1",
|
"winston": "^3.7.1",
|
||||||
@@ -115,12 +117,14 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@automatisch/types": "^0.9.3",
|
"@automatisch/types": "^0.9.3",
|
||||||
|
"@faker-js/faker": "^8.1.0",
|
||||||
"@types/bcrypt": "^5.0.0",
|
"@types/bcrypt": "^5.0.0",
|
||||||
"@types/bull": "^3.15.8",
|
"@types/bull": "^3.15.8",
|
||||||
"@types/cors": "^2.8.12",
|
"@types/cors": "^2.8.12",
|
||||||
"@types/crypto-js": "^4.0.2",
|
"@types/crypto-js": "^4.0.2",
|
||||||
"@types/express": "^4.17.15",
|
"@types/express": "^4.17.15",
|
||||||
"@types/http-errors": "^1.8.1",
|
"@types/http-errors": "^1.8.1",
|
||||||
|
"@types/jest": "^29.5.5",
|
||||||
"@types/jsonwebtoken": "^8.5.8",
|
"@types/jsonwebtoken": "^8.5.8",
|
||||||
"@types/lodash.get": "^4.4.6",
|
"@types/lodash.get": "^4.4.6",
|
||||||
"@types/memory-cache": "^0.2.2",
|
"@types/memory-cache": "^0.2.2",
|
||||||
@@ -132,9 +136,12 @@
|
|||||||
"@types/pino": "^7.0.5",
|
"@types/pino": "^7.0.5",
|
||||||
"@types/pluralize": "^0.0.30",
|
"@types/pluralize": "^0.0.30",
|
||||||
"@types/showdown": "^2.0.1",
|
"@types/showdown": "^2.0.1",
|
||||||
"ava": "^5.3.1",
|
"@types/supertest": "^2.0.14",
|
||||||
|
"jest": "^29.7.0",
|
||||||
"nodemon": "^2.0.13",
|
"nodemon": "^2.0.13",
|
||||||
"sinon": "^11.1.2",
|
"sinon": "^11.1.2",
|
||||||
|
"supertest": "^6.3.3",
|
||||||
|
"ts-jest": "^29.1.1",
|
||||||
"ts-node": "^10.2.1",
|
"ts-node": "^10.2.1",
|
||||||
"ts-node-dev": "^1.1.8"
|
"ts-node-dev": "^1.1.8"
|
||||||
},
|
},
|
||||||
|
@@ -33,6 +33,7 @@ injectBullBoardHandler(app, serverAdapter);
|
|||||||
appAssetsHandler(app);
|
appAssetsHandler(app);
|
||||||
|
|
||||||
app.use(morgan);
|
app.use(morgan);
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
express.json({
|
express.json({
|
||||||
limit: appConfig.requestBodySizeLimit,
|
limit: appConfig.requestBodySizeLimit,
|
||||||
|
@@ -1,61 +0,0 @@
|
|||||||
import defineAction from '../../../../helpers/define-action';
|
|
||||||
|
|
||||||
export default defineAction({
|
|
||||||
name: 'Get Device Location',
|
|
||||||
key: 'getDeviceLocation',
|
|
||||||
description: 'Get the location of the device.',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
label: 'MSISDN',
|
|
||||||
key: 'msisdn',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
description:
|
|
||||||
'Subscriber number in E.164 format (starting with country code). Optionally prefixed with ' +
|
|
||||||
'.',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Latitude',
|
|
||||||
key: 'latitude',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
description: 'Latitude component of location',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Longitude',
|
|
||||||
key: 'longitude',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
description: 'Longitude component of location',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Accuracy',
|
|
||||||
key: 'accuracy',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
description: 'Accuracy expected for location verification in km',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
const payload = {
|
|
||||||
ueId: {
|
|
||||||
msisdn: $.step.parameters.msisdn,
|
|
||||||
},
|
|
||||||
latitude: $.step.parameters.latitude,
|
|
||||||
longitude: $.step.parameters.longitude,
|
|
||||||
accuracy: $.step.parameters.accuracy,
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await $.http.post(
|
|
||||||
'https://api-eu.vonage.com/camara/location/v0/verify',
|
|
||||||
payload
|
|
||||||
);
|
|
||||||
|
|
||||||
$.setActionItem({ raw: response.data });
|
|
||||||
},
|
|
||||||
});
|
|
@@ -1,3 +0,0 @@
|
|||||||
import getDeviceLocation from './get-device-location';
|
|
||||||
|
|
||||||
export default [getDeviceLocation];
|
|
@@ -1,4 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 38" part="logo-svg" fill="#e20074" role="img" aria-labelledby="logo-title-2">
|
|
||||||
<path d="M7.6 25.1H0v-7.6h7.6v7.6ZM0 0v12.9h2.3v-.4c0-6.1 3.4-9.9 9.9-9.9h.4V30c0 3.8-1.5 5.3-5.3 5.3H6.1V38h19.8v-2.7h-1.1c-3.8 0-5.3-1.5-5.3-5.3V2.7h.4c6.5 0 9.9 3.8 9.9 9.9v.4h2.3V0H0Zm24.3 25.1h7.6v-7.6h-7.6v7.6Z">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 372 B |
@@ -1,39 +0,0 @@
|
|||||||
import { IGlobalVariable } from '@automatisch/types';
|
|
||||||
import { URLSearchParams } from 'url';
|
|
||||||
import jwt from 'jsonwebtoken';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
|
|
||||||
const verifyCredentials = async ($: IGlobalVariable) => {
|
|
||||||
const claims = {
|
|
||||||
application_id: $.auth.data.applicationId as string,
|
|
||||||
iat: Math.floor(new Date().getTime() / 1000),
|
|
||||||
exp: Math.floor(new Date().getTime() / 1000) + 24 * 60 * 60,
|
|
||||||
jti: uuidv4(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const privateKey = ($.auth.data.privateKey as string).replaceAll('\\n', '\n');
|
|
||||||
|
|
||||||
const jwtToken = jwt.sign(claims, privateKey, {
|
|
||||||
algorithm: 'RS256',
|
|
||||||
});
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
Authorization: 'Bearer ' + jwtToken,
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await $.http.post(
|
|
||||||
'https://api.nexmo.com/oauth2/token?grant_type=client_credentials',
|
|
||||||
null,
|
|
||||||
{ headers }
|
|
||||||
);
|
|
||||||
|
|
||||||
const responseData = Object.fromEntries(new URLSearchParams(response.data));
|
|
||||||
|
|
||||||
await $.auth.set({
|
|
||||||
accessToken: responseData.access_token,
|
|
||||||
tokenType: responseData.token_type,
|
|
||||||
expiresIn: responseData.expires_in,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default verifyCredentials;
|
|
@@ -1,18 +0,0 @@
|
|||||||
import defineApp from '../../helpers/define-app';
|
|
||||||
import addAuthHeader from './common/add-auth-header';
|
|
||||||
import auth from './auth';
|
|
||||||
import actions from './actions';
|
|
||||||
|
|
||||||
export default defineApp({
|
|
||||||
name: '5G API',
|
|
||||||
key: '5g-api',
|
|
||||||
iconUrl: '{BASE_URL}/apps/5g-api/assets/favicon.svg',
|
|
||||||
authDocUrl: 'https://automatisch.io/docs/apps/5g-api/connection',
|
|
||||||
supportsConnections: true,
|
|
||||||
baseUrl: 'https://developer.telekom.de',
|
|
||||||
apiBaseUrl: 'https://api.developer.telekom.de',
|
|
||||||
primaryColor: 'e20074',
|
|
||||||
beforeRequest: [addAuthHeader],
|
|
||||||
auth,
|
|
||||||
actions,
|
|
||||||
});
|
|
@@ -1,3 +1,4 @@
|
|||||||
|
import Crypto from 'crypto';
|
||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import defineTrigger from '../../../../helpers/define-trigger';
|
import defineTrigger from '../../../../helpers/define-trigger';
|
||||||
import webhookFilters from '../../common/webhook-filters';
|
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($) {
|
async testRun($) {
|
||||||
const lastExecutionStep = await $.getLastExecutionStep();
|
const lastExecutionStep = await $.getLastExecutionStep();
|
||||||
|
|
||||||
|
@@ -3,11 +3,13 @@ import defineAction from '../../../../helpers/define-action';
|
|||||||
import performMathOperation from './transformers/perform-math-operation';
|
import performMathOperation from './transformers/perform-math-operation';
|
||||||
import randomNumber from './transformers/random-number';
|
import randomNumber from './transformers/random-number';
|
||||||
import formatNumber from './transformers/format-number';
|
import formatNumber from './transformers/format-number';
|
||||||
|
import formatPhoneNumber from './transformers/format-phone-number';
|
||||||
|
|
||||||
const transformers = {
|
const transformers = {
|
||||||
performMathOperation,
|
performMathOperation,
|
||||||
randomNumber,
|
randomNumber,
|
||||||
formatNumber,
|
formatNumber,
|
||||||
|
formatPhoneNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
@@ -26,6 +28,7 @@ export default defineAction({
|
|||||||
{ label: 'Perform Math Operation', value: 'performMathOperation' },
|
{ label: 'Perform Math Operation', value: 'performMathOperation' },
|
||||||
{ label: 'Random Number', value: 'randomNumber' },
|
{ label: 'Random Number', value: 'randomNumber' },
|
||||||
{ label: 'Format Number', value: 'formatNumber' },
|
{ label: 'Format Number', value: 'formatNumber' },
|
||||||
|
{ label: 'Format Phone Number', value: 'formatPhoneNumber' },
|
||||||
],
|
],
|
||||||
additionalFields: {
|
additionalFields: {
|
||||||
type: 'query',
|
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;
|
@@ -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;
|
@@ -12,6 +12,7 @@ import useDefaultValue from './text/use-default-value';
|
|||||||
import performMathOperation from './numbers/perform-math-operation';
|
import performMathOperation from './numbers/perform-math-operation';
|
||||||
import randomNumber from './numbers/random-number';
|
import randomNumber from './numbers/random-number';
|
||||||
import formatNumber from './numbers/format-number';
|
import formatNumber from './numbers/format-number';
|
||||||
|
import formatPhoneNumber from './numbers/format-phone-number';
|
||||||
import formatDateTime from './date-time/format-date-time';
|
import formatDateTime from './date-time/format-date-time';
|
||||||
|
|
||||||
const options: IJSONObject = {
|
const options: IJSONObject = {
|
||||||
@@ -28,6 +29,7 @@ const options: IJSONObject = {
|
|||||||
performMathOperation,
|
performMathOperation,
|
||||||
randomNumber,
|
randomNumber,
|
||||||
formatNumber,
|
formatNumber,
|
||||||
|
formatPhoneNumber,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -19,6 +20,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.confidential_issues_events,
|
key: GITLAB_EVENT_TYPE.confidential_issues_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_issues_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_issues_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -19,6 +20,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.confidential_note_events,
|
key: GITLAB_EVENT_TYPE.confidential_note_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_note_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_note_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.deployment_events,
|
key: GITLAB_EVENT_TYPE.deployment_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.deployment_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.deployment_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.feature_flag_events,
|
key: GITLAB_EVENT_TYPE.feature_flag_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.feature_flag_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.feature_flag_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.issues_events,
|
key: GITLAB_EVENT_TYPE.issues_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.issues_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.issues_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -17,6 +18,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.job_events,
|
key: GITLAB_EVENT_TYPE.job_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.job_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.job_events),
|
||||||
unregisterHook,
|
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 =
|
export const getTestRunFn =
|
||||||
(eventData: IJSONObject) => ($: IGlobalVariable) => {
|
(eventData: IJSONObject) => ($: IGlobalVariable) => {
|
||||||
/*
|
/*
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.merge_requests_events,
|
key: GITLAB_EVENT_TYPE.merge_requests_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.merge_requests_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.merge_requests_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.note_events,
|
key: GITLAB_EVENT_TYPE.note_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.note_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.note_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.pipeline_events,
|
key: GITLAB_EVENT_TYPE.pipeline_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.pipeline_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.pipeline_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -54,6 +55,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
branchFilterStrategyArgumentDescriptor,
|
branchFilterStrategyArgumentDescriptor,
|
||||||
pushEventsBranchFilterArgumentDescriptor,
|
pushEventsBranchFilterArgumentDescriptor,
|
||||||
],
|
],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.push_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.push_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -17,6 +18,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.releases_events,
|
key: GITLAB_EVENT_TYPE.releases_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.releases_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.releases_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.tag_push_events,
|
key: GITLAB_EVENT_TYPE.tag_push_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.tag_push_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.tag_push_events),
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
|
@@ -3,6 +3,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import { GITLAB_EVENT_TYPE } from '../types';
|
import { GITLAB_EVENT_TYPE } from '../types';
|
||||||
import {
|
import {
|
||||||
getRegisterHookFn,
|
getRegisterHookFn,
|
||||||
|
getRunFn,
|
||||||
getTestRunFn,
|
getTestRunFn,
|
||||||
projectArgumentDescriptor,
|
projectArgumentDescriptor,
|
||||||
unregisterHook,
|
unregisterHook,
|
||||||
@@ -18,6 +19,7 @@ export const triggerDescriptor: IRawTrigger = {
|
|||||||
key: GITLAB_EVENT_TYPE.wiki_page_events,
|
key: GITLAB_EVENT_TYPE.wiki_page_events,
|
||||||
type: 'webhook',
|
type: 'webhook',
|
||||||
arguments: [projectArgumentDescriptor],
|
arguments: [projectArgumentDescriptor],
|
||||||
|
run: ($) => getRunFn($),
|
||||||
testRun: getTestRunFn(data),
|
testRun: getTestRunFn(data),
|
||||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.wiki_page_events),
|
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.wiki_page_events),
|
||||||
unregisterHook,
|
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 |
@@ -1,28 +1,22 @@
|
|||||||
import { IField, IGlobalVariable } from '@automatisch/types';
|
import { IField, IGlobalVariable } from '@automatisch/types';
|
||||||
import { URLSearchParams } from 'url';
|
import { URLSearchParams } from 'url';
|
||||||
|
import authScope from '../common/auth-scope';
|
||||||
|
|
||||||
export default async function generateAuthUrl($: IGlobalVariable) {
|
export default async function generateAuthUrl($: IGlobalVariable) {
|
||||||
const scopes = [
|
|
||||||
'read_odometer',
|
|
||||||
'required:read_vehicle_info',
|
|
||||||
'required:read_location',
|
|
||||||
'required:read_battery',
|
|
||||||
];
|
|
||||||
|
|
||||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
(field: IField) => field.key == 'oAuthRedirectUrl'
|
||||||
);
|
);
|
||||||
const redirectUri = oauthRedirectUrlField.value as string;
|
const redirectUri = oauthRedirectUrlField.value as string;
|
||||||
|
|
||||||
const searchParams = new URLSearchParams({
|
const searchParams = new URLSearchParams({
|
||||||
response_type: 'code',
|
|
||||||
client_id: $.auth.data.clientId as string,
|
client_id: $.auth.data.clientId as string,
|
||||||
scope: scopes.join(' '),
|
|
||||||
redirect_uri: redirectUri,
|
redirect_uri: redirectUri,
|
||||||
mode: 'simulated',
|
prompt: 'select_account',
|
||||||
|
scope: authScope.join(' '),
|
||||||
|
response_type: 'code',
|
||||||
|
access_type: 'offline',
|
||||||
});
|
});
|
||||||
|
|
||||||
const url = `https://connect.smartcar.com/oauth/authorize?${searchParams.toString()}`;
|
const url = `https://accounts.google.com/o/oauth2/v2/auth?${searchParams.toString()}`;
|
||||||
|
|
||||||
await $.auth.set({
|
await $.auth.set({
|
||||||
url,
|
url,
|
@@ -1,5 +1,6 @@
|
|||||||
import generateAuthUrl from './generate-auth-url';
|
import generateAuthUrl from './generate-auth-url';
|
||||||
import verifyCredentials from './verify-credentials';
|
import verifyCredentials from './verify-credentials';
|
||||||
|
import refreshToken from './refresh-token';
|
||||||
import isStillVerified from './is-still-verified';
|
import isStillVerified from './is-still-verified';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -10,24 +11,12 @@ export default {
|
|||||||
type: 'string' as const,
|
type: 'string' as const,
|
||||||
required: true,
|
required: true,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
value: '{WEB_APP_URL}/app/twitter/connections/add',
|
value: '{WEB_APP_URL}/app/google-calendar/connections/add',
|
||||||
placeholder: null,
|
placeholder: null,
|
||||||
description:
|
description:
|
||||||
'When asked to input an OAuth callback or redirect URL in Smartcar OAuth, enter the URL above.',
|
'When asked to input a redirect URL in Google Cloud, enter the URL above.',
|
||||||
clickToCopy: true,
|
clickToCopy: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: 'screenName',
|
|
||||||
label: 'Screen Name',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
readOnly: false,
|
|
||||||
value: null,
|
|
||||||
placeholder: null,
|
|
||||||
description:
|
|
||||||
'Screen name of your connection to be used on Automatisch UI.',
|
|
||||||
clickToCopy: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: 'clientId',
|
key: 'clientId',
|
||||||
label: 'Client ID',
|
label: 'Client ID',
|
||||||
@@ -55,4 +44,5 @@ export default {
|
|||||||
generateAuthUrl,
|
generateAuthUrl,
|
||||||
verifyCredentials,
|
verifyCredentials,
|
||||||
isStillVerified,
|
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;
|
@@ -1,10 +1,8 @@
|
|||||||
import { TBeforeRequest } from '@automatisch/types';
|
import { TBeforeRequest } from '@automatisch/types';
|
||||||
|
|
||||||
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
||||||
const { accessToken } = $.auth.data;
|
if ($.auth.data?.accessToken) {
|
||||||
|
requestConfig.headers.Authorization = `${$.auth.data.tokenType} ${$.auth.data.accessToken}`;
|
||||||
if (accessToken) {
|
|
||||||
requestConfig.headers.Authorization = `Bearer ${accessToken}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return requestConfig;
|
return requestConfig;
|
@@ -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;
|
||||||
|
},
|
||||||
|
};
|
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);
|
||||||
|
},
|
||||||
|
});
|
@@ -1,20 +0,0 @@
|
|||||||
import defineAction from '../../../../helpers/define-action';
|
|
||||||
|
|
||||||
export default defineAction({
|
|
||||||
name: 'Get Battery Level',
|
|
||||||
key: 'getBatteryLevel',
|
|
||||||
description: 'Get the battery level of a vehicle',
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
const response = await $.http.get(
|
|
||||||
`https://sandbox.rest-api.high-mobility.com/v5/charging`
|
|
||||||
);
|
|
||||||
|
|
||||||
$.setActionItem({
|
|
||||||
raw: {
|
|
||||||
batteryLevel: response.data.batteryLevel.data,
|
|
||||||
estimatedRange: response.data.estimatedRange.data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
@@ -1,15 +0,0 @@
|
|||||||
import defineAction from '../../../../helpers/define-action';
|
|
||||||
|
|
||||||
export default defineAction({
|
|
||||||
name: 'Get Vehicle Location',
|
|
||||||
key: 'getVehicleLocation',
|
|
||||||
description: 'Get the location of a vehicle',
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
const response = await $.http.get(
|
|
||||||
`https://sandbox.rest-api.high-mobility.com/v5/vehicle_location`
|
|
||||||
);
|
|
||||||
|
|
||||||
$.setActionItem({ raw: response.data });
|
|
||||||
},
|
|
||||||
});
|
|
@@ -1,4 +0,0 @@
|
|||||||
import getVehicleLocation from './get-vehicle-location';
|
|
||||||
import getBatteryLevel from './get-battery-level';
|
|
||||||
|
|
||||||
export default [getVehicleLocation, getBatteryLevel];
|
|
@@ -1,3 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.1098 0H21.9778C27.5162 0 32.0436 4.52747 31.9997 10.0659V21.9341C31.9997 27.4725 27.4723 32 21.9338 32H10.0658C4.52743 32 0 27.4725 0 21.9341V10.0659C0 4.52747 4.52743 0 10.1098 0ZM9.58232 17.1868H14.4174C14.9889 17.1868 15.4724 16.7033 15.4724 16.1319C15.4724 15.5604 14.9889 15.0769 14.4174 15.0769H9.58232V10.4615C9.58232 9.89011 9.09881 9.40659 8.52739 9.40659C7.95597 9.40659 7.47245 9.89011 7.47245 10.4615V21.5824C7.47245 22.1538 7.95597 22.6374 8.52739 22.6374C9.09881 22.6374 9.58232 22.1538 9.58232 21.5824V17.1868ZM23.5163 22.6374C24.0877 22.6374 24.5712 22.1538 24.5712 21.5824H24.5674V10.4691C24.5712 10.4336 24.5731 10.3975 24.5731 10.361C24.5731 9.80393 24.1216 9.35237 23.5645 9.35237C23.2507 9.35237 22.9704 9.49569 22.7854 9.72044L22.7851 9.7192L17.4943 14.4615C17.0548 14.8571 17.0108 15.5165 17.4064 15.956C17.6262 16.1758 17.8899 16.3077 18.1976 16.3077C18.4614 16.3077 18.6811 16.2198 18.9009 16.044L22.4613 12.8352V21.5824C22.4613 22.1538 22.9448 22.6374 23.5163 22.6374Z" fill="#0A4B58"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,93 +0,0 @@
|
|||||||
import generateAuthUrl from './generate-auth-url';
|
|
||||||
import verifyCredentials from './verify-credentials';
|
|
||||||
import isStillVerified from './is-still-verified';
|
|
||||||
import refreshToken from './refresh-token';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
key: 'oAuthRedirectUrl',
|
|
||||||
label: 'OAuth Redirect URL',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
readOnly: true,
|
|
||||||
value: '{WEB_APP_URL}/app/high-mobility/connections/add',
|
|
||||||
placeholder: null,
|
|
||||||
description:
|
|
||||||
'When asked to input an OAuth callback or redirect URL in High Mobility OAuth, enter the URL above.',
|
|
||||||
clickToCopy: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'screenName',
|
|
||||||
label: 'Screen Name',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
readOnly: false,
|
|
||||||
value: null,
|
|
||||||
placeholder: null,
|
|
||||||
description:
|
|
||||||
'Screen name of your connection to be used on Automatisch UI.',
|
|
||||||
clickToCopy: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'clientId',
|
|
||||||
label: 'Client ID',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
readOnly: false,
|
|
||||||
value: null,
|
|
||||||
placeholder: null,
|
|
||||||
description: 'Client ID of your High Mobility OAuth app.',
|
|
||||||
clickToCopy: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'clientSecret',
|
|
||||||
label: 'Client Secret',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
readOnly: false,
|
|
||||||
value: null,
|
|
||||||
placeholder: null,
|
|
||||||
description: 'Client Secret of your High Mobility OAuth app.',
|
|
||||||
clickToCopy: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'privateKey',
|
|
||||||
label: 'Private Key',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
readOnly: false,
|
|
||||||
value: null,
|
|
||||||
placeholder: null,
|
|
||||||
description: 'Private Key of your High Mobility OAuth app.',
|
|
||||||
clickToCopy: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'appId',
|
|
||||||
label: 'App ID',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
readOnly: false,
|
|
||||||
value: null,
|
|
||||||
placeholder: null,
|
|
||||||
description: 'App ID of your High Mobility OAuth app.',
|
|
||||||
clickToCopy: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'clientSerialNumber',
|
|
||||||
label: 'Client Serial Number',
|
|
||||||
type: 'string' as const,
|
|
||||||
required: true,
|
|
||||||
readOnly: false,
|
|
||||||
value: null,
|
|
||||||
placeholder: null,
|
|
||||||
description: 'Client Serial Number of your High Mobility OAuth app.',
|
|
||||||
clickToCopy: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
generateAuthUrl,
|
|
||||||
verifyCredentials,
|
|
||||||
isStillVerified,
|
|
||||||
refreshToken,
|
|
||||||
};
|
|
@@ -1,36 +0,0 @@
|
|||||||
import { IGlobalVariable, IField } from '@automatisch/types';
|
|
||||||
import { URLSearchParams } from 'url';
|
|
||||||
|
|
||||||
const verifyCredentials = async ($: IGlobalVariable) => {
|
|
||||||
const oauthRedirectUrlField = $.app.auth.fields.find(
|
|
||||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
|
||||||
);
|
|
||||||
const redirectUri = oauthRedirectUrlField.value as string;
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
client_id: $.auth.data.clientId as string,
|
|
||||||
client_secret: $.auth.data.clientSecret as string,
|
|
||||||
code: $.auth.data.code as string,
|
|
||||||
redirect_uri: redirectUri,
|
|
||||||
grant_type: 'authorization_code',
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await $.http.post(
|
|
||||||
'https://sandbox.api.high-mobility.com/v1/access_tokens',
|
|
||||||
payload
|
|
||||||
);
|
|
||||||
|
|
||||||
const responseData = Object.fromEntries(new URLSearchParams(response.data));
|
|
||||||
|
|
||||||
await $.auth.set({
|
|
||||||
tokenType: responseData.token_type,
|
|
||||||
status: responseData.status,
|
|
||||||
scope: responseData.scope,
|
|
||||||
refreshToken: responseData.refresh_token,
|
|
||||||
expiresIn: responseData.expires_in,
|
|
||||||
accessToken: responseData.access_token,
|
|
||||||
authorizationId: responseData.authorization_id,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default verifyCredentials;
|
|
@@ -1,41 +0,0 @@
|
|||||||
import { TBeforeRequest } from '@automatisch/types';
|
|
||||||
import jwt from 'jsonwebtoken';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
|
|
||||||
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
|
||||||
const { accessToken } = $.auth.data;
|
|
||||||
const { url } = requestConfig;
|
|
||||||
|
|
||||||
if (accessToken && url === '/v1/vehicleinfo') {
|
|
||||||
requestConfig.headers.Authorization = `Bearer ${accessToken}`;
|
|
||||||
return requestConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
version: '3.0',
|
|
||||||
type: 'rest_api',
|
|
||||||
private_key: ($.auth.data.privateKey as string).replaceAll('\\n', '\n'),
|
|
||||||
app_uri: 'https://sandbox.rest-api.high-mobility.com/v5',
|
|
||||||
app_id: $.auth.data.appId as string,
|
|
||||||
client_serial_number: $.auth.data.clientSerialNumber as string,
|
|
||||||
};
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
ver: config.version,
|
|
||||||
aud: config.app_uri,
|
|
||||||
iss: config.client_serial_number,
|
|
||||||
iat: Math.round(Date.now() / 1000),
|
|
||||||
jti: uuidv4(),
|
|
||||||
sub: $.auth.data.accessToken,
|
|
||||||
};
|
|
||||||
|
|
||||||
const priv = Buffer.from(config.private_key, 'utf8');
|
|
||||||
|
|
||||||
const token = jwt.sign(payload, priv, { algorithm: 'ES256' });
|
|
||||||
|
|
||||||
requestConfig.headers.Authorization = `Bearer ${token}`;
|
|
||||||
|
|
||||||
return requestConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default addAuthHeader;
|
|
@@ -1,13 +0,0 @@
|
|||||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
const getVehicleInfo = async ($: IGlobalVariable): Promise<IJSONObject> => {
|
|
||||||
const response = await $.http.get(
|
|
||||||
'https://sandbox.api.high-mobility.com/v1/vehicleinfo'
|
|
||||||
);
|
|
||||||
|
|
||||||
const currentVehicle = response.data;
|
|
||||||
|
|
||||||
return currentVehicle;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getVehicleInfo;
|
|
@@ -1,18 +0,0 @@
|
|||||||
import defineApp from '../../helpers/define-app';
|
|
||||||
import addAuthHeader from './common/add-auth-header';
|
|
||||||
import auth from './auth';
|
|
||||||
import actions from './actions';
|
|
||||||
|
|
||||||
export default defineApp({
|
|
||||||
name: 'High Mobility',
|
|
||||||
key: 'high-mobility',
|
|
||||||
iconUrl: '{BASE_URL}/apps/high-mobility/assets/favicon.svg',
|
|
||||||
authDocUrl: 'https://automatisch.io/docs/apps/high-mobility/connection',
|
|
||||||
supportsConnections: true,
|
|
||||||
baseUrl: 'https://high-mobility.com',
|
|
||||||
apiBaseUrl: 'https://api.high-mobility.com',
|
|
||||||
primaryColor: '000000',
|
|
||||||
beforeRequest: [addAuthHeader],
|
|
||||||
auth,
|
|
||||||
actions,
|
|
||||||
});
|
|
@@ -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,
|
||||||
|
};
|
@@ -1,9 +1,10 @@
|
|||||||
import { IGlobalVariable } from '@automatisch/types';
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
import getVehicleInfo from '../common/get-vehicle-info';
|
import verifyCredentials from './verify-credentials';
|
||||||
|
|
||||||
const isStillVerified = async ($: IGlobalVariable) => {
|
const isStillVerified = async ($: IGlobalVariable) => {
|
||||||
const user = await getVehicleInfo($);
|
await verifyCredentials($);
|
||||||
return !!user;
|
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default isStillVerified;
|
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;
|
||||||
|
},
|
||||||
|
};
|
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 |
@@ -6,14 +6,13 @@ export default async function generateAuthUrl($: IGlobalVariable) {
|
|||||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
(field: IField) => field.key == 'oAuthRedirectUrl'
|
||||||
);
|
);
|
||||||
const redirectUri = oauthRedirectUrlField.value as string;
|
const redirectUri = oauthRedirectUrlField.value as string;
|
||||||
|
|
||||||
const searchParams = new URLSearchParams({
|
const searchParams = new URLSearchParams({
|
||||||
response_type: 'code',
|
response_type: 'code',
|
||||||
client_id: $.auth.data.clientId as string,
|
client_id: $.auth.data.clientId as string,
|
||||||
redirect_uri: redirectUri,
|
redirect_uri: redirectUri,
|
||||||
});
|
});
|
||||||
|
|
||||||
const url = `https://sandbox.owner-panel.high-mobility.com/oauth/new?${searchParams.toString()}`;
|
const url = `https://miro.com/oauth/authorize?${searchParams.toString()}`;
|
||||||
|
|
||||||
await $.auth.set({
|
await $.auth.set({
|
||||||
url,
|
url,
|
@@ -1,45 +1,48 @@
|
|||||||
|
import generateAuthUrl from './generate-auth-url';
|
||||||
import verifyCredentials from './verify-credentials';
|
import verifyCredentials from './verify-credentials';
|
||||||
|
import refreshToken from './refresh-token';
|
||||||
import isStillVerified from './is-still-verified';
|
import isStillVerified from './is-still-verified';
|
||||||
// import refreshToken from './refresh-token';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
key: 'screenName',
|
key: 'oAuthRedirectUrl',
|
||||||
label: 'Screen Name',
|
label: 'OAuth Redirect URL',
|
||||||
type: 'string' as const,
|
type: 'string' as const,
|
||||||
required: true,
|
required: true,
|
||||||
readOnly: false,
|
readOnly: true,
|
||||||
value: null,
|
value: '{WEB_APP_URL}/app/miro/connections/add',
|
||||||
placeholder: null,
|
placeholder: null,
|
||||||
description:
|
description:
|
||||||
'Screen name of your connection to be used on Automatisch UI.',
|
'When asked to input a redirect URL in Miro, enter the URL above.',
|
||||||
clickToCopy: false,
|
clickToCopy: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'privateKey',
|
key: 'clientId',
|
||||||
label: 'Private Key',
|
label: 'Client ID',
|
||||||
type: 'string' as const,
|
type: 'string' as const,
|
||||||
required: true,
|
required: true,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
value: null,
|
value: null,
|
||||||
placeholder: null,
|
placeholder: null,
|
||||||
description: 'Private Key of your High Mobility OAuth app.',
|
description: null,
|
||||||
clickToCopy: false,
|
clickToCopy: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'applicationId',
|
key: 'clientSecret',
|
||||||
label: 'Application ID',
|
label: 'Client Secret',
|
||||||
type: 'string' as const,
|
type: 'string' as const,
|
||||||
required: true,
|
required: true,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
value: null,
|
value: null,
|
||||||
placeholder: null,
|
placeholder: null,
|
||||||
description: 'App ID of your High Mobility OAuth app.',
|
description: null,
|
||||||
clickToCopy: false,
|
clickToCopy: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
generateAuthUrl,
|
||||||
verifyCredentials,
|
verifyCredentials,
|
||||||
// isStillVerified,
|
isStillVerified,
|
||||||
// refreshToken,
|
refreshToken,
|
||||||
};
|
};
|
@@ -2,8 +2,8 @@ import { IGlobalVariable } from '@automatisch/types';
|
|||||||
import getCurrentUser from '../common/get-current-user';
|
import getCurrentUser from '../common/get-current-user';
|
||||||
|
|
||||||
const isStillVerified = async ($: IGlobalVariable) => {
|
const isStillVerified = async ($: IGlobalVariable) => {
|
||||||
const user = await getCurrentUser($);
|
const currentUser = await getCurrentUser($);
|
||||||
return !!user;
|
return !!currentUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default isStillVerified;
|
export default isStillVerified;
|
@@ -1,26 +1,22 @@
|
|||||||
|
import { URLSearchParams } from 'node:url';
|
||||||
import { IGlobalVariable } from '@automatisch/types';
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
|
|
||||||
const refreshToken = async ($: IGlobalVariable) => {
|
const refreshToken = async ($: IGlobalVariable) => {
|
||||||
const payload = {
|
const params = new URLSearchParams({
|
||||||
|
grant_type: 'refresh_token',
|
||||||
client_id: $.auth.data.clientId as string,
|
client_id: $.auth.data.clientId as string,
|
||||||
client_secret: $.auth.data.clientSecret as string,
|
client_secret: $.auth.data.clientSecret as string,
|
||||||
refresh_token: $.auth.data.refreshToken as string,
|
refresh_token: $.auth.data.refreshToken as string,
|
||||||
grant_type: 'refresh_token',
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const { data } = await $.http.post(
|
const { data } = await $.http.post('/v1/oauth/token', params.toString());
|
||||||
'https://sandbox.api.high-mobility.com/v1/access_tokens',
|
|
||||||
payload
|
|
||||||
);
|
|
||||||
|
|
||||||
await $.auth.set({
|
await $.auth.set({
|
||||||
tokenType: data.token_type,
|
|
||||||
status: data.status,
|
|
||||||
scope: data.scope,
|
|
||||||
refreshToken: data.refresh_token,
|
|
||||||
expiresIn: data.expires_in,
|
|
||||||
accessToken: data.access_token,
|
accessToken: data.access_token,
|
||||||
authorizationId: data.authorization_id,
|
expiresIn: data.expires_in,
|
||||||
|
refreshToken: data.refresh_token,
|
||||||
|
scope: data.scope,
|
||||||
|
tokenType: data.token_type,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
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;
|
||||||
|
},
|
||||||
|
};
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user