docs: adjust page naming for better SEO and add notion references
This commit is contained in:
parent
0117076fd8
commit
1969aada85
11 changed files with 211 additions and 344 deletions
133
docs/docs/integrations/notion/add-content-to-page.md
Normal file
133
docs/docs/integrations/notion/add-content-to-page.md
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
Langflow allows extending its functionality with custom components like `AddContentToPage`, which converts markdown text to Notion blocks and appends them to a Notion page.
|
||||||
|
|
||||||
|
[Notion Reference](https://developers.notion.com/reference/patch-block-children)
|
||||||
|
|
||||||
|
## Component Functionality
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Code Block for the `AddContentToPage` Component
|
||||||
|
|
||||||
|
```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 a Markdown as input:
|
||||||
|
|
||||||
|
<ZoomableImage
|
||||||
|
alt="NotionDatabaseProperties Flow Example"
|
||||||
|
sources={{
|
||||||
|
light: "img/notion/AddContentToPage_flow_example.png",
|
||||||
|
dark: "img/notion/AddContentToPage_flow_example.png",
|
||||||
|
}}
|
||||||
|
style={{ width: "100%", margin: "20px 0" }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If issues arise:
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
@ -7,6 +7,8 @@ import ZoomableImage from "/src/theme/ZoomableImage.js";
|
||||||
|
|
||||||
Langflow allows you to extend its functionality with custom components. The `NotionDatabaseProperties` component is designed to retrieve properties of a Notion database. It provides a convenient way to integrate Notion database information into your Langflow workflows.
|
Langflow allows you to extend its functionality with custom components. The `NotionDatabaseProperties` component is designed to retrieve 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)
|
||||||
|
|
||||||
<Admonition type="tip" title="Component Functionality">
|
<Admonition type="tip" title="Component Functionality">
|
||||||
The `NotionDatabaseProperties` component enables you to:
|
The `NotionDatabaseProperties` component enables you to:
|
||||||
- Retrieve properties of a Notion database
|
- Retrieve properties of a Notion database
|
||||||
|
|
@ -29,13 +31,15 @@ Here's the code block for the `NotionDatabaseProperties` component:
|
||||||
```python
|
```python
|
||||||
import requests
|
import requests
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from langflow import CustomComponent
|
from langflow import CustomComponent
|
||||||
from langflow.schema import Record
|
from langflow.schema import Record
|
||||||
|
|
||||||
|
|
||||||
class NotionDatabaseProperties(CustomComponent):
|
class NotionDatabaseProperties(CustomComponent):
|
||||||
display_name = "List Database Properties [Notion]"
|
display_name = "List Database Properties [Notion]"
|
||||||
description = "Retrieve properties of a Notion database."
|
description = "Retrieve properties of a Notion database."
|
||||||
documentation: str = "https://developers.notion.com/reference/post-database-query"
|
documentation: str = "https://docs.langflow.org/integrations/notion/list-database-properties"
|
||||||
icon = "NotionDirectoryLoader"
|
icon = "NotionDirectoryLoader"
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
|
|
@ -63,10 +67,13 @@ class NotionDatabaseProperties(CustomComponent):
|
||||||
"Authorization": f"Bearer {notion_secret}",
|
"Authorization": f"Bearer {notion_secret}",
|
||||||
"Notion-Version": "2022-06-28", # Use the latest supported version
|
"Notion-Version": "2022-06-28", # Use the latest supported version
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.get(url, headers=headers)
|
response = requests.get(url, headers=headers)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
properties = data.get("properties", {})
|
properties = data.get("properties", {})
|
||||||
|
|
||||||
record = Record(text=str(response.json()), data=properties)
|
record = Record(text=str(response.json()), data=properties)
|
||||||
self.status = f"Retrieved {len(properties)} properties from the Notion database.\n {record.text}"
|
self.status = f"Retrieved {len(properties)} properties from the Notion database.\n {record.text}"
|
||||||
return record
|
return record
|
||||||
|
|
@ -3,11 +3,13 @@ import ThemedImage from "@theme/ThemedImage";
|
||||||
import useBaseUrl from "@docusaurus/useBaseUrl";
|
import useBaseUrl from "@docusaurus/useBaseUrl";
|
||||||
import ZoomableImage from "/src/theme/ZoomableImage.js";
|
import ZoomableImage from "/src/theme/ZoomableImage.js";
|
||||||
|
|
||||||
# Database Query
|
# List Pages
|
||||||
|
|
||||||
Langflow allows you to extend its functionality with custom components. The `NotionListPages
|
Langflow allows you to extend its functionality with custom components. The `NotionListPages
|
||||||
` component is designed to query a Notion database with filtering and sorting. It provides a convenient way to integrate Notion database querying capabilities into your Langflow workflows.
|
` component is designed to query 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)
|
||||||
|
|
||||||
> **Tip**:
|
> **Tip**:
|
||||||
>
|
>
|
||||||
> ### Component Functionality
|
> ### Component Functionality
|
||||||
|
|
@ -50,7 +52,7 @@ class NotionListPages(CustomComponent):
|
||||||
"Example input:\n"
|
"Example input:\n"
|
||||||
'{"filter": {"property": "Status", "select": {"equals": "Done"}}, "sorts": [{"timestamp": "created_time", "direction": "descending"}]}'
|
'{"filter": {"property": "Status", "select": {"equals": "Done"}}, "sorts": [{"timestamp": "created_time", "direction": "descending"}]}'
|
||||||
)
|
)
|
||||||
documentation: str = "https://developers.notion.com/reference/post-database-query"
|
documentation: str = "https://docs.langflow.org/integrations/notion/list-pages"
|
||||||
icon = "NotionDirectoryLoader"
|
icon = "NotionDirectoryLoader"
|
||||||
|
|
||||||
field_order = [
|
field_order = [
|
||||||
|
|
@ -7,6 +7,8 @@ import ZoomableImage from "/src/theme/ZoomableImage.js";
|
||||||
|
|
||||||
Langflow allows you to extend its functionality with custom components. The `NotionUserList` component is designed to retrieve users from Notion. It provides a convenient way to integrate Notion user data into your Langflow workflows.
|
Langflow allows you to extend its functionality with custom components. The `NotionUserList` component is designed to retrieve 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)
|
||||||
|
|
||||||
> **Component Functionality**
|
> **Component Functionality**
|
||||||
>
|
>
|
||||||
> The `NotionUserList` component enables you to:
|
> The `NotionUserList` component enables you to:
|
||||||
|
|
@ -28,13 +30,15 @@ Here's the code for the `NotionUserList` component:
|
||||||
```python
|
```python
|
||||||
import requests
|
import requests
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from langflow import CustomComponent
|
from langflow import CustomComponent
|
||||||
from langflow.schema import Record
|
from langflow.schema import Record
|
||||||
|
|
||||||
|
|
||||||
class NotionUserList(CustomComponent):
|
class NotionUserList(CustomComponent):
|
||||||
display_name = "List Users [Notion]"
|
display_name = "List Users [Notion]"
|
||||||
description = "Retrieve users from Notion."
|
description = "Retrieve users from Notion."
|
||||||
documentation: str = "https://developers.notion.com/reference/get-users"
|
documentation: str = "https://docs.langflow.org/integrations/notion/list-users"
|
||||||
icon = "NotionDirectoryLoader"
|
icon = "NotionDirectoryLoader"
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
|
|
@ -47,34 +51,44 @@ class NotionUserList(CustomComponent):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def build(self, notion_secret: str) -> List[Record]:
|
def build(
|
||||||
|
self,
|
||||||
|
notion_secret: str,
|
||||||
|
) -> List[Record]:
|
||||||
url = "https://api.notion.com/v1/users"
|
url = "https://api.notion.com/v1/users"
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {notion_secret}",
|
"Authorization": f"Bearer {notion_secret}",
|
||||||
"Notion-Version": "2022-06-28",
|
"Notion-Version": "2022-06-28",
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.get(url, headers=headers)
|
response = requests.get(url, headers=headers)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
results = data['results']
|
results = data['results']
|
||||||
|
|
||||||
records = []
|
records = []
|
||||||
for user in results:
|
for user in results:
|
||||||
id = user['id']
|
id = user['id']
|
||||||
type = user['type']
|
type = user['type']
|
||||||
name = user.get('name', '')
|
name = user.get('name', '')
|
||||||
avatar_url = user.get('avatar_url', '')
|
avatar_url = user.get('avatar_url', '')
|
||||||
|
|
||||||
record_data = {
|
record_data = {
|
||||||
"id": id,
|
"id": id,
|
||||||
"type": type,
|
"type": type,
|
||||||
"name": name,
|
"name": name,
|
||||||
"avatar_url": avatar_url,
|
"avatar_url": avatar_url,
|
||||||
}
|
}
|
||||||
|
|
||||||
output = "User:\n"
|
output = "User:\n"
|
||||||
for key, value in record_data.items():
|
for key, value in record_data.items():
|
||||||
output += f"{key.replace('_', ' ').title()}: {value}\n"
|
output += f"{key.replace('_', ' ').title()}: {value}\n"
|
||||||
output += "________________________\n"
|
output += "________________________\n"
|
||||||
|
|
||||||
record = Record(text=output, data=record_data)
|
record = Record(text=output, data=record_data)
|
||||||
records.append(record)
|
records.append(record)
|
||||||
|
|
||||||
self.status = "\n".join(record.text for record in records)
|
self.status = "\n".join(record.text for record in records)
|
||||||
return records
|
return records
|
||||||
```
|
```
|
||||||
|
|
@ -1,307 +0,0 @@
|
||||||
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
|
|
||||||
|
|
||||||
Langflow allows extending its functionality with custom components like `AddContentToPage`, which converts markdown text to Notion blocks and appends them to a Notion page.
|
|
||||||
|
|
||||||
## Component Functionality
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Code Block for the `AddContentToPage` Component
|
|
||||||
|
|
||||||
```python
|
|
||||||
import json
|
|
||||||
from typing import List, Dict, Any
|
|
||||||
from markdown import markdown
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
import requests
|
|
||||||
|
|
||||||
from langflow import CustomComponent
|
|
||||||
from langflow.schema import Record
|
|
||||||
|
|
||||||
class AddContentToPage(CustomComponent):
|
|
||||||
display_name = "Add Content to Page [Notion]"
|
|
||||||
description = "Convert markdown text to Notion blocks and append them to a Notion page."
|
|
||||||
documentation: str = "https://developers.notion.com/reference/patch-block-children"
|
|
||||||
icon = "NotionDirectoryLoader"
|
|
||||||
|
|
||||||
def build_config(self):
|
|
||||||
return {
|
|
||||||
"markdown_text": {
|
|
||||||
"display_name": "Markdown Text",
|
|
||||||
"field_type": "str",
|
|
||||||
"info": "The markdown text to convert to Notion blocks.",
|
|
||||||
"multiline": True,
|
|
||||||
},
|
|
||||||
"block_id": {
|
|
||||||
"display_name": "Page/Block ID",
|
|
||||||
"field_type": "str",
|
|
||||||
"info": "The ID of the page/block to add the content.",
|
|
||||||
},
|
|
||||||
"notion_secret": {
|
|
||||||
"display_name": "Notion Secret",
|
|
||||||
"field_type": "str",
|
|
||||||
"info": "The Notion integration token.",
|
|
||||||
"password": True,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(self, markdown_text: str, block_id: str, notion_secret: str) -> Record:
|
|
||||||
html_text = markdown(markdown_text)
|
|
||||||
soup = BeautifulSoup(html_text, 'html.parser')
|
|
||||||
blocks = self.process_node(soup)
|
|
||||||
|
|
||||||
url = f"https://api.notion.com/v1/blocks/{block_id}/children"
|
|
||||||
headers = {
|
|
||||||
"Authorization": f"Bearer {notion_secret}",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"Notion-Version": "2022-06-28",
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
"children": blocks,
|
|
||||||
}
|
|
||||||
|
|
||||||
response = requests.patch(url, headers=headers, json=data)
|
|
||||||
self.status = str(response.json())
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
result = response.json()
|
|
||||||
self.status = f"Appended {len(blocks)} blocks to page with ID: {block_id}"
|
|
||||||
return Record(data=result, text=json.dumps(result))
|
|
||||||
|
|
||||||
def process_node(self, node):
|
|
||||||
blocks = []
|
|
||||||
if isinstance(node, str):
|
|
||||||
text = node.strip()
|
|
||||||
if text:
|
|
||||||
if text.startswith('#'):
|
|
||||||
heading_level = text.count('#', 0, 6)
|
|
||||||
heading_text = text[heading_level:].strip()
|
|
||||||
if heading_level == 1:
|
|
||||||
blocks.append(self.create_block('heading_1', heading_text))
|
|
||||||
elif heading_level == 2:
|
|
||||||
blocks.append(self.create_block('heading_2', heading_text))
|
|
||||||
elif heading_level == 3:
|
|
||||||
blocks.append(self.create_block('heading_3', heading_text))
|
|
||||||
else:
|
|
||||||
blocks.append(self.create_block('paragraph', text))
|
|
||||||
elif node.name == 'h1':
|
|
||||||
blocks.append(self.create_block('heading_1', node.get_text(strip=True)))
|
|
||||||
elif node.name == 'h2':
|
|
||||||
blocks.append(self.create_block('heading_2', node.get_text(strip=True)))
|
|
||||||
elif node.name == 'h3':
|
|
||||||
blocks.append(self.create_block('heading_3', node.get_text(strip=True)))
|
|
||||||
elif node.name == 'p':
|
|
||||||
code_node = node.find('code')
|
|
||||||
if code_node:
|
|
||||||
code_text = code_node.get_text()
|
|
||||||
language, code = self.extract_language_and_code(code_text)
|
|
||||||
blocks.append(self.create_block('code', code, language=language))
|
|
||||||
elif self.is_table(str(node)):
|
|
||||||
blocks.extend(self.process_table(node))
|
|
||||||
else:
|
|
||||||
blocks.append(self.create_block('paragraph', node.get_text(strip=True)))
|
|
||||||
elif node.name == 'ul':
|
|
||||||
blocks.extend(self.process_list(node, 'bulleted_list_item'))
|
|
||||||
elif node.name == 'ol':
|
|
||||||
blocks.extend(self.process_list(node, 'numbered_list_item'))
|
|
||||||
elif node.name == 'blockquote':
|
|
||||||
blocks.append(self.create_block('quote', node.get_text(strip=True)))
|
|
||||||
elif node.name == 'hr':
|
|
||||||
blocks.append(self.create_block('divider', ''))
|
|
||||||
elif node.name == 'img':
|
|
||||||
blocks.append(self.create_block('image', '', image_url=node.get('src')))
|
|
||||||
elif node.name == 'a':
|
|
||||||
blocks.append(self.create_block('bookmark', node.get_text(strip=True), link_url=node.get('href')))
|
|
||||||
elif node.name == 'table':
|
|
||||||
blocks.extend(self.process_table(node))
|
|
||||||
|
|
||||||
for child in node.children:
|
|
||||||
if isinstance(child, str):
|
|
||||||
continue
|
|
||||||
blocks.extend(self.process_node(child))
|
|
||||||
|
|
||||||
return blocks
|
|
||||||
|
|
||||||
def extract_language_and_code(self, code_text):
|
|
||||||
lines = code_text.split('\n')
|
|
||||||
language = lines[0].strip()
|
|
||||||
code = '\n'.join(lines[1:]).strip()
|
|
||||||
return language, code
|
|
||||||
|
|
||||||
def is_code_block(self, text):
|
|
||||||
return text.startswith('```')
|
|
||||||
|
|
||||||
def extract_code_block(self, text):
|
|
||||||
lines = text.split('\n')
|
|
||||||
language = lines[0].strip('`').strip()
|
|
||||||
code = '\n'.join(lines[1:]).strip('`').strip()
|
|
||||||
return language, code
|
|
||||||
|
|
||||||
def is_table(self, text):
|
|
||||||
rows = text.split('\n')
|
|
||||||
if len(rows) < 2:
|
|
||||||
return False
|
|
||||||
|
|
||||||
has_separator = False
|
|
||||||
for i, row in enumerate(rows):
|
|
||||||
if '|' in row:
|
|
||||||
cells = [cell.strip() for cell in row.split('|')]
|
|
||||||
cells = [cell for cell in cells if cell] # Remove empty cells
|
|
||||||
if i == 1 and all(set(cell) <= set('-|') for cell in cells):
|
|
||||||
has_separator = True
|
|
||||||
elif not cells:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return has_separator and len(rows) >= 3
|
|
||||||
|
|
||||||
def process_list(self, node, list_type):
|
|
||||||
blocks = []
|
|
||||||
for item in node.find_all('li'):
|
|
||||||
item_text = item.get_text(strip=True)
|
|
||||||
checked = item_text.startswith('[x]')
|
|
||||||
is_checklist = item_text.startswith('[ ]') or checked
|
|
||||||
|
|
||||||
if is_checklist:
|
|
||||||
item_text = item_text.replace('[x]', '').replace('[ ]', '').strip()
|
|
||||||
blocks.append(self.create_block('to_do', item_text, checked=checked))
|
|
||||||
else:
|
|
||||||
blocks.append(self.create_block(list_type, item_text))
|
|
||||||
return blocks
|
|
||||||
|
|
||||||
def process_table(self, node):
|
|
||||||
blocks = []
|
|
||||||
header_row = node.find('thead').find('tr') if node.find('thead') else None
|
|
||||||
body_rows = node.find('tbody').find_all('tr') if node.find('tbody') else []
|
|
||||||
|
|
||||||
if header_row or body_rows:
|
|
||||||
table_width = max(len(header_row.find_all(['th', 'td'])) if header_row else 0,
|
|
||||||
max(len(row.find_all(['th', 'td'])) for row in body_rows))
|
|
||||||
|
|
||||||
table_block = self.create_block('table', '', table_width=table_width, has_column_header=bool(header_row))
|
|
||||||
blocks.append(table_block)
|
|
||||||
|
|
||||||
if header_row:
|
|
||||||
header_cells = [cell.get_text(strip=True) for cell in header_row.find_all(['th', 'td'])]
|
|
||||||
header_row_block = self.create_block('table_row', header_cells)
|
|
||||||
blocks.append(header_row_block)
|
|
||||||
|
|
||||||
for row in body_rows:
|
|
||||||
cells = [cell.get_text(strip=True) for cell in row.find_all(['th', 'td'])]
|
|
||||||
row_block = self.create_block('table_row', cells)
|
|
||||||
blocks.append(row_block)
|
|
||||||
|
|
||||||
return blocks
|
|
||||||
|
|
||||||
def create_block(self, block_type: str, content: str, **kwargs) -> Dict[str, Any]:
|
|
||||||
block = {
|
|
||||||
"object": "block",
|
|
||||||
"type": block_type,
|
|
||||||
block_type: {},
|
|
||||||
}
|
|
||||||
|
|
||||||
if block_type in ["paragraph", "heading_1", "heading_2", "heading_3", "bulleted_list_item", "numbered_list_item", "quote"]:
|
|
||||||
block[block_type]["rich_text"] = [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"text": {
|
|
||||||
"content": content,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
]
|
|
||||||
elif block_type == 'to_do':
|
|
||||||
block[block_type]["rich_text"] = [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"text": {
|
|
||||||
"content": content,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
]
|
|
||||||
block[block_type]['checked'] = kwargs.get('checked', False)
|
|
||||||
elif block_type == 'code':
|
|
||||||
block[block_type]['rich_text'] = [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"text": {
|
|
||||||
"content": content,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
]
|
|
||||||
block[block_type]['language'] = kwargs.get('language', 'plain text')
|
|
||||||
elif block_type == 'image':
|
|
||||||
block[block_type] = {
|
|
||||||
"type": "external",
|
|
||||||
"external": {
|
|
||||||
"url": kwargs.get('image_url', '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elif block_type == 'divider':
|
|
||||||
pass
|
|
||||||
elif block_type == 'bookmark':
|
|
||||||
block[block_type]['url'] = kwargs.get('link_url', '')
|
|
||||||
elif block_type == 'table':
|
|
||||||
block[block_type]['table_width'] = kwargs.get('table_width', 0)
|
|
||||||
block[block_type]['has_column_header'] = kwargs.get('has_column_header', False)
|
|
||||||
block[block_type]['has_row_header'] = kwargs.get('has_row_header', False)
|
|
||||||
elif block_type == 'table_row':
|
|
||||||
block[block_type]['cells'] = [[{'type': 'text', 'text': {'content': cell}} for cell in content]]
|
|
||||||
|
|
||||||
return block
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example Usage
|
|
||||||
|
|
||||||
Example of using the `AddContentToPage` component in a Langflow flow using a Markdown as input:
|
|
||||||
|
|
||||||
<ZoomableImage
|
|
||||||
alt="NotionDatabaseProperties Flow Example"
|
|
||||||
sources={{
|
|
||||||
light: "img/notion/AddContentToPage_flow_example.png",
|
|
||||||
dark: "img/notion/AddContentToPage_flow_example.png",
|
|
||||||
}}
|
|
||||||
style={{ width: "100%", margin: "20px 0" }}
|
|
||||||
/>
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
If issues arise:
|
|
||||||
|
|
||||||
- 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
@ -7,6 +7,8 @@ import ZoomableImage from "/src/theme/ZoomableImage.js";
|
||||||
|
|
||||||
Langflow allows you to extend its functionality with custom components. The `NotionPageContent` component is designed to retrieve the content of a Notion page as plain text. It provides a convenient way to integrate Notion page content into your Langflow workflows.
|
Langflow allows you to extend its functionality with custom components. The `NotionPageContent` component is designed to retrieve 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)
|
||||||
|
|
||||||
> **Component Functionality**
|
> **Component Functionality**
|
||||||
>
|
>
|
||||||
> The `NotionPageContent` component enables you to:
|
> The `NotionPageContent` component enables you to:
|
||||||
|
|
@ -30,13 +32,15 @@ Here's the code block for the `NotionPageContent` component:
|
||||||
```python
|
```python
|
||||||
import requests
|
import requests
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
|
|
||||||
from langflow import CustomComponent
|
from langflow import CustomComponent
|
||||||
from langflow.schema import Record
|
from langflow.schema import Record
|
||||||
|
|
||||||
|
|
||||||
class NotionPageContent(CustomComponent):
|
class NotionPageContent(CustomComponent):
|
||||||
display_name = "Page Content Viewer [Notion]"
|
display_name = "Page Content Viewer [Notion]"
|
||||||
description = "Retrieve the content of a Notion page as plain text."
|
description = "Retrieve the content of a Notion page as plain text."
|
||||||
documentation: str = "https://developers.notion.com/reference/get-page"
|
documentation: str = "https://docs.langflow.org/integrations/notion/page-content-viewer"
|
||||||
icon = "NotionDirectoryLoader"
|
icon = "NotionDirectoryLoader"
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
|
|
@ -54,18 +58,25 @@ class NotionPageContent(CustomComponent):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def build(self, page_id: str, notion_secret: str) -> Record:
|
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"
|
blocks_url = f"https://api.notion.com/v1/blocks/{page_id}/children?page_size=100"
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {notion_secret}",
|
"Authorization": f"Bearer {notion_secret}",
|
||||||
"Notion-Version": "2022-06-28", # Use the latest supported version
|
"Notion-Version": "2022-06-28", # Use the latest supported version
|
||||||
}
|
}
|
||||||
|
|
||||||
# Retrieve the child blocks
|
# Retrieve the child blocks
|
||||||
blocks_response = requests.get(blocks_url, headers=headers)
|
blocks_response = requests.get(blocks_url, headers=headers)
|
||||||
blocks_response.raise_for_status()
|
blocks_response.raise_for_status()
|
||||||
blocks_data = blocks_response.json()
|
blocks_data = blocks_response.json()
|
||||||
|
|
||||||
# Parse the blocks and extract the content as plain text
|
# Parse the blocks and extract the content as plain text
|
||||||
content = self.parse_blocks(blocks_data["results"])
|
content = self.parse_blocks(blocks_data["results"])
|
||||||
|
|
||||||
self.status = content
|
self.status = content
|
||||||
return Record(data={"content": content}, text=content)
|
return Record(data={"content": content}, text=content)
|
||||||
|
|
||||||
|
|
@ -7,6 +7,8 @@ import ZoomableImage from "/src/theme/ZoomableImage.js";
|
||||||
|
|
||||||
Langflow allows you to extend its functionality with custom components. The `NotionPageCreator` component is designed to create pages in a Notion database. It provides a convenient way to integrate Notion page creation into your Langflow workflows.
|
Langflow allows you to extend its functionality with custom components. The `NotionPageCreator` component is designed to create 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)
|
||||||
|
|
||||||
<Admonition type="tip" title="Component Functionality">
|
<Admonition type="tip" title="Component Functionality">
|
||||||
The `NotionPageCreator` component enables you to:
|
The `NotionPageCreator` component enables you to:
|
||||||
- Create new pages in a specified Notion database
|
- Create new pages in a specified Notion database
|
||||||
|
|
@ -29,10 +31,17 @@ To use the `NotionPageCreator` component in a Langflow flow, follow these steps:
|
||||||
Here's the code block for the `NotionPageCreator` component:
|
Here's the code block for the `NotionPageCreator` component:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
import json
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from langflow.custom import CustomComponent
|
||||||
|
|
||||||
|
|
||||||
class NotionPageCreator(CustomComponent):
|
class NotionPageCreator(CustomComponent):
|
||||||
display_name = "Create Page [Notion]"
|
display_name = "Create Page [Notion]"
|
||||||
description = "A component for creating Notion pages."
|
description = "A component for creating Notion pages."
|
||||||
documentation: str = "https://developers.notion.com/reference/post-database-query"
|
documentation: str = "https://docs.langflow.org/integrations/notion/page-create"
|
||||||
icon = "NotionDirectoryLoader"
|
icon = "NotionDirectoryLoader"
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
|
|
@ -60,7 +69,7 @@ class NotionPageCreator(CustomComponent):
|
||||||
database_id: str,
|
database_id: str,
|
||||||
notion_secret: str,
|
notion_secret: str,
|
||||||
properties: str = '{"Task name": {"id": "title", "type": "title", "title": [{"type": "text", "text": {"content": "Send Notion Components to LF", "link": null}}]}}',
|
properties: str = '{"Task name": {"id": "title", "type": "title", "title": [{"type": "text", "text": {"content": "Send Notion Components to LF", "link": null}}]}}',
|
||||||
) -> Record:
|
) -> str:
|
||||||
if not database_id or not properties:
|
if not database_id or not properties:
|
||||||
raise ValueError("Invalid input. Please provide 'database_id' and 'properties'.")
|
raise ValueError("Invalid input. Please provide 'database_id' and 'properties'.")
|
||||||
|
|
||||||
|
|
@ -78,18 +87,13 @@ class NotionPageCreator(CustomComponent):
|
||||||
response = requests.post("https://api.notion.com/v1/pages", headers=headers, json=data)
|
response = requests.post("https://api.notion.com/v1/pages", headers=headers, json=data)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
response = response.json()
|
page_id = response.json()["id"]
|
||||||
page_id = response["id"]
|
self.status = f"Successfully created Notion page with ID: {page_id}\n {str(response.json())}"
|
||||||
page_url = response["url"]
|
return response.json()
|
||||||
return_message = f"Successfully created Notion page with ID: {page_id}\n Page URL: {page_url}"
|
|
||||||
self.status=return_message
|
|
||||||
|
|
||||||
return Record(text=return_message, page_id=page_id, url=page_url)
|
|
||||||
else:
|
else:
|
||||||
error_message = f"Failed to create Notion page. Status code: {response.status_code}, Error: {response.text}"
|
error_message = f"Failed to create Notion page. Status code: {response.status_code}, Error: {response.text}"
|
||||||
self.status = error_message
|
self.status = error_message
|
||||||
raise Exception(error_message)
|
raise Exception(error_message)
|
||||||
return Record(text="Not able to connect to notion")
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<Admonition type="info" title="Example Usage">
|
<Admonition type="info" title="Example Usage">
|
||||||
|
|
@ -7,6 +7,8 @@ import ZoomableImage from "/src/theme/ZoomableImage.js";
|
||||||
|
|
||||||
Langflow allows you to extend its functionality with custom components. The `NotionPageUpdate` component is designed to update the properties of a Notion page. It provides a convenient way to integrate updating Notion page properties into your Langflow workflows.
|
Langflow allows you to extend its functionality with custom components. The `NotionPageUpdate` component is designed to update 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
|
## Component Usage
|
||||||
|
|
||||||
To use the `NotionPageUpdate` component in your Langflow flow:
|
To use the `NotionPageUpdate` component in your Langflow flow:
|
||||||
|
|
@ -22,16 +24,15 @@ Here's the code for the `NotionPageUpdate` component:
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from langflow.custom import CustomComponent
|
from langflow import CustomComponent
|
||||||
from langflow.schema import Record
|
from langflow.schema import Record
|
||||||
|
|
||||||
|
|
||||||
class NotionPageUpdate(CustomComponent):
|
class NotionPageUpdate(CustomComponent):
|
||||||
display_name = "Update Page Property [Notion]"
|
display_name = "Update Page Property [Notion]"
|
||||||
description = "Update the properties of a Notion page."
|
description = "Update the properties of a Notion page."
|
||||||
documentation: str = "https://developers.notion.com/reference/patch-page"
|
documentation: str = "https://docs.langflow.org/integrations/notion/page-update"
|
||||||
icon = "NotionDirectoryLoader"
|
icon = "NotionDirectoryLoader"
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
|
|
@ -7,6 +7,8 @@ import ZoomableImage from "/src/theme/ZoomableImage.js";
|
||||||
|
|
||||||
Langflow allows you to extend its functionality with custom components. 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.
|
Langflow allows you to extend its functionality with custom components. 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)
|
||||||
|
|
||||||
> **Tip**:
|
> **Tip**:
|
||||||
>
|
>
|
||||||
> ### Component Functionality
|
> ### Component Functionality
|
||||||
|
|
@ -42,7 +44,7 @@ class NotionSearch(CustomComponent):
|
||||||
description = (
|
description = (
|
||||||
"Searches all pages and databases that have been shared with an integration."
|
"Searches all pages and databases that have been shared with an integration."
|
||||||
)
|
)
|
||||||
documentation: str = "https://developers.notion.com/reference/search"
|
documentation: str = "https://docs.langflow.org/integrations/notion/search"
|
||||||
icon = "NotionDirectoryLoader"
|
icon = "NotionDirectoryLoader"
|
||||||
|
|
||||||
field_order = [
|
field_order = [
|
||||||
|
|
@ -140,15 +140,15 @@ module.exports = {
|
||||||
type: "category",
|
type: "category",
|
||||||
label: "Notion",
|
label: "Notion",
|
||||||
items: [
|
items: [
|
||||||
"integrations/notion/notion-setup",
|
"integrations/notion/setup",
|
||||||
"integrations/notion/notion-search",
|
"integrations/notion/search",
|
||||||
"integrations/notion/notion-list-database-properties",
|
"integrations/notion/list-database-properties",
|
||||||
"integrations/notion/notion-list-pages",
|
"integrations/notion/list-pages",
|
||||||
"integrations/notion/notion-list-users",
|
"integrations/notion/list-users",
|
||||||
"integrations/notion/notion-page-create",
|
"integrations/notion/page-create",
|
||||||
"integrations/notion/notion-add-content-to-page",
|
"integrations/notion/add-content-to-page",
|
||||||
"integrations/notion/notion-page-update",
|
"integrations/notion/page-update",
|
||||||
"integrations/notion/notion-page-content-viewer",
|
"integrations/notion/page-content-viewer",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue