first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
const notionIdRegexp = '[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}';
|
||||
|
||||
export const idExtractionRegexp = `^(${notionIdRegexp})`;
|
||||
export const idValidationRegexp = `${idExtractionRegexp}.*`;
|
||||
|
||||
const baseUrlRegexp = '(?:https|http)://www\\.notion\\.so/(?:[a-z0-9-]{2,}/)?';
|
||||
|
||||
export const databaseUrlExtractionRegexp = `${baseUrlRegexp}(${notionIdRegexp})`;
|
||||
export const databaseUrlValidationRegexp = `${databaseUrlExtractionRegexp}.*`;
|
||||
|
||||
export const databasePageUrlExtractionRegexp = `${baseUrlRegexp}(?:[a-zA-Z0-9-]{1,}-)?(${notionIdRegexp})`;
|
||||
export const databasePageUrlValidationRegexp = `${databasePageUrlExtractionRegexp}.*`;
|
||||
|
||||
export const blockUrlExtractionRegexp = `${baseUrlRegexp}(?:[a-zA-Z0-9-]{2,}-)?(${notionIdRegexp})`;
|
||||
export const blockUrlValidationRegexp = `${blockUrlExtractionRegexp}.*`;
|
||||
@@ -0,0 +1,291 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { blocks } from './Blocks';
|
||||
import {
|
||||
blockUrlExtractionRegexp,
|
||||
blockUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from '../constants';
|
||||
|
||||
//RLC with fixed regex for blockId
|
||||
const blockIdRLC: INodeProperties = {
|
||||
displayName: 'Block',
|
||||
name: 'blockId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder:
|
||||
'e.g. https://www.notion.so/Block-Test-88888ccc303e4f44847f27d24bd7ad8e?pvs=4#c44444444444bbbbb4d32fdfdd84e',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: blockUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
// extractValue: {
|
||||
// type: 'regex',
|
||||
// regex: blockUrlExtractionRegexp,
|
||||
// },
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'e.g. ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
description:
|
||||
"The Notion Block to get all children from, when using 'By URL' mode make sure to use the URL of the block itself, you can find it in block parameters in Notion under 'Copy link to block'",
|
||||
};
|
||||
|
||||
export const blockOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Append After',
|
||||
value: 'append',
|
||||
description: 'Append a block',
|
||||
action: 'Append a block',
|
||||
},
|
||||
{
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-option-name-wrong-for-get-many
|
||||
name: 'Get Child Blocks',
|
||||
value: 'getAll',
|
||||
description: 'Get many child blocks',
|
||||
action: 'Get many child blocks',
|
||||
},
|
||||
],
|
||||
default: 'append',
|
||||
},
|
||||
];
|
||||
|
||||
export const blockFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* block:append */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Block',
|
||||
name: 'blockId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://www.notion.so/My-Page-b4eeb113e118403ba450af65ac25f0b9',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: blockUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: blockUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['append'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [{ _cnd: { gte: 2.2 } }],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Block to append blocks to',
|
||||
},
|
||||
{
|
||||
...blockIdRLC,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['append'],
|
||||
'@version': [{ _cnd: { gte: 2.2 } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
...blocks('block', 'append'),
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* block:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Block',
|
||||
name: 'blockId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://www.notion.so/My-Page-b4eeb113e118403ba450af65ac25f0b9',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: blockUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: blockUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [{ _cnd: { gte: 2.2 } }],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Block to get all children from',
|
||||
},
|
||||
{
|
||||
...blockIdRLC,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
'@version': [{ _cnd: { gte: 2.2 } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Also Fetch Nested Blocks',
|
||||
name: 'fetchNestedBlocks',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify Output',
|
||||
name: 'simplifyOutput',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1, 2],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,603 @@
|
||||
import type { IDisplayOptions, INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
databaseUrlExtractionRegexp,
|
||||
databaseUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from '../constants';
|
||||
|
||||
const colors = [
|
||||
{
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
name: 'Gray',
|
||||
value: 'gray',
|
||||
},
|
||||
{
|
||||
name: 'Brown',
|
||||
value: 'brown',
|
||||
},
|
||||
{
|
||||
name: 'Orange',
|
||||
value: 'orange',
|
||||
},
|
||||
{
|
||||
name: 'Yellow',
|
||||
value: 'yellow',
|
||||
},
|
||||
{
|
||||
name: 'Green',
|
||||
value: 'green',
|
||||
},
|
||||
{
|
||||
name: 'Blue',
|
||||
value: 'blue',
|
||||
},
|
||||
{
|
||||
name: 'Purple',
|
||||
value: 'purple',
|
||||
},
|
||||
{
|
||||
name: 'Pink',
|
||||
value: 'pink',
|
||||
},
|
||||
{
|
||||
name: 'Red',
|
||||
value: 'red',
|
||||
},
|
||||
{
|
||||
name: 'Gray Background',
|
||||
value: 'gray_background',
|
||||
},
|
||||
{
|
||||
name: 'Brown Background',
|
||||
value: 'brown_background',
|
||||
},
|
||||
{
|
||||
name: 'Orange Background',
|
||||
value: 'orange_background',
|
||||
},
|
||||
{
|
||||
name: 'Yellow Background',
|
||||
value: 'yellow_background',
|
||||
},
|
||||
{
|
||||
name: 'Green Background',
|
||||
value: 'green_background',
|
||||
},
|
||||
{
|
||||
name: 'Blue Background',
|
||||
value: 'blue_background',
|
||||
},
|
||||
{
|
||||
name: 'Purple Background',
|
||||
value: 'purple_background',
|
||||
},
|
||||
{
|
||||
name: 'Pink Background',
|
||||
value: 'pink_background',
|
||||
},
|
||||
{
|
||||
name: 'Red Background',
|
||||
value: 'red_background',
|
||||
},
|
||||
];
|
||||
|
||||
const annotation: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Annotations',
|
||||
name: 'annotationUi',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Annotation',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Bold',
|
||||
name: 'bold',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is bolded',
|
||||
},
|
||||
{
|
||||
displayName: 'Italic',
|
||||
name: 'italic',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is italicized',
|
||||
},
|
||||
{
|
||||
displayName: 'Strikethrough',
|
||||
name: 'strikethrough',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is struck through',
|
||||
},
|
||||
{
|
||||
displayName: 'Underline',
|
||||
name: 'underline',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is underlined',
|
||||
},
|
||||
{
|
||||
displayName: 'Code',
|
||||
name: 'code',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is code style',
|
||||
},
|
||||
{
|
||||
displayName: 'Color',
|
||||
name: 'color',
|
||||
type: 'options',
|
||||
options: colors,
|
||||
default: '',
|
||||
description: 'Color of the text',
|
||||
},
|
||||
],
|
||||
description: 'All annotations that apply to this rich text',
|
||||
},
|
||||
];
|
||||
|
||||
const typeMention: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'mentionType',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['mention'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Database',
|
||||
value: 'database',
|
||||
},
|
||||
{
|
||||
name: 'Date',
|
||||
value: 'date',
|
||||
},
|
||||
{
|
||||
name: 'Page',
|
||||
value: 'page',
|
||||
},
|
||||
{
|
||||
name: 'User',
|
||||
value: 'user',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description:
|
||||
'An inline mention of a user, page, database, or date. In the app these are created by typing @ followed by the name of a user, page, database, or a date.',
|
||||
},
|
||||
{
|
||||
displayName: 'User Name or ID',
|
||||
name: 'user',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['user'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'The ID of the user being mentioned. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Page ID',
|
||||
name: 'page',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['page'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The ID of the page being mentioned',
|
||||
},
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'database',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'list', value: '' },
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'list',
|
||||
type: 'list',
|
||||
placeholder: 'Select a Database...',
|
||||
typeOptions: {
|
||||
searchListMethod: 'getDatabases',
|
||||
searchable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder:
|
||||
'https://www.notion.so/0fe2f7de558b471eab07e9d871cdf4a9?v=f2d424ba0c404733a3f500c78c881610',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databaseUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databaseUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['database'],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Database being mentioned',
|
||||
},
|
||||
{
|
||||
displayName: 'Range',
|
||||
name: 'range',
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['date'],
|
||||
},
|
||||
},
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether or not you want to define a date range',
|
||||
},
|
||||
{
|
||||
displayName: 'Date',
|
||||
name: 'date',
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['date'],
|
||||
range: [false],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
{
|
||||
displayName: 'Date Start',
|
||||
name: 'dateStart',
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['date'],
|
||||
range: [true],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
{
|
||||
displayName: 'Date End',
|
||||
name: 'dateEnd',
|
||||
displayOptions: {
|
||||
show: {
|
||||
range: [true],
|
||||
mentionType: ['date'],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description:
|
||||
'An ISO 8601 formatted date, with optional time. Represents the end of a date range.',
|
||||
},
|
||||
];
|
||||
|
||||
const typeEquation: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Expression',
|
||||
name: 'expression',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['equation'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
];
|
||||
|
||||
const typeText: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['text'],
|
||||
},
|
||||
},
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
"Text content. This field contains the actual content of your text and is probably the field you'll use most often.",
|
||||
},
|
||||
{
|
||||
displayName: 'Is Link',
|
||||
name: 'isLink',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['text'],
|
||||
},
|
||||
},
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
displayName: 'Text Link',
|
||||
name: 'textLink',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['text'],
|
||||
isLink: [true],
|
||||
},
|
||||
},
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The URL that this link points to',
|
||||
},
|
||||
];
|
||||
|
||||
export const text = (displayOptions: IDisplayOptions): INodeProperties[] =>
|
||||
[
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
placeholder: 'Add Text',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
displayOptions,
|
||||
options: [
|
||||
{
|
||||
name: 'text',
|
||||
displayName: 'Text',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'textType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Equation',
|
||||
value: 'equation',
|
||||
},
|
||||
{
|
||||
name: 'Mention',
|
||||
value: 'mention',
|
||||
},
|
||||
{
|
||||
name: 'Text',
|
||||
value: 'text',
|
||||
},
|
||||
],
|
||||
default: 'text',
|
||||
},
|
||||
...typeText,
|
||||
...typeMention,
|
||||
...typeEquation,
|
||||
|
||||
...annotation,
|
||||
],
|
||||
},
|
||||
],
|
||||
description: 'Rich text in the block',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
const todo = (type: string): INodeProperties[] =>
|
||||
[
|
||||
{
|
||||
displayName: 'Checked',
|
||||
name: 'checked',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [type],
|
||||
},
|
||||
},
|
||||
description: 'Whether the to_do is checked or not',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
const title = (type: string): INodeProperties[] =>
|
||||
[
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [type],
|
||||
},
|
||||
},
|
||||
description: 'Plain text of page title',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
const richText = (displayOptions: IDisplayOptions): INodeProperties[] => [
|
||||
{
|
||||
displayName: 'Rich Text',
|
||||
name: 'richText',
|
||||
type: 'boolean',
|
||||
displayOptions,
|
||||
default: false,
|
||||
},
|
||||
];
|
||||
|
||||
const textContent = (displayOptions: IDisplayOptions): INodeProperties[] => [
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'textContent',
|
||||
type: 'string',
|
||||
displayOptions,
|
||||
default: '',
|
||||
},
|
||||
];
|
||||
|
||||
const imageBlock = (type: string): INodeProperties[] => [
|
||||
{
|
||||
displayName: 'Image URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [type],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Image file reference',
|
||||
},
|
||||
];
|
||||
|
||||
const block = (blockType: string): INodeProperties[] => {
|
||||
const data: INodeProperties[] = [];
|
||||
switch (blockType) {
|
||||
case 'to_do':
|
||||
data.push(...todo(blockType));
|
||||
data.push(
|
||||
...richText({
|
||||
show: {
|
||||
type: [blockType],
|
||||
},
|
||||
}),
|
||||
);
|
||||
data.push(
|
||||
...textContent({
|
||||
show: {
|
||||
type: [blockType],
|
||||
richText: [false],
|
||||
},
|
||||
}),
|
||||
);
|
||||
data.push(
|
||||
...text({
|
||||
show: {
|
||||
type: [blockType],
|
||||
richText: [true],
|
||||
},
|
||||
}),
|
||||
);
|
||||
break;
|
||||
case 'child_page':
|
||||
data.push(...title(blockType));
|
||||
break;
|
||||
case 'image':
|
||||
data.push(...imageBlock(blockType));
|
||||
break;
|
||||
default:
|
||||
data.push(
|
||||
...richText({
|
||||
show: {
|
||||
type: [blockType],
|
||||
},
|
||||
}),
|
||||
);
|
||||
data.push(
|
||||
...textContent({
|
||||
show: {
|
||||
type: [blockType],
|
||||
richText: [false],
|
||||
},
|
||||
}),
|
||||
);
|
||||
data.push(
|
||||
...text({
|
||||
show: {
|
||||
type: [blockType],
|
||||
richText: [true],
|
||||
},
|
||||
}),
|
||||
);
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
export const blocks = (resource: string, operation: string): INodeProperties[] => [
|
||||
{
|
||||
displayName: 'Blocks',
|
||||
name: 'blockUi',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [resource],
|
||||
operation: [operation],
|
||||
},
|
||||
},
|
||||
placeholder: 'Add Block',
|
||||
options: [
|
||||
{
|
||||
name: 'blockValues',
|
||||
displayName: 'Block',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type Name or ID',
|
||||
name: 'type',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getBlockTypes',
|
||||
},
|
||||
default: 'paragraph',
|
||||
},
|
||||
...block('paragraph'),
|
||||
...block('heading_1'),
|
||||
...block('heading_2'),
|
||||
...block('heading_3'),
|
||||
...block('toggle'),
|
||||
...block('to_do'),
|
||||
...block('child_page'),
|
||||
...block('bulleted_list_item'),
|
||||
...block('numbered_list_item'),
|
||||
...block('image'),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,320 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
databaseUrlExtractionRegexp,
|
||||
databaseUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from '../constants';
|
||||
|
||||
export const databaseOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a database',
|
||||
action: 'Get a database',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many databases',
|
||||
action: 'Get many databases',
|
||||
},
|
||||
{
|
||||
name: 'Search',
|
||||
value: 'search',
|
||||
description: 'Search databases using text search',
|
||||
action: 'Search a database',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
resource: ['database'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a database',
|
||||
action: 'Get a database',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many databases',
|
||||
action: 'Get many databases',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const databaseFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* database:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'databaseId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'list', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'list',
|
||||
type: 'list',
|
||||
placeholder: 'Select a Database...',
|
||||
typeOptions: {
|
||||
searchListMethod: 'getDatabases',
|
||||
searchable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder:
|
||||
'https://www.notion.so/0fe2f7de558b471eab07e9d871cdf4a9?v=f2d424ba0c404733a3f500c78c881610',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databaseUrlValidationRegexp,
|
||||
errorMessage:
|
||||
'Not a valid Notion Database URL. Hint: use the URL of the database itself, not a page containing it.',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databaseUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Database to get',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* database:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['getAll', 'get'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* database:search */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Search Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
description: 'The text to search for',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
placeholder: 'Add Sort',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: false,
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sortValue',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Direction',
|
||||
name: 'direction',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Ascending',
|
||||
value: 'ascending',
|
||||
},
|
||||
{
|
||||
name: 'Descending',
|
||||
value: 'descending',
|
||||
},
|
||||
],
|
||||
default: 'descending',
|
||||
description: 'The direction to sort',
|
||||
},
|
||||
{
|
||||
displayName: 'Timestamp',
|
||||
name: 'timestamp',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Last Edited Time',
|
||||
value: 'last_edited_time',
|
||||
},
|
||||
],
|
||||
default: 'last_edited_time',
|
||||
description: 'The name of the timestamp to sort against',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,388 @@
|
||||
export const filters = (conditions: any) => [
|
||||
{
|
||||
displayName: 'Property Name or ID',
|
||||
name: 'key',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getFilterProperties',
|
||||
loadOptionsDependsOn: ['datatabaseId'],
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'The name of the property to filter by. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'type',
|
||||
type: 'hidden',
|
||||
default: '={{$parameter["&key"].split("|")[1]}}',
|
||||
},
|
||||
...conditions,
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'titleValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['title'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'richTextValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['rich_text'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Phone Number',
|
||||
name: 'phoneNumberValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['phone_number'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Phone number. No structure is enforced.',
|
||||
},
|
||||
{
|
||||
displayName: 'Option Name or ID',
|
||||
name: 'multiSelectValue',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getPropertySelectValues',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['multi_select'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: [],
|
||||
},
|
||||
{
|
||||
displayName: 'Option Name or ID',
|
||||
name: 'selectValue',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getPropertySelectValues',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['select'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Status Name or ID',
|
||||
name: 'statusValue',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getPropertySelectValues',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['status'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'emailValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['email'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'URL',
|
||||
name: 'urlValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['url'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'User Name or ID',
|
||||
name: 'peopleValue',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['people'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'List of users. Multiples can be defined separated by comma. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'User Name or ID',
|
||||
name: 'createdByValue',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['created_by'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'List of users. Multiples can be defined separated by comma. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'User Name or ID',
|
||||
name: 'lastEditedByValue',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['last_edited_by'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'List of users. Multiples can be defined separated by comma. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Relation ID',
|
||||
name: 'relationValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['relation'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Checked',
|
||||
name: 'checkboxValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['checkbox'],
|
||||
},
|
||||
},
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether or not the checkbox is checked. <code>true</code> represents checked. <code>false</code> represents unchecked',
|
||||
},
|
||||
{
|
||||
displayName: 'Number',
|
||||
name: 'numberValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['number'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'Number value',
|
||||
},
|
||||
{
|
||||
displayName: 'Date',
|
||||
name: 'date',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['date'],
|
||||
},
|
||||
hide: {
|
||||
condition: [
|
||||
'is_empty',
|
||||
'is_not_empty',
|
||||
'past_week',
|
||||
'past_month',
|
||||
'past_year',
|
||||
'next_week',
|
||||
'next_month',
|
||||
'next_year',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
{
|
||||
displayName: 'Created Time',
|
||||
name: 'createdTimeValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['created_time'],
|
||||
},
|
||||
hide: {
|
||||
condition: [
|
||||
'is_empty',
|
||||
'is_not_empty',
|
||||
'past_week',
|
||||
'past_month',
|
||||
'past_year',
|
||||
'next_week',
|
||||
'next_month',
|
||||
'next_year',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
{
|
||||
displayName: 'Last Edited Time',
|
||||
name: 'lastEditedTime',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['last_edited_time'],
|
||||
},
|
||||
hide: {
|
||||
condition: [
|
||||
'is_empty',
|
||||
'is_not_empty',
|
||||
'past_week',
|
||||
'past_month',
|
||||
'past_year',
|
||||
'next_week',
|
||||
'next_month',
|
||||
'next_year',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
//formula types
|
||||
{
|
||||
displayName: 'Number',
|
||||
name: 'numberValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['formula'],
|
||||
returnType: ['number'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'Number value',
|
||||
},
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'textValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['formula'],
|
||||
returnType: ['text'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Boolean',
|
||||
name: 'checkboxValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['formula'],
|
||||
returnType: ['checkbox'],
|
||||
},
|
||||
},
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether or not the checkbox is checked. <code>true</code> represents checked. <code>false</code> represents unchecked',
|
||||
},
|
||||
{
|
||||
displayName: 'Date',
|
||||
name: 'dateValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['formula'],
|
||||
returnType: ['date'],
|
||||
},
|
||||
hide: {
|
||||
condition: [
|
||||
'is_empty',
|
||||
'is_not_empty',
|
||||
'past_week',
|
||||
'past_month',
|
||||
'past_year',
|
||||
'next_week',
|
||||
'next_month',
|
||||
'next_year',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,491 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { blocks } from './Blocks';
|
||||
import {
|
||||
databasePageUrlExtractionRegexp,
|
||||
databasePageUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from '../constants';
|
||||
|
||||
export const pageOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
resource: ['page'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a page',
|
||||
action: 'Create a page',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a page',
|
||||
action: 'Get a page',
|
||||
},
|
||||
{
|
||||
name: 'Search',
|
||||
value: 'search',
|
||||
description: 'Text search of pages',
|
||||
action: 'Search a page',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Archive',
|
||||
value: 'archive',
|
||||
description: 'Archive a page',
|
||||
action: 'Archive a page',
|
||||
},
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a page',
|
||||
action: 'Create a page',
|
||||
},
|
||||
{
|
||||
name: 'Search',
|
||||
value: 'search',
|
||||
description: 'Text search of pages',
|
||||
action: 'Search a page',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const pageFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* page:archive */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Page',
|
||||
name: 'pageId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://www.notion.so/My-Page-b4eeb113e118403aa450af65ac25f0b9',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databasePageUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database Page URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databasePageUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Page ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['archive'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Page to archive',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['archive'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* page:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Parent Page',
|
||||
name: 'pageId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://www.notion.so/My-Page-b4eeb113e118403aa450af65ac25f0b9',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databasePageUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database Page URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databasePageUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Page ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Database Page to create a child page for',
|
||||
},
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'Page title. Appears at the top of the page and can be found via Quick Find.',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
...blocks('page', 'create'),
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add option',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Icon Type',
|
||||
name: 'iconType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Emoji',
|
||||
value: 'emoji',
|
||||
description: 'Use an Emoji for the icon',
|
||||
},
|
||||
{
|
||||
name: 'File',
|
||||
value: 'file',
|
||||
description: 'Use a file for the icon',
|
||||
},
|
||||
],
|
||||
default: 'emoji',
|
||||
description: 'The icon type for the page, Either a URL or an Emoji',
|
||||
},
|
||||
{
|
||||
displayName: 'Icon',
|
||||
name: 'icon',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Emoji or File URL to use as the icon',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* page:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Page Link or ID',
|
||||
name: 'pageId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
resource: ['page'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
"The Page URL from Notion's 'copy link' functionality (or just the ID contained within the URL)",
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
resource: ['page'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* page:search */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Search Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
description: 'The text to search for',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filter',
|
||||
placeholder: 'Add Filter',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: false,
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Filter',
|
||||
name: 'filters',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Property',
|
||||
name: 'property',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Object',
|
||||
value: 'object',
|
||||
},
|
||||
],
|
||||
default: 'object',
|
||||
description: 'The name of the property to filter by',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Database',
|
||||
value: 'database',
|
||||
},
|
||||
{
|
||||
name: 'Page',
|
||||
value: 'page',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description: 'The value of the property to filter by',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
placeholder: 'Add Sort',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: false,
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sortValue',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Direction',
|
||||
name: 'direction',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Ascending',
|
||||
value: 'ascending',
|
||||
},
|
||||
{
|
||||
name: 'Descending',
|
||||
value: 'descending',
|
||||
},
|
||||
],
|
||||
default: 'descending',
|
||||
description: 'The direction to sort',
|
||||
},
|
||||
{
|
||||
displayName: 'Timestamp',
|
||||
name: 'timestamp',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Last Edited Time',
|
||||
value: 'last_edited_time',
|
||||
},
|
||||
],
|
||||
default: 'last_edited_time',
|
||||
description: 'The name of the timestamp to sort against',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,83 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const userOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a user',
|
||||
action: 'Get a user',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many users',
|
||||
action: 'Get many users',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const userFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* user:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* user:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1 @@
|
||||
export * as listSearch from './listSearch';
|
||||
@@ -0,0 +1,38 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodeListSearchItems,
|
||||
INodeListSearchResult,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { notionApiRequestAllItems } from '../GenericFunctions';
|
||||
|
||||
export async function getDatabases(
|
||||
this: ILoadOptionsFunctions,
|
||||
filter?: string,
|
||||
): Promise<INodeListSearchResult> {
|
||||
const returnData: INodeListSearchItems[] = [];
|
||||
const body: IDataObject = {
|
||||
page_size: 100,
|
||||
query: filter,
|
||||
filter: { property: 'object', value: 'database' },
|
||||
};
|
||||
const databases = await notionApiRequestAllItems.call(this, 'results', 'POST', '/search', body);
|
||||
for (const database of databases) {
|
||||
returnData.push({
|
||||
name: database.title[0]?.plain_text || database.id,
|
||||
value: database.id,
|
||||
url: database.url,
|
||||
});
|
||||
}
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return { results: returnData };
|
||||
}
|
||||
Reference in New Issue
Block a user