diff --git a/docs/docs/integrations/notion/add-content-to-page.md b/docs/docs/integrations/notion/add-content-to-page.md
new file mode 100644
index 000000000..83b395fd0
--- /dev/null
+++ b/docs/docs/integrations/notion/add-content-to-page.md
@@ -0,0 +1,138 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# Add Content To Page
+
+The `AddContentToPage` component converts markdown text to Notion blocks and appends them to a Notion page.
+
+[Notion Reference](https://developers.notion.com/reference/patch-block-children)
+
+
+
+The `AddContentToPage` component enables you to:
+
+- Convert markdown text to Notion blocks.
+- Append the converted blocks to a specified Notion page.
+- Seamlessly integrate Notion content creation into Langflow workflows.
+
+
+## Component Usage
+
+To use the `AddContentToPage` component in a Langflow flow:
+
+1. **Add the `AddContentToPage` component** to your flow.
+2. **Configure the component** by providing:
+ - `markdown_text`: The markdown text to convert.
+ - `block_id`: The ID of the Notion page/block to append the content.
+ - `notion_secret`: The Notion integration token for authentication.
+3. **Connect the component** to other nodes in your flow as needed.
+4. **Run the flow** to convert the markdown text and append it to the specified Notion page.
+
+## Component Python Code
+
+```python
+import json
+from typing import Optional
+
+import requests
+from langflow.custom import CustomComponent
+
+
+class NotionPageCreator(CustomComponent):
+ display_name = "Create Page [Notion]"
+ description = "A component for creating Notion pages."
+ documentation: str = "https://docs.langflow.org/integrations/notion/add-content-to-page"
+ icon = "NotionDirectoryLoader"
+
+ def build_config(self):
+ return {
+ "database_id": {
+ "display_name": "Database ID",
+ "field_type": "str",
+ "info": "The ID of the Notion database.",
+ },
+ "notion_secret": {
+ "display_name": "Notion Secret",
+ "field_type": "str",
+ "info": "The Notion integration token.",
+ "password": True,
+ },
+ "properties": {
+ "display_name": "Properties",
+ "field_type": "str",
+ "info": "The properties of the new page. Depending on your database setup, this can change. E.G: {'Task name': {'id': 'title', 'type': 'title', 'title': [{'type': 'text', 'text': {'content': 'Send Notion Components to LF', 'link': null}}]}}",
+ },
+ }
+
+ def build(
+ self,
+ database_id: str,
+ notion_secret: str,
+ properties: str = '{"Task name": {"id": "title", "type": "title", "title": [{"type": "text", "text": {"content": "Send Notion Components to LF", "link": null}}]}}',
+ ) -> str:
+ if not database_id or not properties:
+ raise ValueError("Invalid input. Please provide 'database_id' and 'properties'.")
+
+ headers = {
+ "Authorization": f"Bearer {notion_secret}",
+ "Content-Type": "application/json",
+ "Notion-Version": "2022-06-28",
+ }
+
+ data = {
+ "parent": {"database_id": database_id},
+ "properties": json.loads(properties),
+ }
+
+ response = requests.post("https://api.notion.com/v1/pages", headers=headers, json=data)
+
+ if response.status_code == 200:
+ page_id = response.json()["id"]
+ self.status = f"Successfully created Notion page with ID: {page_id}\n {str(response.json())}"
+ return response.json()
+ else:
+ error_message = f"Failed to create Notion page. Status code: {response.status_code}, Error: {response.text}"
+ self.status = error_message
+ raise Exception(error_message)
+```
+
+## Example Usage
+
+
+
+Example of using the `AddContentToPage` component in a Langflow flow using Markdown as input:
+
+
+
+In this example, the `AddContentToPage` component connects to a `MarkdownLoader` component to provide the markdown text input. The converted Notion blocks are appended to the specified Notion page using the provided `block_id` and `notion_secret`.
+
+
+
+## Best Practices
+
+When using the `AddContentToPage` component:
+
+- Ensure markdown text is well-formatted.
+- Verify the `block_id` corresponds to the right Notion page/block.
+- Keep your Notion integration token secure.
+- Test with sample markdown text before production use.
+
+The `AddContentToPage` component is a powerful tool for integrating Notion content creation into Langflow workflows, facilitating easy conversion of markdown text to Notion blocks and appending them to specific pages.
+
+## Troubleshooting
+
+If you encounter any issues while using the `AddContentToPage` component, consider the following:
+- Verify the Notion integration token’s validity and permissions.
+- Check the Notion API documentation for updates.
+- Ensure markdown text is properly formatted.
+- Double-check the `block_id` for correctness.
+
diff --git a/docs/docs/integrations/notion/intro.md b/docs/docs/integrations/notion/intro.md
new file mode 100644
index 000000000..ec8738dc7
--- /dev/null
+++ b/docs/docs/integrations/notion/intro.md
@@ -0,0 +1,43 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# Introduction to Notion in Langflow
+
+The Notion integration in Langflow enables seamless connectivity with Notion databases, pages, and users, facilitating automation and improving productivity.
+
+
+
+#### Download Notion Components Bundle
+
+### Key Features of Notion Integration in Langflow
+
+- **List Pages**: Retrieve a list of pages from a Notion database and access data stored in your Notion workspace.
+- **List Database Properties**: Obtain insights into the properties of a Notion database, allowing for easy understanding of its structure and metadata.
+- **Add Page Content**: Programmatically add new content to a Notion page, simplifying the creation and updating of pages.
+- **List Users**: Retrieve a list of users with access to a Notion workspace, aiding in user management and collaboration.
+- **Update Property**: Update the value of a specific property in a Notion page, enabling easy modification and maintenance of Notion data.
+
+### Potential Use Cases for Notion Integration in Langflow
+
+- **Task Automation**: Automate task creation in Notion using Langflow's AI capabilities. Describe the required tasks, and they will be automatically created and updated in Notion.
+- **Context Extraction from Meetings**: Leverage AI to analyze meeting contexts, extract key points, and update the relevant Notion pages automatically.
+- **Content Creation**: Utilize AI to generate ideas, suggest templates, and populate Notion pages with relevant data, enhancing content management efficiency.
+
+### Getting Started with Notion Integration in Langflow
+
+1. **Set Up Notion Integration**: Follow the guide [Setting up a Notion App](./setup) to set up a Notion integration in your workspace.
+2. **Configure Notion Components**: Provide the necessary authentication details and parameters to configure the Notion components in your Langflow flows.
+3. **Connect Components**: Integrate Notion components with other Langflow components to build your workflow.
+4. **Test and Refine**: Ensure your Langflow flow operates as intended by testing and refining it.
+5. **Deploy and Run**: Deploy your Langflow flow to automate Notion-related tasks and processes.
+
+The Notion integration in Langflow offers a powerful toolset for automation and productivity enhancement. Whether managing tasks, extracting meeting insights, or creating content, Langflow and Notion provide robust solutions for streamlining workflows.
diff --git a/docs/docs/integrations/notion/list-database-properties.md b/docs/docs/integrations/notion/list-database-properties.md
new file mode 100644
index 000000000..830ea3324
--- /dev/null
+++ b/docs/docs/integrations/notion/list-database-properties.md
@@ -0,0 +1,115 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# Database Properties
+
+The `NotionDatabaseProperties` component retrieves properties of a Notion database. It provides a convenient way to integrate Notion database information into your Langflow workflows.
+
+[Notion Reference](https://developers.notion.com/reference/post-database-query)
+
+
+The `NotionDatabaseProperties` component enables you to:
+- Retrieve properties of a Notion database
+- Access the retrieved properties in your Langflow flows
+- Integrate Notion database information seamlessly into your workflows
+
+
+## Component Usage
+
+To use the `NotionDatabaseProperties` component in a Langflow flow, follow these steps:
+
+1. Add the `NotionDatabaseProperties` component to your flow.
+2. Configure the component by providing the required inputs:
+ - `database_id`: The ID of the Notion database you want to retrieve properties from.
+ - `notion_secret`: The Notion integration token for authentication.
+3. Connect the output of the `NotionDatabaseProperties` component to other components in your flow as needed.
+
+## Component Python code
+
+```python
+import requests
+from typing import Dict
+
+from langflow import CustomComponent
+from langflow.schema import Record
+
+
+class NotionDatabaseProperties(CustomComponent):
+ display_name = "List Database Properties [Notion]"
+ description = "Retrieve properties of a Notion database."
+ documentation: str = "https://docs.langflow.org/integrations/notion/list-database-properties"
+ icon = "NotionDirectoryLoader"
+
+ def build_config(self):
+ return {
+ "database_id": {
+ "display_name": "Database ID",
+ "field_type": "str",
+ "info": "The ID of the Notion database.",
+ },
+ "notion_secret": {
+ "display_name": "Notion Secret",
+ "field_type": "str",
+ "info": "The Notion integration token.",
+ "password": True,
+ },
+ }
+
+ def build(
+ self,
+ database_id: str,
+ notion_secret: str,
+ ) -> Record:
+ url = f"https://api.notion.com/v1/databases/{database_id}"
+ headers = {
+ "Authorization": f"Bearer {notion_secret}",
+ "Notion-Version": "2022-06-28", # Use the latest supported version
+ }
+
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ properties = data.get("properties", {})
+
+ record = Record(text=str(response.json()), data=properties)
+ self.status = f"Retrieved {len(properties)} properties from the Notion database.\n {record.text}"
+ return record
+```
+
+## Example Usage
+
+Here's an example of how you can use the `NotionDatabaseProperties` component in a Langflow flow:
+
+
+
+In this example, the `NotionDatabaseProperties` component retrieves the properties of a Notion database, and the retrieved properties are then used as input for subsequent components in the flow.
+
+
+## Best Practices
+
+When using the `NotionDatabaseProperties` component, consider the following best practices:
+
+- Ensure that you have a valid Notion integration token with the necessary permissions to access the desired database.
+- Double-check the database ID to avoid retrieving properties from the wrong database.
+- Handle potential errors gracefully by checking the response status and providing appropriate error messages.
+
+The `NotionDatabaseProperties` component simplifies the process of retrieving properties from a Notion database and integrating them into your Langflow workflows. By leveraging this component, you can easily access and utilize Notion database information in your flows, enabling powerful integrations and automations.
+
+Feel free to explore the capabilities of the `NotionDatabaseProperties` component and experiment with different use cases to enhance your Langflow workflows!
+
+## Troubleshooting
+
+If you encounter any issues while using the `NotionDatabaseProperties` component, consider the following:
+- Verify that the Notion integration token is valid and has the required permissions.
+- Check the database ID to ensure it matches the intended Notion database.
+- Inspect the response from the Notion API for any error messages or status codes that may indicate the cause of the issue.
\ No newline at end of file
diff --git a/docs/docs/integrations/notion/list-pages.md b/docs/docs/integrations/notion/list-pages.md
new file mode 100644
index 000000000..3e219870e
--- /dev/null
+++ b/docs/docs/integrations/notion/list-pages.md
@@ -0,0 +1,178 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# List Pages
+
+The `NotionListPages` component queries a Notion database with filtering and sorting. It provides a convenient way to integrate Notion database querying capabilities into your Langflow workflows.
+
+[Notion Reference](https://developers.notion.com/reference/post-database-query)
+
+
+ The `NotionListPages` component enables you to:
+
+- Query a Notion database with custom filters and sorting options
+- Retrieve specific pages from a Notion database based on the provided criteria
+- Integrate Notion database data seamlessly into your Langflow workflows
+
+
+
+## Component Usage
+
+To use the `NotionListPages
+` component in a Langflow flow, follow these steps:
+
+1. **Add the `NotionListPages
+` component to your flow.**
+2. **Configure the component by providing the required parameters:**
+ - `notion_secret`: The Notion integration token for authentication.
+ - `database_id`: The ID of the Notion database you want to query.
+ - `query_payload`: A JSON string containing the filters and sorting options for the query.
+3. **Connect the `NotionListPages
+` component to other components in your flow as needed.**
+
+## Component Python code
+
+```python
+import requests
+import json
+from typing import Dict, Any, List
+from langflow.custom import CustomComponent
+from langflow.schema import Record
+
+class NotionListPages(CustomComponent):
+ display_name = "List Pages [Notion]"
+ description = (
+ "Query a Notion database with filtering and sorting. "
+ "The input should be a JSON string containing the 'filter' and 'sorts' objects. "
+ "Example input:\n"
+ '{"filter": {"property": "Status", "select": {"equals": "Done"}}, "sorts": [{"timestamp": "created_time", "direction": "descending"}]}'
+ )
+ documentation: str = "https://docs.langflow.org/integrations/notion/list-pages"
+ icon = "NotionDirectoryLoader"
+
+ field_order = [
+ "notion_secret",
+ "database_id",
+ "query_payload",
+ ]
+
+ def build_config(self):
+ return {
+ "notion_secret": {
+ "display_name": "Notion Secret",
+ "field_type": "str",
+ "info": "The Notion integration token.",
+ "password": True,
+ },
+ "database_id": {
+ "display_name": "Database ID",
+ "field_type": "str",
+ "info": "The ID of the Notion database to query.",
+ },
+ "query_payload": {
+ "display_name": "Database query",
+ "field_type": "str",
+ "info": "A JSON string containing the filters that will be used for querying the database. EG: {'filter': {'property': 'Status', 'status': {'equals': 'In progress'}}}",
+ },
+ }
+
+ def build(
+ self,
+ notion_secret: str,
+ database_id: str,
+ query_payload: str = "{}",
+ ) -> List[Record]:
+ try:
+ query_data = json.loads(query_payload)
+ filter_obj = query_data.get("filter")
+ sorts = query_data.get("sorts", [])
+
+ url = f"https://api.notion.com/v1/databases/{database_id}/query"
+ headers = {
+ "Authorization": f"Bearer {notion_secret}",
+ "Content-Type": "application/json",
+ "Notion-Version": "2022-06-28",
+ }
+
+ data = {
+ "sorts": sorts,
+ }
+
+ if filter_obj:
+ data["filter"] = filter_obj
+
+ response = requests.post(url, headers=headers, json=data)
+ response.raise_for_status()
+
+ results = response.json()
+ records = []
+ combined_text = f"Pages found: {len(results['results'])}\n\n"
+ for page in results['results']:
+ page_data = {
+ 'id': page['id'],
+ 'url': page['url'],
+ 'created_time': page['created_time'],
+ 'last_edited_time': page['last_edited_time'],
+ 'properties': page['properties'],
+ }
+
+ text = (
+ f"id: {page['id']}\n"
+ f"url: {page['url']}\n"
+ f"created_time: {page['created_time']}\n"
+ f"last_edited_time: {page['last_edited_time']}\n"
+ f"properties: {json.dumps(page['properties'], indent=2)}\n\n"
+ )
+
+ combined_text += text
+ records.append(Record(text=text, data=page_data))
+
+ self.status = combined_text.strip()
+ return records
+
+ except Exception as e:
+ self.status = f"An error occurred: {str(e)}"
+ return [Record(text=self.status, data=[])]
+```
+
+
+
+## Example Usage
+Here's an example of how you can use the `NotionListPages` component in a Langflow flow and passing to the Prompt component:
+
+
+
+In this example, the `NotionListPages` component is used to retrieve specific pages from a Notion database based on the provided filters and sorting options. The retrieved data can then be processed further in the subsequent components of the flow.
+
+
+## Best Practices
+
+ When using the `NotionListPages
+` component, consider the following best practices:
+
+- Ensure that you have a valid Notion integration token with the necessary permissions to query the desired database.
+- Construct the `query_payload` JSON string carefully, following the Notion API documentation for filtering and sorting options.
+
+The `NotionListPages
+` component provides a powerful way to integrate Notion database querying capabilities into your Langflow workflows. By leveraging this component, you can easily retrieve specific pages from a Notion database based on custom filters and sorting options, enabling you to build more dynamic and data-driven flows.
+
+We encourage you to explore the capabilities of the `NotionListPages
+` component further and experiment with different querying scenarios to unlock the full potential of integrating Notion databases into your Langflow workflows.
+
+## Troubleshooting
+
+ If you encounter any issues while using the `NotionListPages` component, consider the following:
+
+- Double-check that the `notion_secret` and `database_id` are correct and valid.
+- Verify that the `query_payload` JSON string is properly formatted and contains valid filtering and sorting options.
+- Check the Notion API documentation for any updates or changes that may affect the component's functionality.
diff --git a/docs/docs/integrations/notion/list-users.md b/docs/docs/integrations/notion/list-users.md
new file mode 100644
index 000000000..90761239a
--- /dev/null
+++ b/docs/docs/integrations/notion/list-users.md
@@ -0,0 +1,127 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# User List
+
+The `NotionUserList` component retrieves users from Notion. It provides a convenient way to integrate Notion user data into your Langflow workflows.
+
+[Notion Reference](https://developers.notion.com/reference/get-users)
+
+
+ The `NotionUserList` component enables you to:
+
+- Retrieve user data from Notion
+- Access user information such as ID, type, name, and avatar URL
+- Integrate Notion user data seamlessly into your Langflow workflows
+
+
+## Component Usage
+
+To use the `NotionUserList` component in a Langflow flow, follow these steps:
+
+1. Add the `NotionUserList` component to your flow.
+2. Configure the component by providing the required Notion secret token.
+3. Connect the component to other nodes in your flow as needed.
+
+## Component Python code
+
+```python
+import requests
+from typing import List
+
+from langflow import CustomComponent
+from langflow.schema import Record
+
+
+class NotionUserList(CustomComponent):
+ display_name = "List Users [Notion]"
+ description = "Retrieve users from Notion."
+ documentation: str = "https://docs.langflow.org/integrations/notion/list-users"
+ icon = "NotionDirectoryLoader"
+
+ def build_config(self):
+ return {
+ "notion_secret": {
+ "display_name": "Notion Secret",
+ "field_type": "str",
+ "info": "The Notion integration token.",
+ "password": True,
+ },
+ }
+
+ def build(
+ self,
+ notion_secret: str,
+ ) -> List[Record]:
+ url = "https://api.notion.com/v1/users"
+ headers = {
+ "Authorization": f"Bearer {notion_secret}",
+ "Notion-Version": "2022-06-28",
+ }
+
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ results = data['results']
+
+ records = []
+ for user in results:
+ id = user['id']
+ type = user['type']
+ name = user.get('name', '')
+ avatar_url = user.get('avatar_url', '')
+
+ record_data = {
+ "id": id,
+ "type": type,
+ "name": name,
+ "avatar_url": avatar_url,
+ }
+
+ output = "User:\n"
+ for key, value in record_data.items():
+ output += f"{key.replace('_', ' ').title()}: {value}\n"
+ output += "________________________\n"
+
+ record = Record(text=output, data=record_data)
+ records.append(record)
+
+ self.status = "\n".join(record.text for record in records)
+ return records
+```
+
+## Example Usage
+
+Here's an example of how you can use the `NotionUserList` component in a Langflow flow and passing the outputs to the Prompt component:
+
+
+
+
+
+## Best Practices
+
+ When using the `NotionUserList` component, consider the following best practices:
+
+- Ensure that you have a valid Notion integration token with the necessary permissions to retrieve user data.
+- Handle the retrieved user data securely and in compliance with Notion's API usage guidelines.
+
+The `NotionUserList` component provides a seamless way to integrate Notion user data into your Langflow workflows. By leveraging this component, you can easily retrieve and utilize user information from Notion, enhancing the capabilities of your Langflow applications. Feel free to explore and experiment with the `NotionUserList` component to unlock new possibilities in your Langflow projects!
+
+
+## Troubleshooting
+
+ If you encounter any issues while using the `NotionUserList` component, consider the following:
+
+- Double-check that your Notion integration token is valid and has the required permissions.
+- Verify that you have installed the necessary dependencies (`requests`) for the component to function properly.
+- Check the Notion API documentation for any updates or changes that may affect the component's functionality.
\ No newline at end of file
diff --git a/docs/docs/integrations/notion/page-content-viewer.md b/docs/docs/integrations/notion/page-content-viewer.md
new file mode 100644
index 000000000..a38c05fd0
--- /dev/null
+++ b/docs/docs/integrations/notion/page-content-viewer.md
@@ -0,0 +1,142 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# Page Content
+
+The `NotionPageContent` component retrieves the content of a Notion page as plain text. It provides a convenient way to integrate Notion page content into your Langflow workflows.
+
+[Notion Reference](https://developers.notion.com/reference/get-page)
+
+
+
+ The `NotionPageContent` component enables you to:
+
+- Retrieve the content of a Notion page as plain text
+- Extract text from various block types, including paragraphs, headings, lists, and more
+- Integrate Notion page content seamlessly into your Langflow workflows
+
+
+
+## Component Usage
+
+To use the `NotionPageContent` component in a Langflow flow, follow these steps:
+
+1. Add the `NotionPageContent` component to your flow.
+2. Configure the component by providing the required inputs:
+ - `page_id`: The ID of the Notion page you want to retrieve.
+ - `notion_secret`: Your Notion integration token for authentication.
+3. Connect the output of the `NotionPageContent` component to other components in your flow as needed.
+
+## Component Python code
+
+```python
+import requests
+from typing import Dict, Any
+
+from langflow import CustomComponent
+from langflow.schema import Record
+
+
+class NotionPageContent(CustomComponent):
+ display_name = "Page Content Viewer [Notion]"
+ description = "Retrieve the content of a Notion page as plain text."
+ documentation: str = "https://docs.langflow.org/integrations/notion/page-content-viewer"
+ icon = "NotionDirectoryLoader"
+
+ def build_config(self):
+ return {
+ "page_id": {
+ "display_name": "Page ID",
+ "field_type": "str",
+ "info": "The ID of the Notion page to retrieve.",
+ },
+ "notion_secret": {
+ "display_name": "Notion Secret",
+ "field_type": "str",
+ "info": "The Notion integration token.",
+ "password": True,
+ },
+ }
+
+ def build(
+ self,
+ page_id: str,
+ notion_secret: str,
+ ) -> Record:
+ blocks_url = f"https://api.notion.com/v1/blocks/{page_id}/children?page_size=100"
+ headers = {
+ "Authorization": f"Bearer {notion_secret}",
+ "Notion-Version": "2022-06-28", # Use the latest supported version
+ }
+
+ # Retrieve the child blocks
+ blocks_response = requests.get(blocks_url, headers=headers)
+ blocks_response.raise_for_status()
+ blocks_data = blocks_response.json()
+
+ # Parse the blocks and extract the content as plain text
+ content = self.parse_blocks(blocks_data["results"])
+
+ self.status = content
+ return Record(data={"content": content}, text=content)
+
+ def parse_blocks(self, blocks: list) -> str:
+ content = ""
+ for block in blocks:
+ block_type = block["type"]
+ if block_type in ["paragraph", "heading_1", "heading_2", "heading_3", "quote"]:
+ content += self.parse_rich_text(block[block_type]["rich_text"]) + "\n\n"
+ elif block_type in ["bulleted_list_item", "numbered_list_item"]:
+ content += self.parse_rich_text(block[block_type]["rich_text"]) + "\n"
+ elif block_type == "to_do":
+ content += self.parse_rich_text(block["to_do"]["rich_text"]) + "\n"
+ elif block_type == "code":
+ content += self.parse_rich_text(block["code"]["rich_text"]) + "\n\n"
+ elif block_type == "image":
+ content += f"[Image: {block['image']['external']['url']}]\n\n"
+ elif block_type == "divider":
+ content += "---\n\n"
+ return content.strip()
+
+ def parse_rich_text(self, rich_text: list) -> str:
+ text = ""
+ for segment in rich_text:
+ text += segment["plain_text"]
+ return text
+```
+
+## Example Usage
+
+
+
+Here's an example of how you can use the `NotionPageContent` component in a Langflow flow:
+
+
+
+
+## Best Practices
+
+ When using the `NotionPageContent` component, consider the following best practices:
+
+- Ensure that you have the necessary permissions to access the Notion page you want to retrieve.
+- Keep your Notion integration token secure and avoid sharing it publicly.
+- Be mindful of the content you retrieve and ensure that it aligns with your intended use case.
+
+The `NotionPageContent` component provides a seamless way to integrate Notion page content into your Langflow workflows. By leveraging this component, you can easily retrieve and process the content of Notion pages, enabling you to build powerful and dynamic applications. Explore the capabilities of the `NotionPageContent` component and unlock new possibilities in your Langflow projects!
+
+## Troubleshooting
+
+ If you encounter any issues while using the `NotionPageContent` component, consider the following:
+
+- Double-check that you have provided the correct Notion page ID.
+- Verify that your Notion integration token is valid and has the necessary permissions.
+- Check the Notion API documentation for any updates or changes that may affect the component's functionality.
diff --git a/docs/docs/integrations/notion/page-create.md b/docs/docs/integrations/notion/page-create.md
new file mode 100644
index 000000000..0269096b9
--- /dev/null
+++ b/docs/docs/integrations/notion/page-create.md
@@ -0,0 +1,129 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# Page Create
+
+The `NotionPageCreator` component creates pages in a Notion database. It provides a convenient way to integrate Notion page creation into your Langflow workflows.
+
+[Notion Reference](https://developers.notion.com/reference/patch-block-children)
+
+
+The `NotionPageCreator` component enables you to:
+- Create new pages in a specified Notion database
+- Set custom properties for the created pages
+- Retrieve the ID and URL of the newly created pages
+
+
+## Component Usage
+
+To use the `NotionPageCreator` component in a Langflow flow, follow these steps:
+
+1. Add the `NotionPageCreator` component to your flow.
+2. Configure the component by providing the required inputs:
+ - `database_id`: The ID of the Notion database where the pages will be created.
+ - `notion_secret`: The Notion integration token for authentication.
+ - `properties`: The properties of the new page, specified as a JSON string.
+3. Connect the component to other components in your flow as needed.
+4. Run the flow to create Notion pages based on the configured inputs.
+
+## Component Python Code
+
+```python
+import json
+from typing import Optional
+
+import requests
+from langflow.custom import CustomComponent
+
+
+class NotionPageCreator(CustomComponent):
+ display_name = "Create Page [Notion]"
+ description = "A component for creating Notion pages."
+ documentation: str = "https://docs.langflow.org/integrations/notion/page-create"
+ icon = "NotionDirectoryLoader"
+
+ def build_config(self):
+ return {
+ "database_id": {
+ "display_name": "Database ID",
+ "field_type": "str",
+ "info": "The ID of the Notion database.",
+ },
+ "notion_secret": {
+ "display_name": "Notion Secret",
+ "field_type": "str",
+ "info": "The Notion integration token.",
+ "password": True,
+ },
+ "properties": {
+ "display_name": "Properties",
+ "field_type": "str",
+ "info": "The properties of the new page. Depending on your database setup, this can change. E.G: {'Task name': {'id': 'title', 'type': 'title', 'title': [{'type': 'text', 'text': {'content': 'Send Notion Components to LF', 'link': null}}]}}",
+ },
+ }
+
+ def build(
+ self,
+ database_id: str,
+ notion_secret: str,
+ properties: str = '{"Task name": {"id": "title", "type": "title", "title": [{"type": "text", "text": {"content": "Send Notion Components to LF", "link": null}}]}}',
+ ) -> str:
+ if not database_id or not properties:
+ raise ValueError("Invalid input. Please provide 'database_id' and 'properties'.")
+
+ headers = {
+ "Authorization": f"Bearer {notion_secret}",
+ "Content-Type": "application/json",
+ "Notion-Version": "2022-06-28",
+ }
+
+ data = {
+ "parent": {"database_id": database_id},
+ "properties": json.loads(properties),
+ }
+
+ response = requests.post("https://api.notion.com/v1/pages", headers=headers, json=data)
+
+ if response.status_code == 200:
+ page_id = response.json()["id"]
+ self.status = f"Successfully created Notion page with ID: {page_id}\n {str(response.json())}"
+ return response.json()
+ else:
+ error_message = f"Failed to create Notion page. Status code: {response.status_code}, Error: {response.text}"
+ self.status = error_message
+ raise Exception(error_message)
+```
+
+## Example Usage
+
+Here's an example of how to use the `NotionPageCreator` component in a Langflow flow:
+
+
+
+
+## Best Practices
+
+When using the `NotionPageCreator` component, consider the following best practices:
+
+- Ensure that you have a valid Notion integration token with the necessary permissions to create pages in the specified database.
+- Properly format the `properties` input as a JSON string, matching the structure and field types of your Notion database.
+- Handle any errors or exceptions that may occur during the page creation process and provide appropriate error messages.
+- To avoid the hassle of messing with JSON, we recommend using the LLM to create the JSON for you as input.
+
+The `NotionPageCreator` component simplifies the process of creating pages in a Notion database directly from your Langflow workflows. By leveraging this component, you can seamlessly integrate Notion page creation functionality into your automated processes, saving time and effort. Feel free to explore the capabilities of the `NotionPageCreator` component and adapt it to suit your specific requirements.
+
+## Troubleshooting
+
+If you encounter any issues while using the `NotionPageCreator` component, consider the following:
+- Double-check that the `database_id` and `notion_secret` inputs are correct and valid.
+- Verify that the `properties` input is properly formatted as a JSON string and matches the structure of your Notion database.
+- Check the Notion API documentation for any updates or changes that may affect the component's functionality.
\ No newline at end of file
diff --git a/docs/docs/integrations/notion/page-update.md b/docs/docs/integrations/notion/page-update.md
new file mode 100644
index 000000000..3389f64d3
--- /dev/null
+++ b/docs/docs/integrations/notion/page-update.md
@@ -0,0 +1,139 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# Page Update
+
+The `NotionPageUpdate` component updates the properties of a Notion page. It provides a convenient way to integrate updating Notion page properties into your Langflow workflows.
+
+[Notion Reference](https://developers.notion.com/reference/patch-page)
+
+## Component Usage
+
+To use the `NotionPageUpdate` component in your Langflow flow:
+
+1. Drag and drop the `NotionPageUpdate` component onto the canvas.
+2. Double-click the component to open its configuration.
+3. Provide the required parameters as defined in the component's `build_config` method.
+4. Connect the component to other nodes in your flow as needed.
+
+## Component Python Code
+
+```python
+import json
+import requests
+from typing import Dict, Any
+
+from langflow import CustomComponent
+from langflow.schema import Record
+
+
+class NotionPageUpdate(CustomComponent):
+ display_name = "Update Page Property [Notion]"
+ description = "Update the properties of a Notion page."
+ documentation: str = "https://docs.langflow.org/integrations/notion/page-update"
+ icon = "NotionDirectoryLoader"
+
+ def build_config(self):
+ return {
+ "page_id": {
+ "display_name": "Page ID",
+ "field_type": "str",
+ "info": "The ID of the Notion page to update.",
+ },
+ "properties": {
+ "display_name": "Properties",
+ "field_type": "str",
+ "info": "The properties to update on the page (as a JSON string).",
+ "multiline": True,
+ },
+ "notion_secret": {
+ "display_name": "Notion Secret",
+ "field_type": "str",
+ "info": "The Notion integration token.",
+ "password": True,
+ },
+ }
+
+ def build(
+ self,
+ page_id: str,
+ properties: str,
+ notion_secret: str,
+ ) -> Record:
+ url = f"https://api.notion.com/v1/pages/{page_id}"
+ headers = {
+ "Authorization": f"Bearer {notion_secret}",
+ "Content-Type": "application/json",
+ "Notion-Version": "2022-06-28", # Use the latest supported version
+ }
+
+ try:
+ parsed_properties = json.loads(properties)
+ except json.JSONDecodeError as e:
+ raise ValueError("Invalid JSON format for properties") from e
+
+ data = {
+ "properties": parsed_properties
+ }
+
+ response = requests.patch(url, headers=headers, json=data)
+ response.raise_for_status()
+
+ updated_page = response.json()
+
+ output = "Updated page properties:\n"
+ for prop_name, prop_value in updated_page["properties"].items():
+ output += f"{prop_name}: {prop_value}\n"
+
+ self.status = output
+ return Record(data=updated_page)
+```
+
+Let's break down the key parts of this component:
+
+- The `build_config` method defines the configuration fields for the component. It specifies the required parameters and their properties, such as display names, field types, and any additional information or validation.
+
+- The `build` method contains the main logic of the component. It takes the configured parameters as input and performs the necessary operations to update the properties of a Notion page.
+
+- The component interacts with the Notion API to update the page properties. It constructs the API URL, headers, and request data based on the provided parameters.
+
+- The processed data is returned as a `Record` object, which can be connected to other components in the Langflow flow. The `Record` object contains the updated page data.
+
+- The component also stores the updated page properties in the `status` attribute for logging and debugging purposes.
+
+## Example Usage
+
+
+Here's an example of how to use the `NotionPageUpdate` component in a Langflow flow using:
+
+
+
+
+## Best Practices
+
+When using the `NotionPageUpdate` component, consider the following best practices:
+
+- Ensure that you have a valid Notion integration token with the necessary permissions to update page properties.
+- Handle edge cases and error scenarios gracefully, such as invalid JSON format for properties or API request failures.
+- We recommend using an LLM to generate the inputs for this component, to allow flexibilty
+
+By leveraging the `NotionPageUpdate` component in Langflow, you can easily integrate updating Notion page properties into your language model workflows and build powerful applications that extend Langflow's capabilities.
+
+
+## Troubleshooting
+
+If you encounter any issues while using the `NotionPageUpdate` component, consider the following:
+
+- Double-check that you have correctly configured the component with the required parameters, including the page ID, properties JSON, and Notion integration token.
+- Verify that your Notion integration token has the necessary permissions to update page properties.
+- Check the Langflow logs for any error messages or exceptions related to the component, such as invalid JSON format or API request failures.
+- Consult the [Notion API Documentation](https://developers.notion.com/reference/patch-page) for specific troubleshooting steps or common issues related to updating page properties.
diff --git a/docs/docs/integrations/notion/search.md b/docs/docs/integrations/notion/search.md
new file mode 100644
index 000000000..3ff7472dc
--- /dev/null
+++ b/docs/docs/integrations/notion/search.md
@@ -0,0 +1,183 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# Notion Search
+
+The `NotionSearch` component is designed to search all pages and databases that have been shared with an integration in Notion. It provides a convenient way to integrate Notion search capabilities into your Langflow workflows.
+
+[Notion Reference](https://developers.notion.com/reference/search)
+
+
+ The `NotionSearch` component enables you to:
+
+- Search for pages and databases in Notion that have been shared with an integration
+- Filter the search results based on object type (pages or databases)
+- Sort the search results in ascending or descending order based on the last edited time
+
+
+
+## Component Usage
+
+To use the `NotionSearch` component in a Langflow flow, follow these steps:
+
+1. **Add the `NotionSearch` component to your flow.**
+2. **Configure the component by providing the required parameters:**
+ - `notion_secret`: The Notion integration token for authentication.
+ - `query`: The text to search for in page and database titles.
+ - `filter_value`: The type of objects to include in the search results (pages or databases).
+ - `sort_direction`: The direction to sort the search results (ascending or descending).
+3. **Connect the `NotionSearch` component to other components in your flow as needed.**
+
+## Component Python Code
+
+```python
+import requests
+from typing import Dict, Any, List
+from langflow.custom import CustomComponent
+from langflow.schema import Record
+
+class NotionSearch(CustomComponent):
+ display_name = "Search Notion"
+ description = (
+ "Searches all pages and databases that have been shared with an integration."
+ )
+ documentation: str = "https://docs.langflow.org/integrations/notion/search"
+ icon = "NotionDirectoryLoader"
+
+ field_order = [
+ "notion_secret",
+ "query",
+ "filter_value",
+ "sort_direction",
+ ]
+
+ def build_config(self):
+ return {
+ "notion_secret": {
+ "display_name": "Notion Secret",
+ "field_type": "str",
+ "info": "The Notion integration token.",
+ "password": True,
+ },
+ "query": {
+ "display_name": "Search Query",
+ "field_type": "str",
+ "info": "The text that the API compares page and database titles against.",
+ },
+ "filter_value": {
+ "display_name": "Filter Type",
+ "field_type": "str",
+ "info": "Limits the results to either only pages or only databases.",
+ "options": ["page", "database"],
+ "default_value": "page",
+ },
+ "sort_direction": {
+ "display_name": "Sort Direction",
+ "field_type": "str",
+ "info": "The direction to sort the results.",
+ "options": ["ascending", "descending"],
+ "default_value": "descending",
+ },
+ }
+
+ def build(
+ self,
+ notion_secret: str,
+ query: str = "",
+ filter_value: str = "page",
+ sort_direction: str = "descending",
+ ) -> List[Record]:
+ try:
+ url = "https://api.notion.com/v1/search"
+ headers = {
+ "Authorization": f"Bearer {notion_secret}",
+ "Content-Type": "application/json",
+ "Notion-Version": "2022-06-28",
+ }
+
+ data = {
+ "query": query,
+ "filter": {
+ "value": filter_value,
+ "property": "object"
+ },
+ "sort":{
+ "direction": sort_direction,
+ "timestamp": "last_edited_time"
+ }
+ }
+
+ response = requests.post(url, headers=headers, json=data)
+ response.raise_for_status()
+
+ results = response.json()
+ records = []
+ combined_text = f"Results found: {len(results['results'])}\n\n"
+ for result in results['results']:
+ result_data = {
+ 'id': result['id'],
+ 'type': result['object'],
+ 'last_edited_time': result['last_edited_time'],
+ }
+
+ if result['object'] == 'page':
+ result_data['title_or_url'] = result['url']
+ text = f"id: {result['id']}\ntitle_or_url: {result['url']}\n"
+ elif result['object'] == 'database':
+ if 'title' in result and isinstance(result['title'], list) and len(result['title']) > 0:
+ result_data['title_or_url'] = result['title'][0]['plain_text']
+ text = f"id: {result['id']}\ntitle_or_url: {result['title'][0]['plain_text']}\n"
+ else:
+ result_data['title_or_url'] = "N/A"
+ text = f"id: {result['id']}\ntitle_or_url: N/A\n"
+
+ text += f"type: {result['object']}\nlast_edited_time: {result['last_edited_time']}\n\n"
+ combined_text += text
+ records.append(Record(text=text, data=result_data))
+
+ self.status = combined_text
+ return records
+
+ except Exception as e:
+ self.status = f"An error occurred: {str(e)}"
+ return [Record(text=self.status, data=[])]
+```
+
+## Example Usage
+
+Here's an example of how you can use the `NotionSearch` component in a Langflow flow:
+
+
+
+In this example, the `NotionSearch` component is used to search for pages and databases in Notion based on the provided query and filter criteria. The retrieved data can then be processed further in the subsequent components of the flow.
+
+
+## Best Practices
+
+When using the `NotionSearch` component, consider these best practices:
+
+- Ensure you have a valid Notion integration token with the necessary permissions to search for pages and databases.
+- Provide a meaningful search query to narrow down the results to the desired pages or databases.
+- Choose the appropriate filter type (`page` or `database`) based on your search requirements.
+- Consider the sorting direction (`ascending` or `descending`) to organize the search results effectively.
+
+The `NotionSearch` component provides a powerful way to integrate Notion search capabilities into your Langflow workflows. By leveraging this component, you can easily search for pages and databases in Notion based on custom queries and filters, enabling you to build more dynamic and data-driven flows.
+
+We encourage you to explore the capabilities of the `NotionSearch` component further and experiment with different search scenarios to unlock the full potential of integrating Notion search into your Langflow workflows.
+
+## Troubleshooting
+
+If you encounter any issues while using the `NotionSearch` component, consider the following:
+
+- Double-check that the `notion_secret` is correct and valid.
+- Verify that the Notion integration has the necessary permissions to access the desired pages and databases.
+- Check the Notion API documentation for any updates or changes that may affect the component's functionality.
diff --git a/docs/docs/integrations/notion/setup.md b/docs/docs/integrations/notion/setup.md
new file mode 100644
index 000000000..9511d9c81
--- /dev/null
+++ b/docs/docs/integrations/notion/setup.md
@@ -0,0 +1,79 @@
+import Admonition from "@theme/Admonition";
+
+# Setting up a Notion App
+
+To use Notion components in Langflow, you first need to create a Notion integration and configure it with the necessary capabilities. This guide will walk you through the process of setting up a Notion integration and granting it access to your Notion databases.
+
+## Prerequisites
+
+- A Notion account with access to the workspace where you want to use the integration.
+- Admin permissions in the Notion workspace to create and manage integrations.
+
+## Step 1: Create a Notion Integration
+
+1. Go to the [Notion Integrations](https://www.notion.com/my-integrations) page.
+2. Click on the "New integration" button.
+3. Give your integration a name and select the workspace where you want to use it.
+4. Click "Submit" to create the integration.
+
+
+When creating the integration, make sure to enable the necessary capabilities based on your requirements. Refer to the [Notion Integration Capabilities](https://developers.notion.com/reference/capabilities) documentation for more information on each capability.
+
+
+## Step 2: Configure Integration Capabilities
+
+After creating the integration, you need to configure its capabilities to define what actions it can perform and what data it can access.
+
+1. In the integration settings page, go to the **Capabilities** tab.
+2. Enable the required capabilities for your integration. For example:
+ - If your integration needs to read data from Notion, enable the "Read content" capability.
+ - If your integration needs to create new content in Notion, enable the "Insert content" capability.
+ - If your integration needs to update existing content in Notion, enable the "Update content" capability.
+3. Configure the user information access level based on your integration's requirements.
+4. Save the changes.
+
+## Step 3: Obtain Integration Token
+
+To authenticate your integration with Notion, you need to obtain an integration token.
+
+1. In the integration settings page, go to the "Secrets" tab.
+2. Copy the "Internal Integration Token" value. This token will be used to authenticate your integration with Notion.
+
+
+Your integration token is a sensitive piece of information. Make sure to keep it secure and never share it publicly. Store it safely in your Langflow configuration or environment variables.
+
+
+## Step 4: Grant Integration Access to Notion Databases
+
+For your integration to interact with Notion databases, you need to grant it access to the specific databases it will be working with.
+
+1. Open the Notion database that you want your integration to access.
+2. Click on the "Share" button in the top-right corner of the page.
+3. In the "Invite" section, select your integration from the list.
+4. Click "Invite" to grant the integration access to the database.
+
+
+If your database contains references to other databases, you need to grant the integration access to those referenced databases as well. Repeat step 4 for each referenced database to ensure your integration has the necessary access.
+
+
+## Using Notion Components in Langflow
+
+Once you have set up your Notion integration and granted it access to the required databases, you can start using the Notion components in Langflow.
+
+Langflow provides the following Notion components:
+
+- **List Pages**: Retrieves a list of pages from a Notion database.
+- **List Database Properties**: Retrieves the properties of a Notion database.
+- **Add Page Content**: Adds content to a Notion page.
+- **List Users**: Retrieves a list of users with access to a Notion workspace.
+- **Update Property**: Updates the value of a property in a Notion page.
+
+Refer to the individual component documentation for more details on how to use each component in your Langflow flows.
+
+## Additional Resources
+
+- [Notion API Documentation](https://developers.notion.com/docs/getting-started)
+- [Notion Integration Capabilities](https://developers.notion.com/reference/capabilities)
+
+If you encounter any issues or have questions, please reach out to our support team or consult the Langflow community forums.
+
diff --git a/docs/sidebars.js b/docs/sidebars.js
index 7a5d5bdc2..b03fb76e8 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -131,5 +131,28 @@ module.exports = {
"contributing/contribute-component",
],
},
+ {
+ type: "category",
+ label: "Integrations",
+ collapsed: false,
+ items: [
+ {
+ type: "category",
+ label: "Notion",
+ items: [
+ "integrations/notion/intro",
+ "integrations/notion/setup",
+ "integrations/notion/search",
+ "integrations/notion/list-database-properties",
+ "integrations/notion/list-pages",
+ "integrations/notion/list-users",
+ "integrations/notion/page-create",
+ "integrations/notion/add-content-to-page",
+ "integrations/notion/page-update",
+ "integrations/notion/page-content-viewer",
+ ],
+ },
+ ],
+ },
],
};
diff --git a/docs/static/img/notion/AddContentToPage_flow_example.png b/docs/static/img/notion/AddContentToPage_flow_example.png
new file mode 100644
index 000000000..31aadb080
Binary files /dev/null and b/docs/static/img/notion/AddContentToPage_flow_example.png differ
diff --git a/docs/static/img/notion/AddContentToPage_flow_example_dark.png b/docs/static/img/notion/AddContentToPage_flow_example_dark.png
new file mode 100644
index 000000000..0d8809209
Binary files /dev/null and b/docs/static/img/notion/AddContentToPage_flow_example_dark.png differ
diff --git a/docs/static/img/notion/NotionDatabaseProperties_flow_example.png b/docs/static/img/notion/NotionDatabaseProperties_flow_example.png
new file mode 100644
index 000000000..6ec3d7ac1
Binary files /dev/null and b/docs/static/img/notion/NotionDatabaseProperties_flow_example.png differ
diff --git a/docs/static/img/notion/NotionDatabaseProperties_flow_example_dark.png b/docs/static/img/notion/NotionDatabaseProperties_flow_example_dark.png
new file mode 100644
index 000000000..4d3a5a2c9
Binary files /dev/null and b/docs/static/img/notion/NotionDatabaseProperties_flow_example_dark.png differ
diff --git a/docs/static/img/notion/NotionListPages_flow_example.png b/docs/static/img/notion/NotionListPages_flow_example.png
new file mode 100644
index 000000000..c04e3d857
Binary files /dev/null and b/docs/static/img/notion/NotionListPages_flow_example.png differ
diff --git a/docs/static/img/notion/NotionListPages_flow_example_dark.png b/docs/static/img/notion/NotionListPages_flow_example_dark.png
new file mode 100644
index 000000000..ee041bde7
Binary files /dev/null and b/docs/static/img/notion/NotionListPages_flow_example_dark.png differ
diff --git a/docs/static/img/notion/NotionPageContent_flow_example.png b/docs/static/img/notion/NotionPageContent_flow_example.png
new file mode 100644
index 000000000..5d89af125
Binary files /dev/null and b/docs/static/img/notion/NotionPageContent_flow_example.png differ
diff --git a/docs/static/img/notion/NotionPageContent_flow_example_dark.png b/docs/static/img/notion/NotionPageContent_flow_example_dark.png
new file mode 100644
index 000000000..144c1e0ed
Binary files /dev/null and b/docs/static/img/notion/NotionPageContent_flow_example_dark.png differ
diff --git a/docs/static/img/notion/NotionPageCreator_flow_example.png b/docs/static/img/notion/NotionPageCreator_flow_example.png
new file mode 100644
index 000000000..1cc14788a
Binary files /dev/null and b/docs/static/img/notion/NotionPageCreator_flow_example.png differ
diff --git a/docs/static/img/notion/NotionPageCreator_flow_example_dark.png b/docs/static/img/notion/NotionPageCreator_flow_example_dark.png
new file mode 100644
index 000000000..97788dbc0
Binary files /dev/null and b/docs/static/img/notion/NotionPageCreator_flow_example_dark.png differ
diff --git a/docs/static/img/notion/NotionPageUpdate_flow_example.png b/docs/static/img/notion/NotionPageUpdate_flow_example.png
new file mode 100644
index 000000000..dd02f9bba
Binary files /dev/null and b/docs/static/img/notion/NotionPageUpdate_flow_example.png differ
diff --git a/docs/static/img/notion/NotionPageUpdate_flow_example_dark.png b/docs/static/img/notion/NotionPageUpdate_flow_example_dark.png
new file mode 100644
index 000000000..bc37ff236
Binary files /dev/null and b/docs/static/img/notion/NotionPageUpdate_flow_example_dark.png differ
diff --git a/docs/static/img/notion/NotionSearch_flow_example.png b/docs/static/img/notion/NotionSearch_flow_example.png
new file mode 100644
index 000000000..95e6c72a7
Binary files /dev/null and b/docs/static/img/notion/NotionSearch_flow_example.png differ
diff --git a/docs/static/img/notion/NotionSearch_flow_example_dark.png b/docs/static/img/notion/NotionSearch_flow_example_dark.png
new file mode 100644
index 000000000..924aff55b
Binary files /dev/null and b/docs/static/img/notion/NotionSearch_flow_example_dark.png differ
diff --git a/docs/static/img/notion/NotionUserList_flow_example.png b/docs/static/img/notion/NotionUserList_flow_example.png
new file mode 100644
index 000000000..e0fbd8579
Binary files /dev/null and b/docs/static/img/notion/NotionUserList_flow_example.png differ
diff --git a/docs/static/img/notion/NotionUserList_flow_example_dark.png b/docs/static/img/notion/NotionUserList_flow_example_dark.png
new file mode 100644
index 000000000..d59e7d9a8
Binary files /dev/null and b/docs/static/img/notion/NotionUserList_flow_example_dark.png differ
diff --git a/docs/static/img/notion/notion_components_bundle.png b/docs/static/img/notion/notion_components_bundle.png
new file mode 100644
index 000000000..f924ed14a
Binary files /dev/null and b/docs/static/img/notion/notion_components_bundle.png differ
diff --git a/docs/static/img/notion/notion_components_bundle_dark.png b/docs/static/img/notion/notion_components_bundle_dark.png
new file mode 100644
index 000000000..048646bdb
Binary files /dev/null and b/docs/static/img/notion/notion_components_bundle_dark.png differ
diff --git a/docs/static/json_files/Notion_Components_bundle.json b/docs/static/json_files/Notion_Components_bundle.json
new file mode 100644
index 000000000..21181187c
--- /dev/null
+++ b/docs/static/json_files/Notion_Components_bundle.json
@@ -0,0 +1 @@
+{"id":"7cd51434-9767-450f-8742-27857367f8c2","data":{"nodes":[{"id":"RecordsToText-Q69g5","type":"genericNode","position":{"x":-2671.5528488127866,"y":-963.4266471378126},"data":{"type":"RecordsToText","node":{"template":{"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import requests\r\nfrom typing import List\r\n\r\nfrom langflow import CustomComponent\r\nfrom langflow.schema import Record\r\n\r\n\r\nclass NotionUserList(CustomComponent):\r\n display_name = \"List Users [Notion]\"\r\n description = \"Retrieve users from Notion.\"\r\n documentation: str = \"https://docs.langflow.org/integrations/notion/list-users\"\r\n icon = \"NotionDirectoryLoader\"\r\n \r\n def build_config(self):\r\n return {\r\n \"notion_secret\": {\r\n \"display_name\": \"Notion Secret\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The Notion integration token.\",\r\n \"password\": True,\r\n },\r\n }\r\n\r\n def build(\r\n self,\r\n notion_secret: str,\r\n ) -> List[Record]:\r\n url = \"https://api.notion.com/v1/users\"\r\n headers = {\r\n \"Authorization\": f\"Bearer {notion_secret}\",\r\n \"Notion-Version\": \"2022-06-28\",\r\n }\r\n\r\n response = requests.get(url, headers=headers)\r\n response.raise_for_status()\r\n\r\n data = response.json()\r\n results = data['results']\r\n\r\n records = []\r\n for user in results:\r\n id = user['id']\r\n type = user['type']\r\n name = user.get('name', '')\r\n avatar_url = user.get('avatar_url', '')\r\n\r\n record_data = {\r\n \"id\": id,\r\n \"type\": type,\r\n \"name\": name,\r\n \"avatar_url\": avatar_url,\r\n }\r\n\r\n output = \"User:\\n\"\r\n for key, value in record_data.items():\r\n output += f\"{key.replace('_', ' ').title()}: {value}\\n\"\r\n output += \"________________________\\n\"\r\n\r\n record = Record(text=output, data=record_data)\r\n records.append(record)\r\n\r\n self.status = \"\\n\".join(record.text for record in records)\r\n return records","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"notion_secret":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"notion_secret","display_name":"Notion Secret","advanced":false,"dynamic":false,"info":"The Notion integration token.","load_from_db":false,"title_case":false,"input_types":["Text"],"value":""},"_type":"CustomComponent"},"description":"Retrieve users from Notion.","icon":"NotionDirectoryLoader","base_classes":["Record"],"display_name":"List Users [Notion] ","documentation":"https://docs.langflow.org/integrations/notion/list-users","custom_fields":{"notion_secret":null},"output_types":["Record"],"field_formatters":{},"frozen":false,"field_order":[],"beta":false},"id":"RecordsToText-Q69g5","description":"Retrieve users from Notion.","display_name":"List Users [Notion] "},"selected":false,"width":384,"height":289,"dragging":false,"positionAbsolute":{"x":-2671.5528488127866,"y":-963.4266471378126}},{"id":"CustomComponent-PU0K5","type":"genericNode","position":{"x":-3077.2269116193215,"y":-960.9450220159636},"data":{"type":"CustomComponent","node":{"template":{"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import json\r\nfrom typing import Optional\r\n\r\nimport requests\r\nfrom langflow.custom import CustomComponent\r\n\r\n\r\nclass NotionPageCreator(CustomComponent):\r\n display_name = \"Create Page [Notion]\"\r\n description = \"A component for creating Notion pages.\"\r\n documentation: str = \"https://docs.langflow.org/integrations/notion/page-create\"\r\n icon = \"NotionDirectoryLoader\"\r\n\r\n def build_config(self):\r\n return {\r\n \"database_id\": {\r\n \"display_name\": \"Database ID\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The ID of the Notion database.\",\r\n },\r\n \"notion_secret\": {\r\n \"display_name\": \"Notion Secret\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The Notion integration token.\",\r\n \"password\": True,\r\n },\r\n \"properties\": {\r\n \"display_name\": \"Properties\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The properties of the new page. Depending on your database setup, this can change. E.G: {'Task name': {'id': 'title', 'type': 'title', 'title': [{'type': 'text', 'text': {'content': 'Send Notion Components to LF', 'link': null}}]}}\",\r\n },\r\n }\r\n\r\n def build(\r\n self,\r\n database_id: str,\r\n notion_secret: str,\r\n properties: str = '{\"Task name\": {\"id\": \"title\", \"type\": \"title\", \"title\": [{\"type\": \"text\", \"text\": {\"content\": \"Send Notion Components to LF\", \"link\": null}}]}}',\r\n ) -> str:\r\n if not database_id or not properties:\r\n raise ValueError(\"Invalid input. Please provide 'database_id' and 'properties'.\")\r\n\r\n headers = {\r\n \"Authorization\": f\"Bearer {notion_secret}\",\r\n \"Content-Type\": \"application/json\",\r\n \"Notion-Version\": \"2022-06-28\",\r\n }\r\n\r\n data = {\r\n \"parent\": {\"database_id\": database_id},\r\n \"properties\": json.loads(properties),\r\n }\r\n\r\n response = requests.post(\"https://api.notion.com/v1/pages\", headers=headers, json=data)\r\n\r\n if response.status_code == 200:\r\n page_id = response.json()[\"id\"]\r\n self.status = f\"Successfully created Notion page with ID: {page_id}\\n {str(response.json())}\"\r\n return response.json()\r\n else:\r\n error_message = f\"Failed to create Notion page. Status code: {response.status_code}, Error: {response.text}\"\r\n self.status = error_message\r\n raise Exception(error_message)","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"database_id":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"database_id","display_name":"Database ID","advanced":false,"dynamic":false,"info":"The ID of the Notion database.","load_from_db":false,"title_case":false,"input_types":["Text"]},"notion_secret":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"notion_secret","display_name":"Notion Secret","advanced":false,"dynamic":false,"info":"The Notion integration token.","load_from_db":false,"title_case":false,"input_types":["Text"],"value":""},"properties":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":"{\"Task name\": {\"id\": \"title\", \"type\": \"title\", \"title\": [{\"type\": \"text\", \"text\": {\"content\": \"Send Notion Components to LF\", \"link\": null}}]}}","fileTypes":[],"file_path":"","password":false,"name":"properties","display_name":"Properties","advanced":false,"dynamic":false,"info":"The properties of the new page. Depending on your database setup, this can change. E.G: {'Task name': {'id': 'title', 'type': 'title', 'title': [{'type': 'text', 'text': {'content': 'Send Notion Components to LF', 'link': null}}]}}","load_from_db":false,"title_case":false,"input_types":["Text"]},"_type":"CustomComponent"},"description":"A component for creating Notion pages.","icon":"NotionDirectoryLoader","base_classes":["object","str","Text"],"display_name":"Create Page [Notion] ","documentation":"https://docs.langflow.org/integrations/notion/page-create","custom_fields":{"database_id":null,"notion_secret":null,"properties":null},"output_types":["Text"],"field_formatters":{},"frozen":false,"field_order":[],"beta":false},"id":"CustomComponent-PU0K5","description":"A component for creating Notion pages.","display_name":"Create Page [Notion] "},"selected":false,"width":384,"height":477,"positionAbsolute":{"x":-3077.2269116193215,"y":-960.9450220159636},"dragging":false},{"id":"CustomComponent-YODla","type":"genericNode","position":{"x":-3485.297183150799,"y":-362.8525892356713},"data":{"type":"CustomComponent","node":{"template":{"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import requests\r\nfrom typing import Dict\r\n\r\nfrom langflow import CustomComponent\r\nfrom langflow.schema import Record\r\n\r\n\r\nclass NotionDatabaseProperties(CustomComponent):\r\n display_name = \"List Database Properties [Notion]\"\r\n description = \"Retrieve properties of a Notion database.\"\r\n documentation: str = \"https://docs.langflow.org/integrations/notion/list-database-properties\"\r\n icon = \"NotionDirectoryLoader\"\r\n \r\n def build_config(self):\r\n return {\r\n \"database_id\": {\r\n \"display_name\": \"Database ID\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The ID of the Notion database.\",\r\n },\r\n \"notion_secret\": {\r\n \"display_name\": \"Notion Secret\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The Notion integration token.\",\r\n \"password\": True,\r\n },\r\n }\r\n\r\n def build(\r\n self,\r\n database_id: str,\r\n notion_secret: str,\r\n ) -> Record:\r\n url = f\"https://api.notion.com/v1/databases/{database_id}\"\r\n headers = {\r\n \"Authorization\": f\"Bearer {notion_secret}\",\r\n \"Notion-Version\": \"2022-06-28\", # Use the latest supported version\r\n }\r\n\r\n response = requests.get(url, headers=headers)\r\n response.raise_for_status()\r\n\r\n data = response.json()\r\n properties = data.get(\"properties\", {})\r\n\r\n record = Record(text=str(response.json()), data=properties)\r\n self.status = f\"Retrieved {len(properties)} properties from the Notion database.\\n {record.text}\"\r\n return record","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"database_id":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"database_id","display_name":"Database ID","advanced":false,"dynamic":false,"info":"The ID of the Notion database.","load_from_db":true,"title_case":false,"input_types":["Text"],"value":"NOTION_NMSTX_DB_ID"},"notion_secret":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"notion_secret","display_name":"Notion Secret","advanced":false,"dynamic":false,"info":"The Notion integration token.","load_from_db":true,"title_case":false,"input_types":["Text"],"value":""},"_type":"CustomComponent"},"description":"Retrieve properties of a Notion database.","icon":"NotionDirectoryLoader","base_classes":["Record"],"display_name":"List Database Properties [Notion] ","documentation":"https://docs.langflow.org/integrations/notion/list-database-properties","custom_fields":{"database_id":null,"notion_secret":null},"output_types":["Record"],"field_formatters":{},"frozen":false,"field_order":[],"beta":false},"id":"CustomComponent-YODla","description":"Retrieve properties of a Notion database.","display_name":"List Database Properties [Notion] "},"selected":true,"width":384,"height":383,"dragging":false,"positionAbsolute":{"x":-3485.297183150799,"y":-362.8525892356713}},{"id":"CustomComponent-wHlSz","type":"genericNode","position":{"x":-2668.7714642455403,"y":-657.2376228212606},"data":{"type":"CustomComponent","node":{"template":{"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import json\r\nimport requests\r\nfrom typing import Dict, Any\r\n\r\nfrom langflow import CustomComponent\r\nfrom langflow.schema import Record\r\n\r\n\r\nclass NotionPageUpdate(CustomComponent):\r\n display_name = \"Update Page Property [Notion]\"\r\n description = \"Update the properties of a Notion page.\"\r\n documentation: str = \"https://docs.langflow.org/integrations/notion/page-update\"\r\n icon = \"NotionDirectoryLoader\"\r\n\r\n def build_config(self):\r\n return {\r\n \"page_id\": {\r\n \"display_name\": \"Page ID\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The ID of the Notion page to update.\",\r\n },\r\n \"properties\": {\r\n \"display_name\": \"Properties\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The properties to update on the page (as a JSON string).\",\r\n \"multiline\": True,\r\n },\r\n \"notion_secret\": {\r\n \"display_name\": \"Notion Secret\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The Notion integration token.\",\r\n \"password\": True,\r\n },\r\n }\r\n\r\n def build(\r\n self,\r\n page_id: str,\r\n properties: str,\r\n notion_secret: str,\r\n ) -> Record:\r\n url = f\"https://api.notion.com/v1/pages/{page_id}\"\r\n headers = {\r\n \"Authorization\": f\"Bearer {notion_secret}\",\r\n \"Content-Type\": \"application/json\",\r\n \"Notion-Version\": \"2022-06-28\", # Use the latest supported version\r\n }\r\n\r\n try:\r\n parsed_properties = json.loads(properties)\r\n except json.JSONDecodeError as e:\r\n raise ValueError(\"Invalid JSON format for properties\") from e\r\n\r\n data = {\r\n \"properties\": parsed_properties\r\n }\r\n\r\n response = requests.patch(url, headers=headers, json=data)\r\n response.raise_for_status()\r\n\r\n updated_page = response.json()\r\n\r\n output = \"Updated page properties:\\n\"\r\n for prop_name, prop_value in updated_page[\"properties\"].items():\r\n output += f\"{prop_name}: {prop_value}\\n\"\r\n\r\n self.status = output\r\n return Record(data=updated_page)","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"notion_secret":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"notion_secret","display_name":"Notion Secret","advanced":false,"dynamic":false,"info":"The Notion integration token.","load_from_db":true,"title_case":false,"input_types":["Text"],"value":""},"page_id":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"page_id","display_name":"Page ID","advanced":false,"dynamic":false,"info":"The ID of the Notion page to update.","load_from_db":false,"title_case":false,"input_types":["Text"]},"properties":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"fileTypes":[],"file_path":"","password":false,"name":"properties","display_name":"Properties","advanced":false,"dynamic":false,"info":"The properties to update on the page (as a JSON string).","load_from_db":false,"title_case":false,"input_types":["Text"],"value":"{ \"title\": [ { \"text\": { \"content\": \"Test Page\" } } ] }"},"_type":"CustomComponent"},"description":"Update the properties of a Notion page.","icon":"NotionDirectoryLoader","base_classes":["Record"],"display_name":"Update Page Property [Notion]","documentation":"https://docs.langflow.org/integrations/notion/page-update","custom_fields":{"page_id":null,"properties":null,"notion_secret":null},"output_types":["Record"],"field_formatters":{},"frozen":false,"field_order":[],"beta":false},"id":"CustomComponent-wHlSz","description":"Update the properties of a Notion page.","display_name":"Update Page Property [Notion]"},"selected":false,"width":384,"height":477,"dragging":false,"positionAbsolute":{"x":-2668.7714642455403,"y":-657.2376228212606}},{"id":"CustomComponent-oelYw","type":"genericNode","position":{"x":-2253.1007124701327,"y":-448.47240118604134},"data":{"type":"CustomComponent","node":{"template":{"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import requests\r\nfrom typing import Dict, Any\r\n\r\nfrom langflow import CustomComponent\r\nfrom langflow.schema import Record\r\n\r\n\r\nclass NotionPageContent(CustomComponent):\r\n display_name = \"Page Content Viewer [Notion]\"\r\n description = \"Retrieve the content of a Notion page as plain text.\"\r\n documentation: str = \"https://docs.langflow.org/integrations/notion/page-content-viewer\"\r\n icon = \"NotionDirectoryLoader\"\r\n\r\n def build_config(self):\r\n return {\r\n \"page_id\": {\r\n \"display_name\": \"Page ID\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The ID of the Notion page to retrieve.\",\r\n },\r\n \"notion_secret\": {\r\n \"display_name\": \"Notion Secret\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The Notion integration token.\",\r\n \"password\": True,\r\n },\r\n }\r\n\r\n def build(\r\n self,\r\n page_id: str,\r\n notion_secret: str,\r\n ) -> Record:\r\n blocks_url = f\"https://api.notion.com/v1/blocks/{page_id}/children?page_size=100\"\r\n headers = {\r\n \"Authorization\": f\"Bearer {notion_secret}\",\r\n \"Notion-Version\": \"2022-06-28\", # Use the latest supported version\r\n }\r\n\r\n # Retrieve the child blocks\r\n blocks_response = requests.get(blocks_url, headers=headers)\r\n blocks_response.raise_for_status()\r\n blocks_data = blocks_response.json()\r\n\r\n # Parse the blocks and extract the content as plain text\r\n content = self.parse_blocks(blocks_data[\"results\"])\r\n\r\n self.status = content\r\n return Record(data={\"content\": content}, text=content)\r\n\r\n def parse_blocks(self, blocks: list) -> str:\r\n content = \"\"\r\n for block in blocks:\r\n block_type = block[\"type\"]\r\n if block_type in [\"paragraph\", \"heading_1\", \"heading_2\", \"heading_3\", \"quote\"]:\r\n content += self.parse_rich_text(block[block_type][\"rich_text\"]) + \"\\n\\n\"\r\n elif block_type in [\"bulleted_list_item\", \"numbered_list_item\"]:\r\n content += self.parse_rich_text(block[block_type][\"rich_text\"]) + \"\\n\"\r\n elif block_type == \"to_do\":\r\n content += self.parse_rich_text(block[\"to_do\"][\"rich_text\"]) + \"\\n\"\r\n elif block_type == \"code\":\r\n content += self.parse_rich_text(block[\"code\"][\"rich_text\"]) + \"\\n\\n\"\r\n elif block_type == \"image\":\r\n content += f\"[Image: {block['image']['external']['url']}]\\n\\n\"\r\n elif block_type == \"divider\":\r\n content += \"---\\n\\n\"\r\n return content.strip()\r\n\r\n def parse_rich_text(self, rich_text: list) -> str:\r\n text = \"\"\r\n for segment in rich_text:\r\n text += segment[\"plain_text\"]\r\n return text","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"notion_secret":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"notion_secret","display_name":"Notion Secret","advanced":false,"dynamic":false,"info":"The Notion integration token.","load_from_db":true,"title_case":false,"input_types":["Text"],"value":""},"page_id":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"page_id","display_name":"Page ID","advanced":false,"dynamic":false,"info":"The ID of the Notion page to retrieve.","load_from_db":false,"title_case":false,"input_types":["Text"]},"_type":"CustomComponent"},"description":"Retrieve the content of a Notion page as plain text.","icon":"NotionDirectoryLoader","base_classes":["Record"],"display_name":"Page Content Viewer [Notion] ","documentation":"https://docs.langflow.org/integrations/notion/page-content-viewer","custom_fields":{"page_id":null,"notion_secret":null},"output_types":["Record"],"field_formatters":{},"frozen":false,"field_order":[],"beta":false},"id":"CustomComponent-oelYw","description":"Retrieve the content of a Notion page as plain text.","display_name":"Page Content Viewer [Notion] "},"selected":false,"width":384,"height":383,"positionAbsolute":{"x":-2253.1007124701327,"y":-448.47240118604134},"dragging":false},{"id":"CustomComponent-Pn52w","type":"genericNode","position":{"x":-3070.9222948695096,"y":-472.4537855763852},"data":{"type":"CustomComponent","node":{"template":{"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import requests\r\nimport json\r\nfrom typing import Dict, Any, List\r\nfrom langflow.custom import CustomComponent\r\nfrom langflow.schema import Record\r\n\r\nclass NotionListPages(CustomComponent):\r\n display_name = \"List Pages [Notion]\"\r\n description = (\r\n \"Query a Notion database with filtering and sorting. \"\r\n \"The input should be a JSON string containing the 'filter' and 'sorts' objects. \"\r\n \"Example input:\\n\"\r\n '{\"filter\": {\"property\": \"Status\", \"select\": {\"equals\": \"Done\"}}, \"sorts\": [{\"timestamp\": \"created_time\", \"direction\": \"descending\"}]}'\r\n )\r\n documentation: str = \"https://docs.langflow.org/integrations/notion/list-pages\"\r\n icon = \"NotionDirectoryLoader\"\r\n\r\n field_order = [\r\n \"notion_secret\",\r\n \"database_id\",\r\n \"query_payload\",\r\n ]\r\n\r\n def build_config(self):\r\n return {\r\n \"notion_secret\": {\r\n \"display_name\": \"Notion Secret\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The Notion integration token.\",\r\n \"password\": True,\r\n },\r\n \"database_id\": {\r\n \"display_name\": \"Database ID\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The ID of the Notion database to query.\",\r\n },\r\n \"query_payload\": {\r\n \"display_name\": \"Database query\",\r\n \"field_type\": \"str\",\r\n \"info\": \"A JSON string containing the filters that will be used for querying the database. EG: {'filter': {'property': 'Status', 'status': {'equals': 'In progress'}}}\",\r\n },\r\n }\r\n\r\n def build(\r\n self,\r\n notion_secret: str,\r\n database_id: str,\r\n query_payload: str = \"{}\",\r\n ) -> List[Record]:\r\n try:\r\n query_data = json.loads(query_payload)\r\n filter_obj = query_data.get(\"filter\")\r\n sorts = query_data.get(\"sorts\", [])\r\n\r\n url = f\"https://api.notion.com/v1/databases/{database_id}/query\"\r\n headers = {\r\n \"Authorization\": f\"Bearer {notion_secret}\",\r\n \"Content-Type\": \"application/json\",\r\n \"Notion-Version\": \"2022-06-28\",\r\n }\r\n\r\n data = {\r\n \"sorts\": sorts,\r\n }\r\n\r\n if filter_obj:\r\n data[\"filter\"] = filter_obj\r\n\r\n response = requests.post(url, headers=headers, json=data)\r\n response.raise_for_status()\r\n\r\n results = response.json()\r\n records = []\r\n combined_text = f\"Pages found: {len(results['results'])}\\n\\n\"\r\n for page in results['results']:\r\n page_data = {\r\n 'id': page['id'],\r\n 'url': page['url'],\r\n 'created_time': page['created_time'],\r\n 'last_edited_time': page['last_edited_time'],\r\n 'properties': page['properties'],\r\n }\r\n\r\n text = (\r\n f\"id: {page['id']}\\n\"\r\n f\"url: {page['url']}\\n\"\r\n f\"created_time: {page['created_time']}\\n\"\r\n f\"last_edited_time: {page['last_edited_time']}\\n\"\r\n f\"properties: {json.dumps(page['properties'], indent=2)}\\n\\n\"\r\n )\r\n\r\n combined_text += text\r\n records.append(Record(text=text, data=page_data))\r\n \r\n self.status = combined_text.strip()\r\n return records\r\n\r\n except Exception as e:\r\n self.status = f\"An error occurred: {str(e)}\"\r\n return [Record(text=self.status, data=[])]","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"database_id":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"database_id","display_name":"Database ID","advanced":false,"dynamic":false,"info":"The ID of the Notion database to query.","load_from_db":true,"title_case":false,"input_types":["Text"],"value":"NOTION_NMSTX_DB_ID"},"notion_secret":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"notion_secret","display_name":"Notion Secret","advanced":false,"dynamic":false,"info":"The Notion integration token.","load_from_db":true,"title_case":false,"input_types":["Text"],"value":""},"query_payload":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":{},"fileTypes":[],"file_path":"","password":false,"name":"query_payload","display_name":"Database query","advanced":false,"dynamic":false,"info":"A JSON string containing the filters that will be used for querying the database. EG: {'filter': {'property': 'Status', 'status': {'equals': 'In progress'}}}","load_from_db":false,"title_case":false,"input_types":["Text"]},"_type":"CustomComponent"},"description":"Query a Notion database with filtering and sorting. The input should be a JSON string containing the 'filter' and 'sorts' objects. Example input:\n{\"filter\": {\"property\": \"Status\", \"select\": {\"equals\": \"Done\"}}, \"sorts\": [{\"timestamp\": \"created_time\", \"direction\": \"descending\"}]}","icon":"NotionDirectoryLoader","base_classes":["Record"],"display_name":"List Pages [Notion] ","documentation":"https://docs.langflow.org/integrations/notion/list-pages","custom_fields":{"notion_secret":null,"database_id":null,"query_payload":null},"output_types":["Record"],"field_formatters":{},"frozen":false,"field_order":["notion_secret","database_id","query_payload"],"beta":false},"id":"CustomComponent-Pn52w","description":"Query a Notion database with filtering and sorting. The input should be a JSON string containing the 'filter' and 'sorts' objects. Example input:\n{\"filter\": {\"property\": \"Status\", \"select\": {\"equals\": \"Done\"}}, \"sorts\": [{\"timestamp\": \"created_time\", \"direction\": \"descending\"}]}","display_name":"List Pages [Notion] "},"selected":false,"width":384,"height":517,"positionAbsolute":{"x":-3070.9222948695096,"y":-472.4537855763852},"dragging":false},{"id":"CustomComponent-I8Dec","type":"genericNode","position":{"x":-2256.686402636563,"y":-963.4541117792749},"data":{"type":"CustomComponent","node":{"template":{"block_id":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"block_id","display_name":"Page/Block ID","advanced":false,"dynamic":false,"info":"The ID of the page/block to add the content.","load_from_db":false,"title_case":false,"input_types":["Text"]},"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import json\r\nfrom typing import List, Dict, Any\r\nfrom markdown import markdown\r\nfrom bs4 import BeautifulSoup\r\nimport requests\r\n\r\nfrom langflow import CustomComponent\r\nfrom langflow.schema import Record\r\n\r\nclass AddContentToPage(CustomComponent):\r\n display_name = \"Add Content to Page [Notion]\"\r\n description = \"Convert markdown text to Notion blocks and append them to a Notion page.\"\r\n documentation: str = \"https://developers.notion.com/reference/patch-block-children\"\r\n icon = \"NotionDirectoryLoader\"\r\n\r\n def build_config(self):\r\n return {\r\n \"markdown_text\": {\r\n \"display_name\": \"Markdown Text\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The markdown text to convert to Notion blocks.\",\r\n \"multiline\": True,\r\n },\r\n \"block_id\": {\r\n \"display_name\": \"Page/Block ID\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The ID of the page/block to add the content.\",\r\n },\r\n \"notion_secret\": {\r\n \"display_name\": \"Notion Secret\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The Notion integration token.\",\r\n \"password\": True,\r\n },\r\n }\r\n\r\n def build(self, markdown_text: str, block_id: str, notion_secret: str) -> Record:\r\n html_text = markdown(markdown_text)\r\n soup = BeautifulSoup(html_text, 'html.parser')\r\n blocks = self.process_node(soup)\r\n\r\n url = f\"https://api.notion.com/v1/blocks/{block_id}/children\"\r\n headers = {\r\n \"Authorization\": f\"Bearer {notion_secret}\",\r\n \"Content-Type\": \"application/json\",\r\n \"Notion-Version\": \"2022-06-28\",\r\n }\r\n\r\n data = {\r\n \"children\": blocks,\r\n }\r\n\r\n response = requests.patch(url, headers=headers, json=data)\r\n self.status = str(response.json())\r\n response.raise_for_status()\r\n\r\n result = response.json()\r\n self.status = f\"Appended {len(blocks)} blocks to page with ID: {block_id}\"\r\n return Record(data=result, text=json.dumps(result))\r\n\r\n def process_node(self, node):\r\n blocks = []\r\n if isinstance(node, str):\r\n text = node.strip()\r\n if text:\r\n if text.startswith('#'):\r\n heading_level = text.count('#', 0, 6)\r\n heading_text = text[heading_level:].strip()\r\n if heading_level == 1:\r\n blocks.append(self.create_block('heading_1', heading_text))\r\n elif heading_level == 2:\r\n blocks.append(self.create_block('heading_2', heading_text))\r\n elif heading_level == 3:\r\n blocks.append(self.create_block('heading_3', heading_text))\r\n else:\r\n blocks.append(self.create_block('paragraph', text))\r\n elif node.name == 'h1':\r\n blocks.append(self.create_block('heading_1', node.get_text(strip=True)))\r\n elif node.name == 'h2':\r\n blocks.append(self.create_block('heading_2', node.get_text(strip=True)))\r\n elif node.name == 'h3':\r\n blocks.append(self.create_block('heading_3', node.get_text(strip=True)))\r\n elif node.name == 'p':\r\n code_node = node.find('code')\r\n if code_node:\r\n code_text = code_node.get_text()\r\n language, code = self.extract_language_and_code(code_text)\r\n blocks.append(self.create_block('code', code, language=language))\r\n elif self.is_table(str(node)):\r\n blocks.extend(self.process_table(node))\r\n else:\r\n blocks.append(self.create_block('paragraph', node.get_text(strip=True)))\r\n elif node.name == 'ul':\r\n blocks.extend(self.process_list(node, 'bulleted_list_item'))\r\n elif node.name == 'ol':\r\n blocks.extend(self.process_list(node, 'numbered_list_item'))\r\n elif node.name == 'blockquote':\r\n blocks.append(self.create_block('quote', node.get_text(strip=True)))\r\n elif node.name == 'hr':\r\n blocks.append(self.create_block('divider', ''))\r\n elif node.name == 'img':\r\n blocks.append(self.create_block('image', '', image_url=node.get('src')))\r\n elif node.name == 'a':\r\n blocks.append(self.create_block('bookmark', node.get_text(strip=True), link_url=node.get('href')))\r\n elif node.name == 'table':\r\n blocks.extend(self.process_table(node))\r\n\r\n for child in node.children:\r\n if isinstance(child, str):\r\n continue\r\n blocks.extend(self.process_node(child))\r\n\r\n return blocks\r\n\r\n def extract_language_and_code(self, code_text):\r\n lines = code_text.split('\\n')\r\n language = lines[0].strip()\r\n code = '\\n'.join(lines[1:]).strip()\r\n return language, code\r\n\r\n def is_code_block(self, text):\r\n return text.startswith('```')\r\n\r\n def extract_code_block(self, text):\r\n lines = text.split('\\n')\r\n language = lines[0].strip('`').strip()\r\n code = '\\n'.join(lines[1:]).strip('`').strip()\r\n return language, code\r\n \r\n def is_table(self, text):\r\n rows = text.split('\\n')\r\n if len(rows) < 2:\r\n return False\r\n\r\n has_separator = False\r\n for i, row in enumerate(rows):\r\n if '|' in row:\r\n cells = [cell.strip() for cell in row.split('|')]\r\n cells = [cell for cell in cells if cell] # Remove empty cells\r\n if i == 1 and all(set(cell) <= set('-|') for cell in cells):\r\n has_separator = True\r\n elif not cells:\r\n return False\r\n\r\n return has_separator and len(rows) >= 3\r\n\r\n def process_list(self, node, list_type):\r\n blocks = []\r\n for item in node.find_all('li'):\r\n item_text = item.get_text(strip=True)\r\n checked = item_text.startswith('[x]')\r\n is_checklist = item_text.startswith('[ ]') or checked\r\n\r\n if is_checklist:\r\n item_text = item_text.replace('[x]', '').replace('[ ]', '').strip()\r\n blocks.append(self.create_block('to_do', item_text, checked=checked))\r\n else:\r\n blocks.append(self.create_block(list_type, item_text))\r\n return blocks\r\n\r\n def process_table(self, node):\r\n blocks = []\r\n header_row = node.find('thead').find('tr') if node.find('thead') else None\r\n body_rows = node.find('tbody').find_all('tr') if node.find('tbody') else []\r\n\r\n if header_row or body_rows:\r\n table_width = max(len(header_row.find_all(['th', 'td'])) if header_row else 0,\r\n max(len(row.find_all(['th', 'td'])) for row in body_rows))\r\n\r\n table_block = self.create_block('table', '', table_width=table_width, has_column_header=bool(header_row))\r\n blocks.append(table_block)\r\n\r\n if header_row:\r\n header_cells = [cell.get_text(strip=True) for cell in header_row.find_all(['th', 'td'])]\r\n header_row_block = self.create_block('table_row', header_cells)\r\n blocks.append(header_row_block)\r\n\r\n for row in body_rows:\r\n cells = [cell.get_text(strip=True) for cell in row.find_all(['th', 'td'])]\r\n row_block = self.create_block('table_row', cells)\r\n blocks.append(row_block)\r\n\r\n return blocks\r\n \r\n def create_block(self, block_type: str, content: str, **kwargs) -> Dict[str, Any]:\r\n block = {\r\n \"object\": \"block\",\r\n \"type\": block_type,\r\n block_type: {},\r\n }\r\n\r\n if block_type in [\"paragraph\", \"heading_1\", \"heading_2\", \"heading_3\", \"bulleted_list_item\", \"numbered_list_item\", \"quote\"]:\r\n block[block_type][\"rich_text\"] = [\r\n {\r\n \"type\": \"text\",\r\n \"text\": {\r\n \"content\": content,\r\n },\r\n }\r\n ]\r\n elif block_type == 'to_do':\r\n block[block_type][\"rich_text\"] = [\r\n {\r\n \"type\": \"text\",\r\n \"text\": {\r\n \"content\": content,\r\n },\r\n }\r\n ]\r\n block[block_type]['checked'] = kwargs.get('checked', False)\r\n elif block_type == 'code':\r\n block[block_type]['rich_text'] = [\r\n {\r\n \"type\": \"text\",\r\n \"text\": {\r\n \"content\": content,\r\n },\r\n }\r\n ]\r\n block[block_type]['language'] = kwargs.get('language', 'plain text')\r\n elif block_type == 'image':\r\n block[block_type] = {\r\n \"type\": \"external\",\r\n \"external\": {\r\n \"url\": kwargs.get('image_url', '')\r\n }\r\n }\r\n elif block_type == 'divider':\r\n pass\r\n elif block_type == 'bookmark':\r\n block[block_type]['url'] = kwargs.get('link_url', '')\r\n elif block_type == 'table':\r\n block[block_type]['table_width'] = kwargs.get('table_width', 0)\r\n block[block_type]['has_column_header'] = kwargs.get('has_column_header', False)\r\n block[block_type]['has_row_header'] = kwargs.get('has_row_header', False)\r\n elif block_type == 'table_row':\r\n block[block_type]['cells'] = [[{'type': 'text', 'text': {'content': cell}} for cell in content]]\r\n\r\n return block","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"markdown_text":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"fileTypes":[],"file_path":"","password":false,"name":"markdown_text","display_name":"Markdown Text","advanced":false,"dynamic":false,"info":"The markdown text to convert to Notion blocks.","load_from_db":false,"title_case":false,"input_types":["Text"],"value":"# Heading 1\n\n## Heading 2\n\n### Heading 3\n\nThis is a regular paragraph.\n\nHere's another paragraph with an image:\n\n\n## Checklist\n- [x] Completed task\n- [ ] Incomplete task\n- [x] Another completed task\n\n## Numbered List\n1. First item\n2. Second item\n3. Third item\n\n## Bulleted List\n- Item 1\n- Item 2\n- Item 3\n\n## Code Block\n```python\ndef hello_world():\n print(\"Hello, World!\")\n```\n\n## Quote\n> This is a blockquote.\n> It can span multiple lines.\n\n## Horizontal Rule\n---\n\n\n## Link\n[Notion API Documentation](https://developers.notion.com)\n\n"},"notion_secret":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"notion_secret","display_name":"Notion Secret","advanced":false,"dynamic":false,"info":"The Notion integration token.","load_from_db":true,"title_case":false,"input_types":["Text"],"value":""},"_type":"CustomComponent"},"description":"Convert markdown text to Notion blocks and append them to a Notion page.","icon":"NotionDirectoryLoader","base_classes":["Record"],"display_name":"Add Content to Page [Notion] ","documentation":"https://developers.notion.com/reference/patch-block-children","custom_fields":{"markdown_text":null,"block_id":null,"notion_secret":null},"output_types":["Record"],"field_formatters":{},"frozen":false,"field_order":[],"beta":false,"official":false},"id":"CustomComponent-I8Dec"},"selected":false,"width":384,"height":497,"positionAbsolute":{"x":-2256.686402636563,"y":-963.4541117792749},"dragging":false},{"id":"CustomComponent-ZcsA9","type":"genericNode","position":{"x":-3488.029350341937,"y":-965.3756250644985},"data":{"type":"CustomComponent","node":{"template":{"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import requests\r\nfrom typing import Dict, Any, List\r\nfrom langflow.custom import CustomComponent\r\nfrom langflow.schema import Record\r\n\r\nclass NotionSearch(CustomComponent):\r\n display_name = \"Search Notion\"\r\n description = (\r\n \"Searches all pages and databases that have been shared with an integration.\"\r\n )\r\n documentation: str = \"https://docs.langflow.org/integrations/notion/search\"\r\n icon = \"NotionDirectoryLoader\"\r\n\r\n field_order = [\r\n \"notion_secret\",\r\n \"query\",\r\n \"filter_value\",\r\n \"sort_direction\",\r\n ]\r\n\r\n def build_config(self):\r\n return {\r\n \"notion_secret\": {\r\n \"display_name\": \"Notion Secret\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The Notion integration token.\",\r\n \"password\": True,\r\n },\r\n \"query\": {\r\n \"display_name\": \"Search Query\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The text that the API compares page and database titles against.\",\r\n },\r\n \"filter_value\": {\r\n \"display_name\": \"Filter Type\",\r\n \"field_type\": \"str\",\r\n \"info\": \"Limits the results to either only pages or only databases.\",\r\n \"options\": [\"page\", \"database\"],\r\n \"default_value\": \"page\",\r\n },\r\n \"sort_direction\": {\r\n \"display_name\": \"Sort Direction\",\r\n \"field_type\": \"str\",\r\n \"info\": \"The direction to sort the results.\",\r\n \"options\": [\"ascending\", \"descending\"],\r\n \"default_value\": \"descending\",\r\n },\r\n }\r\n\r\n def build(\r\n self,\r\n notion_secret: str,\r\n query: str = \"\",\r\n filter_value: str = \"page\",\r\n sort_direction: str = \"descending\",\r\n ) -> List[Record]:\r\n try:\r\n url = \"https://api.notion.com/v1/search\"\r\n headers = {\r\n \"Authorization\": f\"Bearer {notion_secret}\",\r\n \"Content-Type\": \"application/json\",\r\n \"Notion-Version\": \"2022-06-28\",\r\n }\r\n\r\n data = {\r\n \"query\": query,\r\n \"filter\": {\r\n \"value\": filter_value,\r\n \"property\": \"object\"\r\n },\r\n \"sort\":{\r\n \"direction\": sort_direction,\r\n \"timestamp\": \"last_edited_time\"\r\n }\r\n }\r\n\r\n response = requests.post(url, headers=headers, json=data)\r\n response.raise_for_status()\r\n\r\n results = response.json()\r\n records = []\r\n combined_text = f\"Results found: {len(results['results'])}\\n\\n\"\r\n for result in results['results']:\r\n result_data = {\r\n 'id': result['id'],\r\n 'type': result['object'],\r\n 'last_edited_time': result['last_edited_time'],\r\n }\r\n \r\n if result['object'] == 'page':\r\n result_data['title_or_url'] = result['url']\r\n text = f\"id: {result['id']}\\ntitle_or_url: {result['url']}\\n\"\r\n elif result['object'] == 'database':\r\n if 'title' in result and isinstance(result['title'], list) and len(result['title']) > 0:\r\n result_data['title_or_url'] = result['title'][0]['plain_text']\r\n text = f\"id: {result['id']}\\ntitle_or_url: {result['title'][0]['plain_text']}\\n\"\r\n else:\r\n result_data['title_or_url'] = \"N/A\"\r\n text = f\"id: {result['id']}\\ntitle_or_url: N/A\\n\"\r\n\r\n text += f\"type: {result['object']}\\nlast_edited_time: {result['last_edited_time']}\\n\\n\"\r\n combined_text += text\r\n records.append(Record(text=text, data=result_data))\r\n \r\n self.status = combined_text\r\n return records\r\n\r\n except Exception as e:\r\n self.status = f\"An error occurred: {str(e)}\"\r\n return [Record(text=self.status, data=[])]","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"filter_value":{"type":"str","required":false,"placeholder":"","list":true,"show":true,"multiline":false,"value":"database","fileTypes":[],"file_path":"","password":false,"options":["page","database"],"name":"filter_value","display_name":"Filter Type","advanced":false,"dynamic":false,"info":"Limits the results to either only pages or only databases.","load_from_db":false,"title_case":false,"input_types":["Text"]},"notion_secret":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"notion_secret","display_name":"Notion Secret","advanced":false,"dynamic":false,"info":"The Notion integration token.","load_from_db":true,"title_case":false,"input_types":["Text"],"value":""},"query":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":"","fileTypes":[],"file_path":"","password":false,"name":"query","display_name":"Search Query","advanced":false,"dynamic":false,"info":"The text that the API compares page and database titles against.","load_from_db":false,"title_case":false,"input_types":["Text"]},"sort_direction":{"type":"str","required":false,"placeholder":"","list":true,"show":true,"multiline":false,"value":"descending","fileTypes":[],"file_path":"","password":false,"options":["ascending","descending"],"name":"sort_direction","display_name":"Sort Direction","advanced":false,"dynamic":false,"info":"The direction to sort the results.","load_from_db":false,"title_case":false,"input_types":["Text"]},"_type":"CustomComponent"},"description":"Searches all pages and databases that have been shared with an integration.","icon":"NotionDirectoryLoader","base_classes":["Record"],"display_name":"Search [Notion]","documentation":"https://docs.langflow.org/integrations/notion/search","custom_fields":{"notion_secret":null,"query":null,"filter_value":null,"sort_direction":null},"output_types":["Record"],"field_formatters":{},"frozen":false,"field_order":["notion_secret","query","filter_value","sort_direction"],"beta":false},"id":"CustomComponent-ZcsA9","description":"Searches all pages and databases that have been shared with an integration.","display_name":"Search [Notion]"},"selected":false,"width":384,"height":591,"positionAbsolute":{"x":-3488.029350341937,"y":-965.3756250644985},"dragging":false}],"edges":[],"viewport":{"x":2623.378922967084,"y":696.8541079344027,"zoom":0.5981384177708997}},"description":"A Bundle containing Notion components for Page and Database manipulation. You can list pages, users databases, update properties, create new pages and add content to Notion Pages.","name":"Notion - Components","last_tested_version":"1.0.0a36","is_component":false}
\ No newline at end of file