Add Activepieces integration for workflow automation
- Add Activepieces fork with SmoothSchedule custom piece - Create integrations app with Activepieces service layer - Add embed token endpoint for iframe integration - Create Automations page with embedded workflow builder - Add sidebar visibility fix for embed mode - Add list inactive customers endpoint to Public API - Include SmoothSchedule triggers: event created/updated/cancelled - Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpRequest,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const addWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'add_worksheet',
|
||||
description: 'Add a worksheet to a workbook',
|
||||
displayName: 'Add a Worksheet to a Workbook',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_name: Property.ShortText({
|
||||
displayName: 'Worksheet Name',
|
||||
description: 'The name of the new worksheet',
|
||||
required: false,
|
||||
defaultValue: 'Sheet',
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbook_id = propsValue['workbook_id'];
|
||||
const worksheet_name = propsValue['worksheet_name'];
|
||||
|
||||
const request: HttpRequest = {
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets`,
|
||||
body: {
|
||||
name: worksheet_name,
|
||||
},
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpRequest,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon, objectToArray } from '../common/common';
|
||||
|
||||
export const appendRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'append_row',
|
||||
description: 'Append row of values to a worksheet',
|
||||
displayName: 'Append Row to Worksheet',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
first_row_headers: Property.Checkbox({
|
||||
displayName: 'Does the first row contain headers?',
|
||||
description: 'If the first row is headers',
|
||||
required: true,
|
||||
defaultValue: false,
|
||||
}),
|
||||
values: excelCommon.values,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const values = propsValue.first_row_headers
|
||||
? objectToArray(propsValue['values'])
|
||||
: Object.values(propsValue['values'])[0];
|
||||
|
||||
const lastUsedRow = await excelCommon.getLastUsedRow(
|
||||
workbookId,
|
||||
worksheetId,
|
||||
auth['access_token'],
|
||||
);
|
||||
const lastUsedColumn = excelCommon.numberToColumnName(Object.values(values).length);
|
||||
|
||||
const rangeFrom = `A${lastUsedRow + 1}`;
|
||||
const rangeTo = `${lastUsedColumn}${lastUsedRow + 1}`;
|
||||
|
||||
const url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/range(address='${rangeFrom}:${rangeTo}')`;
|
||||
|
||||
const requestBody = {
|
||||
values: [values],
|
||||
};
|
||||
|
||||
const request: HttpRequest = {
|
||||
method: HttpMethod.PATCH,
|
||||
url: url,
|
||||
body: requestBody,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../..';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const appendTableRowsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'append_table_rows',
|
||||
description: 'Append rows to a table',
|
||||
displayName: 'Append Rows to a Table',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
values: excelCommon.table_values,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table_id'];
|
||||
const valuesToAppend = [Object.values(propsValue['values'])];
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/rows`,
|
||||
body: {
|
||||
values: valuesToAppend,
|
||||
},
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const clearRangeAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'clear_range',
|
||||
displayName: 'Clear Cells by Range',
|
||||
description: 'Clear a block of cells (range) content or formatting.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description:
|
||||
'The range of cells to clear, in A1 notation (e.g., "A1:C5").',
|
||||
required: true
|
||||
}),
|
||||
applyTo: Property.StaticDropdown({
|
||||
displayName: 'Clear Type',
|
||||
description: 'Specify what to clear from the range.',
|
||||
required: true,
|
||||
defaultValue: 'All',
|
||||
options: {
|
||||
options: [
|
||||
{
|
||||
label: 'All (Contents and Formatting)',
|
||||
value: 'All'
|
||||
},
|
||||
{
|
||||
label: 'Contents Only',
|
||||
value: 'Contents'
|
||||
},
|
||||
{
|
||||
label: 'Formats Only',
|
||||
value: 'Formats'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, range, applyTo } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
if (!/^[A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?$/.test(range as string)) {
|
||||
throw new Error('Invalid range format. Please use A1 notation (e.g., "A1" or "A1:C5").');
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/range(address='${range}')/clear`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
applyTo: applyTo
|
||||
}
|
||||
});
|
||||
|
||||
// A successful request returns a 200 OK with no body.
|
||||
return response.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const clearColumnAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'clear_column',
|
||||
displayName: 'Clear Column by Index',
|
||||
description: 'Clear contents/formatting of a column by its index.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
column_index: Property.Number({
|
||||
displayName: 'Column Index',
|
||||
description:
|
||||
'The 1-based index of the column to be cleared (e.g., 1 for column A, 2 for column B).',
|
||||
required: true
|
||||
}),
|
||||
applyTo: Property.StaticDropdown({
|
||||
displayName: 'Clear Type',
|
||||
description: 'Specify what to clear from the column.',
|
||||
required: true,
|
||||
defaultValue: 'All',
|
||||
options: {
|
||||
options: [
|
||||
{
|
||||
label: 'All (Contents and Formatting)',
|
||||
value: 'All'
|
||||
},
|
||||
{
|
||||
label: 'Contents Only',
|
||||
value: 'Contents'
|
||||
},
|
||||
{
|
||||
label: 'Formats Only',
|
||||
value: 'Formats'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, column_index, applyTo } =
|
||||
context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
if (
|
||||
typeof column_index !== 'number' ||
|
||||
!Number.isInteger(column_index) ||
|
||||
column_index < 1
|
||||
) {
|
||||
throw new Error('Column index must be a positive integer.');
|
||||
}
|
||||
|
||||
// Convert 1-based index to Excel column letter (e.g., 1 -> 'A')
|
||||
const columnLetter = excelCommon.numberToColumnName(column_index);
|
||||
|
||||
// Construct the range address for the entire column, e.g., 'C:C'
|
||||
const columnAddress = `${columnLetter}:${columnLetter}`;
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/range(address='${columnAddress}')/clear`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
applyTo: applyTo
|
||||
}
|
||||
});
|
||||
|
||||
// A successful request returns a 200 OK with no body.
|
||||
return response.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod, AuthenticationType } from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const clearRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'clear_row',
|
||||
displayName: 'Clear Row by ID',
|
||||
description: 'Clear contents/formatting of an entire row by its ID.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
row_id: Property.Number({
|
||||
displayName: 'Row Number',
|
||||
description: 'The number of the row to be cleared (e.g., 5 for the 5th row).',
|
||||
required: true,
|
||||
}),
|
||||
applyTo: Property.StaticDropdown({
|
||||
displayName: "Clear Type",
|
||||
description: "Specify what to clear from the row.",
|
||||
required: true,
|
||||
defaultValue: 'All',
|
||||
options: {
|
||||
options: [
|
||||
{
|
||||
label: 'All (Contents and Formatting)',
|
||||
value: 'All'
|
||||
},
|
||||
{
|
||||
label: 'Contents Only',
|
||||
value: 'Contents'
|
||||
},
|
||||
{
|
||||
label: 'Formats Only',
|
||||
value: 'Formats'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, row_id, applyTo } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
if (typeof row_id !== 'number' || !Number.isInteger(row_id) || row_id < 1) {
|
||||
throw new Error('Row index must be a positive integer.');
|
||||
}
|
||||
|
||||
|
||||
// Construct the range address for the entire row, e.g., '5:5'
|
||||
const rowAddress = `${row_id}:${row_id}`;
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/range(address='${rowAddress}')/clear`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token,
|
||||
},
|
||||
body: {
|
||||
applyTo: applyTo,
|
||||
},
|
||||
});
|
||||
|
||||
// A successful request returns a 200 OK with no body.
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const clearWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'clear_worksheet',
|
||||
description: 'Clear a worksheet',
|
||||
displayName: 'Clear Worksheet',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description:
|
||||
'The range in A1 notation (e.g., A2:B2) to clear in the worksheet, if not provided, clear the entire worksheet',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const range = propsValue['range'];
|
||||
|
||||
let url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/`;
|
||||
|
||||
// If range is not provided, clear the entire worksheet
|
||||
if (!range) {
|
||||
url += 'usedRange(valuesOnly=true)/clear';
|
||||
} else {
|
||||
url += `range(address = '${range}')/clear`;
|
||||
}
|
||||
|
||||
const request = {
|
||||
method: HttpMethod.POST,
|
||||
url: url,
|
||||
body: {
|
||||
applyTo: 'contents',
|
||||
},
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN as const,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../../index';
|
||||
|
||||
export const convertToRangeAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'convert_to_range',
|
||||
description: 'Converts a table to a range',
|
||||
displayName: 'Convert to Range',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table_id'];
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/convertToRange`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const createTableAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'create_table',
|
||||
description: 'Create a table in a worksheet',
|
||||
displayName: 'Create Table',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
selectRange: Property.Dropdown({
|
||||
auth: excelAuth,
|
||||
displayName: 'Select Range',
|
||||
description: 'How to select the range for the table',
|
||||
required: true,
|
||||
options: async () => {
|
||||
return {
|
||||
disabled: false,
|
||||
options: [
|
||||
{
|
||||
label: 'Automatically',
|
||||
value: 'auto',
|
||||
},
|
||||
{
|
||||
label: 'Manually',
|
||||
value: 'manual',
|
||||
},
|
||||
],
|
||||
defaultValue: 'auto',
|
||||
};
|
||||
},
|
||||
refreshers: [],
|
||||
}),
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description:
|
||||
'The range of cells in A1 notation (e.g., A2:B2) that will be converted to a table',
|
||||
required: false,
|
||||
defaultValue: 'A1:B2',
|
||||
}),
|
||||
hasHeaders: Property.Checkbox({
|
||||
displayName: 'Has Headers',
|
||||
description: 'Whether the range has column labels',
|
||||
required: true,
|
||||
defaultValue: true,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const selectRange = propsValue['selectRange'];
|
||||
const hasHeaders = propsValue['hasHeaders'];
|
||||
|
||||
let range: string | undefined;
|
||||
if (selectRange === 'auto') {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/usedRange`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
queryParams: {
|
||||
select: 'address',
|
||||
},
|
||||
});
|
||||
range = response.body['address'].split('!')[1];
|
||||
} else {
|
||||
range = propsValue['range'];
|
||||
}
|
||||
|
||||
const result = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/add`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
body: {
|
||||
address: range,
|
||||
hasHeaders,
|
||||
},
|
||||
});
|
||||
|
||||
return result.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
export const createWorkbook = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'createWorkbook',
|
||||
displayName: 'Create Workbook',
|
||||
description: 'Create a new workbook at the specified location',
|
||||
props: {
|
||||
name: Property.ShortText({
|
||||
displayName: "Name",
|
||||
description: "The name of the new workbook",
|
||||
required: true
|
||||
}),
|
||||
parentFolder: excelCommon.parent_folder
|
||||
},
|
||||
async run(context) {
|
||||
const { name, parentFolder } = context.propsValue
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/${parentFolder === 'root' ? '' : 'items/'}${parentFolder}/children`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: context.auth['access_token'],
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: {
|
||||
file: {},
|
||||
name: name.endsWith('.xlsx') ? name : `${name}.xlsx`,
|
||||
'@microsoft.graph.conflictBehavior': 'rename'
|
||||
}
|
||||
})
|
||||
|
||||
return response
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,102 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
// Define the response type for creating a worksheet for better type-safety
|
||||
interface CreateWorksheetResponse {
|
||||
id: string;
|
||||
name: string;
|
||||
position: number;
|
||||
visibility: string;
|
||||
}
|
||||
|
||||
export const createWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'create_worksheet',
|
||||
displayName: 'Create Worksheet',
|
||||
description:
|
||||
'Add a new worksheet (tab) to an existing workbook with optional default headers.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
name: Property.ShortText({
|
||||
displayName: 'Worksheet Name',
|
||||
description:
|
||||
"The name for the new worksheet. If not provided, a default name like 'Sheet1' will be assigned.",
|
||||
required: false
|
||||
}),
|
||||
headers: Property.Array({
|
||||
displayName: 'Headers',
|
||||
description:
|
||||
'Optional: A list of headers to add to the first row. A table will be created from these headers.',
|
||||
required: false
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, name, headers } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
// Step 1: Create the new worksheet
|
||||
const createWorksheetResponse =
|
||||
await httpClient.sendRequest<CreateWorksheetResponse>({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/add`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
// Conditionally add the name property to the request body if it exists
|
||||
...(name ? { name } : {})
|
||||
}
|
||||
});
|
||||
|
||||
const newWorksheetName = createWorksheetResponse.body.name;
|
||||
|
||||
// Step 2: If headers are provided, add them and create a table from them
|
||||
if (headers && Array.isArray(headers) && headers.length > 0) {
|
||||
const headersArray = headers as string[];
|
||||
|
||||
// Calculate the table range, e.g., "A1:C1" for 3 headers
|
||||
const endColumn = excelCommon.numberToColumnName(headersArray.length);
|
||||
const address = `A1:${endColumn}1`;
|
||||
|
||||
// Add the header values to the first row of the new worksheet
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.PATCH,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${newWorksheetName}/range(address='${address}')`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
values: [headersArray] // Values must be a 2D array
|
||||
}
|
||||
});
|
||||
|
||||
// Create a table from the newly added header range
|
||||
const createTableResponse = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${newWorksheetName}/tables/add`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
address: address,
|
||||
hasHeaders: true
|
||||
}
|
||||
});
|
||||
|
||||
// Return the result of the table creation
|
||||
return createTableResponse.body;
|
||||
}
|
||||
|
||||
// If no headers were provided, return the result of the worksheet creation
|
||||
return createWorksheetResponse.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const deleteTableAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'delete_table',
|
||||
description: 'Delete a table from a worksheet',
|
||||
displayName: 'Delete Table',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table_id'];
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.DELETE,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpRequest,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const deleteWorkbookAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'delete_workbook',
|
||||
description: 'Delete a workbook',
|
||||
displayName: 'Delete Workbook',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const accessToken = auth['access_token'];
|
||||
|
||||
const request: HttpRequest = {
|
||||
method: HttpMethod.DELETE,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: accessToken,
|
||||
},
|
||||
};
|
||||
|
||||
await httpClient.sendRequest(request);
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const deleteWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'delete_worksheet',
|
||||
description: 'Delete a worksheet in a workbook',
|
||||
displayName: 'Delete Worksheet',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
|
||||
const request = {
|
||||
method: HttpMethod.DELETE,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN as const,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,121 @@
|
||||
import {
|
||||
createAction,
|
||||
Property,
|
||||
OAuth2PropertyValue
|
||||
} from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const findRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'find_row',
|
||||
displayName: 'Find Row',
|
||||
description:
|
||||
'Locate a row by specifying a lookup column and value (e.g. find a row where “ID” = 123).',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
lookup_column: Property.Dropdown({
|
||||
auth: excelAuth,
|
||||
displayName: 'Lookup Column',
|
||||
description: 'The column to search in.',
|
||||
required: true,
|
||||
refreshers: ['workbook_id', 'table_id'],
|
||||
options: async ({ auth, workbook_id, table_id }) => {
|
||||
if (!auth || !workbook_id || !table_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please select a workbook and table first.'
|
||||
};
|
||||
}
|
||||
const authProp = auth as OAuth2PropertyValue;
|
||||
const response = await httpClient.sendRequest<{
|
||||
value: { id: string; name: string }[];
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/columns`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: authProp.access_token
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: response.body.value.map((column) => ({
|
||||
label: column.name,
|
||||
value: column.id
|
||||
}))
|
||||
};
|
||||
}
|
||||
}),
|
||||
lookup_value: Property.ShortText({
|
||||
displayName: 'Lookup Value',
|
||||
description: 'The value to find in the lookup column.',
|
||||
required: true
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, table_id, lookup_column, lookup_value } =
|
||||
context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
const columnId = lookup_column;
|
||||
|
||||
const sanitizedValue = (lookup_value as string).replace(/'/g, "''");
|
||||
|
||||
// Define the URL to clear the filter, which will be used in the 'finally' block
|
||||
const clearFilterUrl = `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/columns/${columnId}/filter/clear`;
|
||||
|
||||
try {
|
||||
// Step 1: Apply the filter to the specified column
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/columns/${columnId}/filter/apply`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
criteria: {
|
||||
criterion1: `=${sanitizedValue}`,
|
||||
filterOn: 'Custom'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Step 2: Get the visible rows (i.e., the filtered results)
|
||||
const foundRowsResponse = await httpClient.sendRequest<{
|
||||
value: unknown[];
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/range/visibleView/rows`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
}
|
||||
});
|
||||
|
||||
// The result is the array of rows that matched the filter
|
||||
return foundRowsResponse.body.value;
|
||||
} finally {
|
||||
// Step 3: Clear the filter to restore the table to its original state.
|
||||
// This runs regardless of whether the previous steps succeeded or failed.
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: clearFilterUrl,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {} // Clear action does not require a body
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const getRangeAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_range',
|
||||
displayName: 'Get Cells in Range',
|
||||
description: 'Retrieve the values in a given cell range (e.g., “A1:C10”).',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description:
|
||||
'The range of cells to retrieve, in A1 notation (e.g., "A1:C10").',
|
||||
required: true
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, range } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
if (!/^[A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?$/.test(range as string)) {
|
||||
throw new Error(
|
||||
'Invalid range format. Please use A1 notation (e.g., "A1" or "A1:C5").'
|
||||
);
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/range(address='${range}')`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
}
|
||||
});
|
||||
|
||||
// The response body contains the workbookRange object with details
|
||||
// like values, text, formulas, rowCount, etc.
|
||||
return response.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpError
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
export const getRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'getRowById',
|
||||
displayName: 'Get Row by ID',
|
||||
description: ' Retrieve the entire content of a row by its row ID.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
row_id: Property.Number({
|
||||
displayName: 'Row ID (Index)',
|
||||
description:
|
||||
'The zero-based index of the row to retrieve (e.g., 0 for the first row, 1 for the second).',
|
||||
required: true
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, table_id, row_id } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
const maxRetries = 3;
|
||||
let attempt = 0;
|
||||
|
||||
while (attempt < maxRetries) {
|
||||
try {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/rows/itemAt(index=${row_id})`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
}
|
||||
});
|
||||
return response.body;
|
||||
} catch (error) {
|
||||
const httpError = error as HttpError;
|
||||
if (httpError.response?.status === 503 && attempt < maxRetries - 1) {
|
||||
const delayMs = 2 ** attempt * 1000;
|
||||
console.warn(
|
||||
`Excel API is unavailable (503). Retrying after ${delayMs}ms... (Attempt ${
|
||||
attempt + 1
|
||||
}/${maxRetries})`
|
||||
);
|
||||
await delay(delayMs);
|
||||
attempt++;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
'Failed to retrieve row after multiple retries due to API unavailability.'
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../..';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
export const getTableColumnsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_table_columns',
|
||||
description: 'List columns of a table in a worksheet',
|
||||
displayName: 'Get Table Columns',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table: excelCommon.table_id,
|
||||
limit: Property.Number({
|
||||
displayName: 'Limit',
|
||||
description: 'Limit the number of columns retrieved',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table'];
|
||||
const limit = propsValue['limit'];
|
||||
|
||||
let url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/columns`;
|
||||
|
||||
if (limit) {
|
||||
url += `?$top=${limit}`;
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: url,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const columnNames = response.body['value'].map(
|
||||
(column: { name: any }) => column.name
|
||||
);
|
||||
|
||||
return columnNames;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../..';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
export const getTableRowsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_table_rows',
|
||||
description: 'List rows of a table in a worksheet',
|
||||
displayName: 'Get Table Rows',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table: excelCommon.table_id,
|
||||
limit: Property.Number({
|
||||
displayName: 'Limit',
|
||||
description: 'Limit the number of rows retrieved',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table'];
|
||||
const limit = propsValue['limit'];
|
||||
|
||||
let url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/rows`;
|
||||
|
||||
if (limit) {
|
||||
url += `?$top=${limit}`;
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: url,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const rowsValues = response.body['value'].map(
|
||||
(row: { values: any[] }) => row.values[0]
|
||||
);
|
||||
|
||||
return rowsValues;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const getWorkbooksAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_workbooks',
|
||||
description: 'Retrieve a list of workbooks',
|
||||
displayName: 'Get Workbooks',
|
||||
props: {
|
||||
limit: Property.Number({
|
||||
displayName: 'Limit',
|
||||
description:
|
||||
'Limits the number of workbooks returned, returns all workbooks if empty',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const limit = propsValue['limit'];
|
||||
|
||||
const queryParams: any = {
|
||||
$filter:
|
||||
"file ne null and file/mimeType eq 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'",
|
||||
};
|
||||
|
||||
if (limit !== null && limit !== undefined) {
|
||||
queryParams.$top = limit.toString();
|
||||
}
|
||||
|
||||
const request = {
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/root/search(q='.xlsx')`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN as const,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
queryParams: queryParams,
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
const workbooks = response.body['value'].map(
|
||||
(item: { id: any; name: any; webUrl: any }) => ({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
webUrl: item.webUrl,
|
||||
})
|
||||
);
|
||||
|
||||
return workbooks;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod, AuthenticationType } from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const getWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_worksheet',
|
||||
displayName: 'Get Worksheet by ID',
|
||||
description: 'Retrieve metadata of a worksheet by its ID.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id, // This dropdown provides the worksheet name as its value
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
// The worksheet_id prop from excelCommon returns the worksheet's name,
|
||||
// which can be used to identify it in the API URL as per the documentation ({id|name}).
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token,
|
||||
},
|
||||
});
|
||||
|
||||
// The response body contains the workbookWorksheet object with its metadata.
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../../index';
|
||||
|
||||
export const getWorksheetRowsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_worksheet_rows',
|
||||
description: 'Retrieve rows from a worksheet',
|
||||
displayName: 'Get Worksheet Rows',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description: 'Range of the rows to retrieve (e.g., A2:B2)',
|
||||
required: false,
|
||||
}),
|
||||
headerRow: Property.Number({
|
||||
displayName: 'Header Row',
|
||||
description: 'Row number of the header',
|
||||
required: false,
|
||||
}),
|
||||
firstDataRow: Property.Number({
|
||||
displayName: 'First Data Row',
|
||||
description: 'Row number of the first data row',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const range = propsValue['range'];
|
||||
const headerRow = propsValue['headerRow'];
|
||||
const firstDataRow = propsValue['firstDataRow'];
|
||||
|
||||
let url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/`;
|
||||
|
||||
if (!range) {
|
||||
url += 'usedRange(valuesOnly=true)';
|
||||
} else {
|
||||
url += `range(address = '${range}')`;
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: url,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const rows = response.body['values'];
|
||||
if (headerRow && firstDataRow) {
|
||||
return rows.slice(firstDataRow - 1).map((row: any[]) => {
|
||||
const obj: { [key: string]: any } = {};
|
||||
rows[headerRow - 1].forEach(
|
||||
(header: any, colIndex: string | number) => {
|
||||
obj[String(header)] = row[Number(colIndex)];
|
||||
}
|
||||
);
|
||||
return obj;
|
||||
});
|
||||
}
|
||||
|
||||
return rows;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const getWorksheetsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_worksheets',
|
||||
description: 'Retrieve worksheets from a workbook',
|
||||
displayName: 'Get Worksheets',
|
||||
props: {
|
||||
workbook: excelCommon.workbook_id,
|
||||
returnAll: Property.Checkbox({
|
||||
displayName: 'Return All',
|
||||
description: 'If checked, all worksheets will be returned',
|
||||
required: false,
|
||||
defaultValue: false,
|
||||
}),
|
||||
limit: Property.Number({
|
||||
displayName: 'Limit',
|
||||
description: 'Limit the number of worksheets returned',
|
||||
required: false,
|
||||
defaultValue: 10,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook'];
|
||||
const returnAll = propsValue['returnAll'];
|
||||
const limit = propsValue['limit'];
|
||||
|
||||
const endpoint = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets`;
|
||||
const headers = {
|
||||
Authorization: `Bearer ${auth['access_token']}`,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: endpoint,
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Failed to retrieve worksheet: ${response.body}`);
|
||||
}
|
||||
|
||||
const worksheets = response.body['value'];
|
||||
|
||||
if (returnAll) {
|
||||
return worksheets;
|
||||
} else {
|
||||
const limitedWorksheets = [];
|
||||
for (let i = 0; i < Math.min(worksheets['length'], limit ?? 0); i++) {
|
||||
limitedWorksheets.push(worksheets[i]);
|
||||
}
|
||||
return limitedWorksheets;
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../..';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const lookupTableColumnAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'lookup_table_column',
|
||||
description: 'Lookup a value in a table column in a worksheet',
|
||||
displayName: 'Lookup Table Column',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
lookup_column: Property.ShortText({
|
||||
displayName: 'Lookup Column',
|
||||
description: 'The column name to lookup the value in',
|
||||
required: true,
|
||||
}),
|
||||
lookup_value: Property.ShortText({
|
||||
displayName: 'Lookup Value',
|
||||
description: 'The value to lookup',
|
||||
required: true,
|
||||
}),
|
||||
return_all_matches: Property.Checkbox({
|
||||
displayName: 'Return All Matches',
|
||||
description: 'If checked, all matching rows will be returned',
|
||||
required: false,
|
||||
defaultValue: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableName = propsValue['table_id'];
|
||||
const lookupColumn = propsValue['lookup_column'];
|
||||
const lookupValue = propsValue['lookup_value'];
|
||||
const returnAllMatches = propsValue['return_all_matches'];
|
||||
|
||||
const rowsUrl = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableName}/rows`;
|
||||
const rowsResponse = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: rowsUrl,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const columnsUrl = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableName}/columns`;
|
||||
const columnsResponse = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: columnsUrl,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const columns = columnsResponse.body['value'];
|
||||
const columnIndex = columns.findIndex(
|
||||
(column: any) => column.name === lookupColumn
|
||||
);
|
||||
|
||||
if (columnIndex === -1) {
|
||||
throw new Error(`Column "${lookupColumn}" not found in the table.`);
|
||||
}
|
||||
|
||||
const rows = rowsResponse.body['value'];
|
||||
const matchedRows = rows.filter(
|
||||
(row: any) => row.values[0][columnIndex] === lookupValue
|
||||
);
|
||||
|
||||
const matchedValues = matchedRows.map(
|
||||
(row: { values: any[] }) => row.values[0]
|
||||
);
|
||||
|
||||
if (returnAllMatches) {
|
||||
return matchedValues;
|
||||
} else {
|
||||
return matchedValues[0] || null;
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
const namingRules = `
|
||||
The new name for the worksheet. The name must adhere to the following rules:
|
||||
- Cannot be blank.
|
||||
- Cannot exceed 31 characters.
|
||||
- Must not contain any of the following characters: \`/\`, \`\\\`, \`?\`, \`*\`, \`:\`, \`[\`, \`]\`.
|
||||
- The name "History" is reserved by Excel and cannot be used.
|
||||
`;
|
||||
|
||||
export const renameWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'rename_worksheet',
|
||||
displayName: 'Rename Worksheet',
|
||||
description: 'Change the name of an existing worksheet.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
new_name: Property.ShortText({
|
||||
displayName: 'New Worksheet Name',
|
||||
description: namingRules,
|
||||
required: true
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, new_name } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
// The worksheet_id prop from excelCommon returns the worksheet's current name,
|
||||
// which can be used to identify it in the API URL.
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.PATCH,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
name: new_name
|
||||
}
|
||||
});
|
||||
|
||||
return response.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod, AuthenticationType } from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon, objectToArray } from '../common/common';
|
||||
|
||||
export const updateRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'update_row',
|
||||
description: 'Update a row in a worksheet',
|
||||
displayName: 'Update Worksheet Rows',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
row_number: Property.Number({
|
||||
displayName: 'Row number',
|
||||
description: 'The row number to update',
|
||||
required: true,
|
||||
}),
|
||||
first_row_headers: Property.Checkbox({
|
||||
displayName: 'Does the first row contain headers?',
|
||||
description: 'If the first row is headers',
|
||||
required: true,
|
||||
defaultValue: false,
|
||||
}),
|
||||
values: excelCommon.values,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const rowNumber = propsValue['row_number'];
|
||||
const values = propsValue.first_row_headers
|
||||
? objectToArray(propsValue['values'])
|
||||
: Object.values(propsValue['values']);
|
||||
|
||||
const requestBody = {
|
||||
values: [values],
|
||||
};
|
||||
|
||||
const lastUsedColumn = excelCommon.numberToColumnName(Object.values(values).length);
|
||||
|
||||
const rangeFrom = `A${rowNumber}`;
|
||||
const rangeTo = `${lastUsedColumn}${rowNumber}`;
|
||||
|
||||
const request = {
|
||||
method: HttpMethod.PATCH,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/range(address='${rangeFrom}:${rangeTo}')`,
|
||||
body: requestBody,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN as const,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,407 @@
|
||||
import { Property, OAuth2PropertyValue } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpRequest
|
||||
} from '@activepieces/pieces-common';
|
||||
import { isNil } from '@activepieces/shared';
|
||||
import { excelAuth } from '../..';
|
||||
|
||||
export const excelCommon = {
|
||||
baseUrl: 'https://graph.microsoft.com/v1.0/me/drive',
|
||||
workbook_id: Property.Dropdown({
|
||||
auth: excelAuth,
|
||||
displayName: 'Workbook',
|
||||
required: true,
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please authenticate first'
|
||||
};
|
||||
}
|
||||
const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue;
|
||||
const workbooks: { id: string; name: string }[] = (
|
||||
await httpClient.sendRequest<{ value: { id: string; name: string }[] }>(
|
||||
{
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/root/search(q='.xlsx')?$select=id,name`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: authProp['access_token']
|
||||
}
|
||||
}
|
||||
)
|
||||
).body.value;
|
||||
return {
|
||||
disabled: false,
|
||||
options: workbooks.map((workbook: { id: string; name: string }) => {
|
||||
return {
|
||||
label: workbook.name,
|
||||
value: workbook.id
|
||||
};
|
||||
})
|
||||
};
|
||||
},
|
||||
refreshers: []
|
||||
}),
|
||||
worksheet_id: Property.Dropdown({
|
||||
auth: excelAuth,
|
||||
displayName: 'Worksheet',
|
||||
required: true,
|
||||
refreshers: ['workbook_id'],
|
||||
options: async ({ auth, workbook_id }) => {
|
||||
if (!auth || !workbook_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please select a workbook first'
|
||||
};
|
||||
}
|
||||
const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue;
|
||||
const worksheets: { id: string; name: string }[] = (
|
||||
await httpClient.sendRequest<{ value: { id: string; name: string }[] }>(
|
||||
{
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets?$select=id,name`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: authProp['access_token']
|
||||
}
|
||||
}
|
||||
)
|
||||
).body.value;
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: worksheets.map((worksheet: { id: string; name: string }) => {
|
||||
return {
|
||||
label: worksheet.name,
|
||||
value: worksheet.name
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
}),
|
||||
table_id: Property.Dropdown({
|
||||
auth: excelAuth,
|
||||
displayName: 'Table',
|
||||
required: true,
|
||||
refreshers: ['workbook_id', 'worksheet_id'],
|
||||
options: async ({ auth, workbook_id, worksheet_id }) => {
|
||||
if (!auth || !workbook_id || !worksheet_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please select a workbook and worksheet first'
|
||||
};
|
||||
}
|
||||
const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue;
|
||||
const tables: { id: string; name: string }[] = (
|
||||
await httpClient.sendRequest<{ value: { id: string; name: string }[] }>(
|
||||
{
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/tables`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: authProp['access_token']
|
||||
}
|
||||
}
|
||||
)
|
||||
).body.value;
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: tables.map((table: { id: string; name: string }) => {
|
||||
return {
|
||||
label: table.name,
|
||||
value: table.id
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
}),
|
||||
values: Property.DynamicProperties({
|
||||
auth: excelAuth,
|
||||
displayName: 'Values',
|
||||
description: 'The values to insert',
|
||||
required: true,
|
||||
refreshers: ['workbook_id', 'worksheet_id', 'first_row_headers'],
|
||||
props: async ({ auth, workbook_id, worksheet_id, first_row_headers }) => {
|
||||
if (
|
||||
!auth ||
|
||||
(workbook_id ?? '').toString().length === 0 ||
|
||||
(worksheet_id ?? '').toString().length === 0
|
||||
) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue;
|
||||
|
||||
if (!first_row_headers) {
|
||||
return {
|
||||
values: Property.Array({
|
||||
displayName: 'Values',
|
||||
required: true
|
||||
})
|
||||
};
|
||||
}
|
||||
const firstRow = await excelCommon.getHeaders(
|
||||
workbook_id as unknown as string,
|
||||
authProp['access_token'],
|
||||
worksheet_id as unknown as string
|
||||
);
|
||||
|
||||
const properties: {
|
||||
[key: string]: any;
|
||||
} = {};
|
||||
for (const key in firstRow) {
|
||||
properties[key] = Property.ShortText({
|
||||
displayName: firstRow[key].toString(),
|
||||
description: firstRow[key].toString(),
|
||||
required: false,
|
||||
defaultValue: ''
|
||||
});
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}),
|
||||
table_values: Property.DynamicProperties({
|
||||
auth: excelAuth,
|
||||
displayName: 'Values',
|
||||
description: 'The values to insert',
|
||||
required: true,
|
||||
refreshers: ['workbook_id', 'worksheet_id', 'table_id'],
|
||||
props: async ({ auth, workbook_id, worksheet_id, table_id }) => {
|
||||
if (
|
||||
!auth ||
|
||||
(workbook_id ?? '').toString().length === 0 ||
|
||||
(worksheet_id ?? '').toString().length === 0 ||
|
||||
(worksheet_id ?? '').toString().length === 0
|
||||
) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue;
|
||||
|
||||
const headers = await excelCommon.getTableHeaders(
|
||||
workbook_id as unknown as string,
|
||||
authProp['access_token'],
|
||||
worksheet_id as unknown as string,
|
||||
table_id as unknown as string
|
||||
);
|
||||
|
||||
const properties: {
|
||||
[key: string]: any;
|
||||
} = {};
|
||||
for (const key in headers) {
|
||||
properties[key] = Property.ShortText({
|
||||
displayName: headers[key].toString(),
|
||||
description: headers[key].toString(),
|
||||
required: false,
|
||||
defaultValue: ''
|
||||
});
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}),
|
||||
parent_folder: Property.Dropdown({
|
||||
auth: excelAuth,
|
||||
displayName: 'Parent Folder',
|
||||
description: 'The parent folder to use',
|
||||
required: true,
|
||||
refreshers: [],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please authenticate first'
|
||||
};
|
||||
}
|
||||
|
||||
const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue;
|
||||
|
||||
const rootFolderId = 'root';
|
||||
const allFolders: { id: string; name: string }[] =
|
||||
await excelCommon.getAllFolders(
|
||||
rootFolderId,
|
||||
authProp['access_token'],
|
||||
''
|
||||
);
|
||||
allFolders.unshift({
|
||||
id: rootFolderId,
|
||||
name: '/'
|
||||
});
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: allFolders.map((table: { id: string; name: string }) => {
|
||||
return {
|
||||
label: table.name,
|
||||
value: table.id
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
}),
|
||||
getHeaders: async function (
|
||||
workbookId: string,
|
||||
accessToken: string,
|
||||
worksheetId: string
|
||||
) {
|
||||
const response = await httpClient.sendRequest<{
|
||||
values: (string | number | boolean)[][];
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/usedRange(valuesOnly=true)`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: accessToken
|
||||
}
|
||||
});
|
||||
|
||||
return response.body.values?.[0] ?? [];
|
||||
},
|
||||
getTableHeaders: async function (
|
||||
workbookId: string,
|
||||
accessToken: string,
|
||||
worksheetId: string,
|
||||
tableId: string
|
||||
) {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/columns`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: accessToken
|
||||
}
|
||||
});
|
||||
|
||||
const columnNames = response.body['value'].map(
|
||||
(column: { name: any }) => column.name
|
||||
);
|
||||
return columnNames;
|
||||
},
|
||||
getLastUsedRow: async function (
|
||||
workbookId: string,
|
||||
worksheetId: string,
|
||||
accessToken: string
|
||||
): Promise<number> {
|
||||
const url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/usedRange`;
|
||||
|
||||
const request: HttpRequest = {
|
||||
method: HttpMethod.GET,
|
||||
url: url,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: accessToken
|
||||
}
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
const usedRange = response.body['address'].split('!')[1];
|
||||
const lastCell = usedRange.indexOf(':') != -1 ? usedRange.split(':')[1] : usedRange;
|
||||
const lastRow = parseInt(lastCell.match(/\d+/)[0], 10);
|
||||
|
||||
return lastRow;
|
||||
},
|
||||
getLastUsedColumn: async function (
|
||||
workbookId: string,
|
||||
worksheetId: string,
|
||||
accessToken: string
|
||||
): Promise<string> {
|
||||
const url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/usedRange`;
|
||||
|
||||
const request: HttpRequest = {
|
||||
method: HttpMethod.GET,
|
||||
url: url,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: accessToken
|
||||
}
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
const usedRange = response.body['address'].split('!')[1];
|
||||
const [, lastCell] = usedRange.split(':');
|
||||
const lastColumnLetter = lastCell.match(/[A-Z]+/)[0];
|
||||
|
||||
return lastColumnLetter;
|
||||
},
|
||||
getAllRows: async function (
|
||||
workbookId: string,
|
||||
worksheetId: string,
|
||||
accessToken: string
|
||||
): Promise<(string | number | boolean)[][]> {
|
||||
const response = await httpClient.sendRequest<{
|
||||
values: (string | number | boolean)[][];
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/usedRange(valuesOnly=true)`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: accessToken
|
||||
}
|
||||
});
|
||||
|
||||
return response.body['values'] ?? [];
|
||||
},
|
||||
numberToColumnName: function (num: number): string {
|
||||
let columnName = '';
|
||||
while (num > 0) {
|
||||
const modulo = (num - 1) % 26;
|
||||
columnName = String.fromCharCode(65 + modulo) + columnName;
|
||||
num = Math.floor((num - modulo) / 26);
|
||||
}
|
||||
return columnName;
|
||||
},
|
||||
getAllFolders: async function (
|
||||
folderId: string,
|
||||
authToken: string,
|
||||
currentPath: string
|
||||
): Promise<{ id: string; name: string }[]> {
|
||||
const apiUrl = `${excelCommon.baseUrl}/items/${folderId}/children?$filter=folder ne null`;
|
||||
const response = await httpClient.sendRequest<{
|
||||
value: { id: string; name: string; folder?: unknown }[];
|
||||
}>({
|
||||
url: apiUrl,
|
||||
method: HttpMethod.GET,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: authToken
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.body || !response.body.value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const folders = response.body.value.map((folder) => ({
|
||||
id: `${folder.id}`,
|
||||
name: `${currentPath}/${folder.name}`
|
||||
}));
|
||||
let allSubFolders: { id: string; name: string }[] = [...folders];
|
||||
|
||||
for (const folder of folders) {
|
||||
const subFolders = await excelCommon.getAllFolders(
|
||||
folder.id,
|
||||
authToken,
|
||||
folder.name
|
||||
);
|
||||
allSubFolders = allSubFolders.concat(subFolders);
|
||||
}
|
||||
return allSubFolders;
|
||||
}
|
||||
};
|
||||
|
||||
export function objectToArray(obj: { [x: string]: any }) {
|
||||
const maxIndex = Math.max(...Object.keys(obj).map(Number));
|
||||
const arr = new Array(maxIndex + 1).fill(null);
|
||||
for (const key in obj) {
|
||||
arr[Number(key)] = obj[key];
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
Property,
|
||||
createTrigger,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { excelCommon } from '../common/common';
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { isNil } from '@activepieces/shared';
|
||||
import { excelAuth } from '../..';
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof excelAuth>,
|
||||
{
|
||||
workbook_id: string;
|
||||
worksheet_id: string;
|
||||
max_rows_to_poll: number | undefined;
|
||||
}
|
||||
> = {
|
||||
strategy: DedupeStrategy.LAST_ITEM,
|
||||
items: async ({ auth, propsValue, lastItemId }) => {
|
||||
const fetchedValues =
|
||||
(await excelCommon.getAllRows(
|
||||
propsValue.workbook_id,
|
||||
propsValue.worksheet_id,
|
||||
auth.access_token
|
||||
)) ?? [];
|
||||
|
||||
const currentValues = fetchedValues.map((row: any[], rowIndex: number) => {
|
||||
const rowObject: any = {};
|
||||
row.forEach((cell: any, cellIndex: number) => {
|
||||
const columnName = String.fromCharCode(65 + cellIndex);
|
||||
rowObject[columnName] = cell;
|
||||
});
|
||||
return {
|
||||
row: rowIndex + 1,
|
||||
values: rowObject,
|
||||
};
|
||||
});
|
||||
|
||||
const items = currentValues
|
||||
.filter((f: any) => Object.keys(f.values).length > 0)
|
||||
.map((item: any, index: number) => ({
|
||||
id: index + 1,
|
||||
data: item,
|
||||
}))
|
||||
.filter(
|
||||
(f: any) => isNil(lastItemId) || f.data.row > (lastItemId as number)
|
||||
);
|
||||
|
||||
return items.reverse();
|
||||
},
|
||||
};
|
||||
|
||||
export const readNewRows = createTrigger({
|
||||
auth: excelAuth,
|
||||
name: 'new_row',
|
||||
displayName: 'New Row',
|
||||
description:
|
||||
'Trigger when a new row is added, and it can include existing rows as well.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
max_rows_to_poll: Property.Number({
|
||||
displayName: 'Max Rows to Poll',
|
||||
description:
|
||||
'The maximum number of rows to poll, the rest will be polled on the next run.',
|
||||
required: false,
|
||||
defaultValue: 10,
|
||||
}),
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
sampleData: {},
|
||||
onEnable: async (context) => {
|
||||
await pollingHelper.onEnable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
onDisable: async (context) => {
|
||||
await pollingHelper.onDisable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
run: async (context) => {
|
||||
return await pollingHelper.poll(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
maxItemsToPoll: Math.max(
|
||||
1,
|
||||
Math.min(10, context.propsValue.max_rows_to_poll ?? 10)
|
||||
),
|
||||
propsValue: context.propsValue,
|
||||
files: context.files,
|
||||
});
|
||||
},
|
||||
test: async (context) => {
|
||||
return await pollingHelper.test(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
files: context.files,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,170 @@
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
OAuth2PropertyValue,
|
||||
Property,
|
||||
createTrigger,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { excelCommon } from '../common/common';
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { isNil } from '@activepieces/shared';
|
||||
import { excelAuth } from '../..';
|
||||
|
||||
interface TableRow {
|
||||
index: number;
|
||||
values: [[string | number | boolean]];
|
||||
}
|
||||
|
||||
// Helper function to get all rows from a specific table
|
||||
async function getTableRows(auth: OAuth2PropertyValue, workbookId: string, tableId: string): Promise<TableRow[]> {
|
||||
try {
|
||||
const response = await httpClient.sendRequest<{ value: TableRow[] }>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/tables/${encodeURIComponent(tableId)}/rows`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth.access_token,
|
||||
},
|
||||
});
|
||||
return response.body.value ?? [];
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to fetch table rows: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof excelAuth>,
|
||||
{
|
||||
workbook_id: string;
|
||||
worksheet_id: string;
|
||||
table_id: string;
|
||||
has_headers: boolean;
|
||||
}
|
||||
> = {
|
||||
strategy: DedupeStrategy.LAST_ITEM,
|
||||
items: async ({ auth, propsValue, lastItemId, store }) => {
|
||||
const rows = await getTableRows(auth, propsValue.workbook_id, propsValue.table_id);
|
||||
|
||||
if (rows.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const cachedHeaders = await store.get<string[]>('table_headers');
|
||||
let headers: string[] = [];
|
||||
|
||||
if (cachedHeaders && cachedHeaders.length > 0) {
|
||||
headers = cachedHeaders
|
||||
} else {
|
||||
try {
|
||||
headers = await excelCommon.getTableHeaders(
|
||||
propsValue.workbook_id,
|
||||
auth.access_token,
|
||||
propsValue.worksheet_id,
|
||||
propsValue.table_id
|
||||
);
|
||||
await store.put('table_headers', headers);
|
||||
} catch (error) {
|
||||
headers = []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const processedRows = rows.map(row => {
|
||||
let rowData: Record<string, unknown> = {};
|
||||
|
||||
if (propsValue.has_headers && headers.length > 0) {
|
||||
// Map values to header keys
|
||||
rowData = headers.reduce((acc, header, index) => {
|
||||
acc[header] = row.values[0]?.[index] ?? null;
|
||||
return acc;
|
||||
}, {} as Record<string, unknown>);
|
||||
} else {
|
||||
// Use default column letter keys (A, B, C...)
|
||||
rowData = row.values[0]?.reduce((acc, value, index) => {
|
||||
acc[excelCommon.numberToColumnName(index + 1)] = value;
|
||||
return acc;
|
||||
}, {} as Record<string, unknown>) ?? {};
|
||||
}
|
||||
|
||||
return {
|
||||
id: row.index, // The row's zero-based index is its unique ID
|
||||
data: {
|
||||
rowIndex: row.index,
|
||||
values: rowData
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// The polling helper will filter for new rows where the ID (row.index) is greater than lastItemId
|
||||
const newItems = processedRows.filter(item => isNil(lastItemId) || item.id > (lastItemId as number));
|
||||
return newItems;
|
||||
}
|
||||
};
|
||||
|
||||
export const newRowInTableTrigger = createTrigger({
|
||||
auth: excelAuth,
|
||||
name: 'new_row_in_table',
|
||||
displayName: 'New Row in Table',
|
||||
description: 'Fires when a new row is added to a table within a worksheet.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
has_headers: Property.Checkbox({
|
||||
displayName: "My table has headers",
|
||||
description: "Enable this if the first row of your table is a header row.",
|
||||
required: true,
|
||||
defaultValue: true,
|
||||
})
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
sampleData: {
|
||||
"rowIndex": 0,
|
||||
"values": {
|
||||
"ID": 1,
|
||||
"Name": "John Doe",
|
||||
"Email": "john.doe@example.com"
|
||||
}
|
||||
},
|
||||
|
||||
onEnable: async (context) => {
|
||||
await pollingHelper.onEnable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
|
||||
onDisable: async (context) => {
|
||||
await pollingHelper.onDisable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
|
||||
run: async (context) => {
|
||||
return await pollingHelper.poll(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
files: context.files,
|
||||
});
|
||||
},
|
||||
|
||||
test: async (context) => {
|
||||
return await pollingHelper.test(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
files: context.files,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
OAuth2PropertyValue,
|
||||
createTrigger
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../..';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
DedupeStrategy
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
interface Worksheet {
|
||||
id: string;
|
||||
name: string;
|
||||
position: number;
|
||||
visibility: string;
|
||||
}
|
||||
|
||||
async function getWorksheets(
|
||||
auth: OAuth2PropertyValue,
|
||||
workbookId: string
|
||||
): Promise<Worksheet[]> {
|
||||
if (!workbookId) return [];
|
||||
|
||||
try {
|
||||
const response = await httpClient.sendRequest<{ value: Worksheet[] }>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth.access_token
|
||||
}
|
||||
});
|
||||
return response.body.value ?? [];
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to fetch worksheets: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
const polling: Polling<AppConnectionValueForAuthProperty<typeof excelAuth>, { workbook_id: string }> = {
|
||||
strategy: DedupeStrategy.LAST_ITEM,
|
||||
items: async ({ auth, propsValue, store }) => {
|
||||
const worksheets = await getWorksheets(auth, propsValue.workbook_id);
|
||||
|
||||
const storedWorksheetIds = await store.get<string[]>('worksheet_ids') ?? [];
|
||||
|
||||
const newWorksheets = worksheets.filter(ws => !storedWorksheetIds.includes(ws.id));
|
||||
|
||||
const currentWorksheetIds = worksheets.map(ws => ws.id);
|
||||
await store.put('worksheet_ids', currentWorksheetIds);
|
||||
|
||||
const processedWorksheets = newWorksheets.map((worksheet) => ({
|
||||
id: worksheet.id,
|
||||
data: worksheet
|
||||
}));
|
||||
|
||||
return processedWorksheets;
|
||||
}
|
||||
};
|
||||
|
||||
export const newWorksheetTrigger = createTrigger({
|
||||
auth: excelAuth,
|
||||
name: 'new_worksheet',
|
||||
displayName: 'New Worksheet',
|
||||
description: 'Fires when a new worksheet is created in a workbook.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
sampleData: {
|
||||
'@odata.id':
|
||||
'/workbook/worksheets(%27%7B00000000-0001-0000-0100-000000000000%7D%27)',
|
||||
id: '{00000000-0001-0000-0100-000000000000}',
|
||||
name: 'Sheet2',
|
||||
position: 1,
|
||||
visibility: 'Visible'
|
||||
},
|
||||
|
||||
onEnable: async (context) => {
|
||||
await pollingHelper.onEnable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue
|
||||
});
|
||||
},
|
||||
|
||||
onDisable: async (context) => {
|
||||
await pollingHelper.onDisable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue
|
||||
});
|
||||
},
|
||||
|
||||
run: async (context) => {
|
||||
return await pollingHelper.poll(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
files: context.files
|
||||
});
|
||||
},
|
||||
|
||||
test: async (context) => {
|
||||
return await pollingHelper.test(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
files: context.files
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,155 @@
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
Property,
|
||||
createTrigger,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../..';
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { createHmac } from 'node:crypto';
|
||||
|
||||
const triggerName = 'updated_row';
|
||||
|
||||
function createRowHash(rowData: unknown[]): string {
|
||||
const rowString = JSON.stringify(rowData);
|
||||
return createHmac('sha1', 'activepieces').update(rowString).digest('hex');
|
||||
}
|
||||
|
||||
// Helper function to get all worksheet rows with error handling
|
||||
async function getWorksheetRows(auth: AppConnectionValueForAuthProperty<typeof excelAuth>, workbookId: string, worksheetId: string): Promise<(string | number | boolean)[][]> {
|
||||
try {
|
||||
return await excelCommon.getAllRows(workbookId, worksheetId, auth.access_token);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to fetch worksheet rows: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Polling implementation using the framework's best practices
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof excelAuth>,
|
||||
{
|
||||
workbook_id: string;
|
||||
worksheet_id: string;
|
||||
has_headers: boolean;
|
||||
}
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth, propsValue, store }) => {
|
||||
const allRows = await getWorksheetRows(auth, propsValue.workbook_id, propsValue.worksheet_id);
|
||||
|
||||
if (allRows.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get stored row hashes from previous run
|
||||
const oldHashes = await store.get<Record<number, string>>('row_hashes') ?? {};
|
||||
|
||||
const headers = (propsValue.has_headers && allRows.length > 0) ? allRows[0] : [];
|
||||
const dataRows = (propsValue.has_headers && allRows.length > 0) ? allRows.slice(1) : allRows;
|
||||
|
||||
const currentHashes: Record<number, string> = {};
|
||||
const changedItems: Array<{ epochMilliSeconds: number; data: unknown }> = [];
|
||||
const currentTime = Date.now();
|
||||
|
||||
// Process each data row
|
||||
dataRows.forEach((row, index) => {
|
||||
const rowIndex = propsValue.has_headers ? index + 1 : index;
|
||||
const newHash = createRowHash(row);
|
||||
currentHashes[rowIndex] = newHash;
|
||||
|
||||
const oldHash = oldHashes[rowIndex];
|
||||
|
||||
// Row has changed or is new
|
||||
if (oldHash !== newHash) {
|
||||
const formattedRow: Record<string, unknown> = {};
|
||||
|
||||
if (propsValue.has_headers && headers.length > 0) {
|
||||
headers.forEach((header, colIndex) => {
|
||||
formattedRow[String(header)] = row[colIndex] ?? null;
|
||||
});
|
||||
} else {
|
||||
row.forEach((cell, colIndex) => {
|
||||
formattedRow[excelCommon.numberToColumnName(colIndex + 1)] = cell;
|
||||
});
|
||||
}
|
||||
|
||||
changedItems.push({
|
||||
epochMilliSeconds: currentTime,
|
||||
data: {
|
||||
rowIndex: rowIndex + 1, // Make it 1-based for user readability
|
||||
values: formattedRow,
|
||||
changeType: oldHash ? 'updated' : 'added'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Update stored hashes for next run
|
||||
await store.put('row_hashes', currentHashes);
|
||||
|
||||
return changedItems;
|
||||
}
|
||||
};
|
||||
|
||||
export const updatedRowTrigger = createTrigger({
|
||||
auth: excelAuth,
|
||||
name: triggerName,
|
||||
displayName: 'Updated Row',
|
||||
description: 'Fires when a row (in a worksheet) is added or updated.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
has_headers: Property.Checkbox({
|
||||
displayName: "First row has headers",
|
||||
description: "Enable this if the first row of your worksheet should be treated as headers.",
|
||||
required: true,
|
||||
defaultValue: false,
|
||||
})
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
sampleData: {
|
||||
"rowIndex": 1,
|
||||
"values": { "ID": 101, "Product": "Widget", "Price": 19.99 }
|
||||
},
|
||||
|
||||
onEnable: async (context) => {
|
||||
|
||||
await pollingHelper.onEnable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
|
||||
onDisable: async (context) => {
|
||||
|
||||
await pollingHelper.onDisable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
|
||||
run: async (context) => {
|
||||
return await pollingHelper.poll(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
files: context.files,
|
||||
});
|
||||
},
|
||||
|
||||
test: async (context) => {
|
||||
return await pollingHelper.test(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
files: context.files,
|
||||
});
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user