feat: add dialog support to dropdown components and enhance AstraDB (#5349)
* feat: add dialog support to dropdown components and enhance AstraDB integration - Introduced a new NodeDialog component for improved user interaction when connecting to Astra DB. - Updated AstraDBVectorStoreComponent to include a dialog option for creating new collections. - Enhanced dropdown components to support dialog functionality, allowing users to create new options directly from the dropdown. - Added `hasDialog` property to relevant component types to manage dialog visibility. - Refactored utility functions to support new naming conventions and improve code clarity. * [autofix.ci] apply automated fixes * Remove creation parameters, add new inputs for dialog * Update astradb.py * [autofix.ci] apply automated fixes * Update the mixins for dialog_inputs * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * refactor: standardize JSON formatting and clean up input types in Vector Store RAG configuration - Reformatted JSON structure for better readability, ensuring consistent indentation and line breaks. - Updated input types across various components to use array notation for clarity. - Removed extraneous entries in package-lock.json to streamline dependencies. - Enhanced overall maintainability of the configuration files. * Add new options_metadata field to dropdown mixin * Update test_astra_component.py * Properly set dictionary mapping * Update astradb.py * Fix collection loading * [autofix.ci] apply automated fixes * Update astradb.py * Update astradb.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Enhance AstraDB integration and update dropdown components - Updated the AstraDBVectorStoreComponent to include new input fields for database and collection creation, with default options for selection. - Refactored dropdown components to support dynamic dialog inputs, improving user interaction for creating new options and refreshing lists. - Updated package-lock.json to reflect dependency upgrades, including Rollup and SWC packages. This commit improves the functionality and usability of the AstraDB integration and dropdown components, ensuring a smoother user experience. * Update astradb.py * Fix autodetection * Enhance dropdown components to support options metadata - Added `optionsMetaData` prop to Dropdown and DropdownComponent for improved data handling. - Updated rendering logic in Dropdown to display metadata alongside options, enhancing user experience. - Modified type definitions to include `optionsMetaData` in relevant components. These changes improve the flexibility and usability of dropdown components, allowing for richer data presentation. * Refactor and enhance AstraDB integration and dropdown components - Updated the `Vector Store RAG.json` configuration for improved formatting and consistency in output and input types. - Enhanced the `NodeDialogComponent` to accept `dialogInputs` as a prop, allowing for more dynamic content rendering. - Modified the `Dropdown` component to use `onSelect` instead of `onClick` for better accessibility and user interaction. - Improved rendering logic in the `Dropdown` component to conditionally display icon options based on the presence of `dialogInputs`. These changes enhance the usability and flexibility of the AstraDB integration and dropdown components, providing a more intuitive user experience. * Don't inherit from dict input in new inputs * [autofix.ci] apply automated fixes * Update astradb.py * update logic for dropdown * Fix the number of records per collection * Update astradb.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * feat: Enhance Dropdown and Parameter Render Components - Updated Dropdown component to integrate post template value handling and refresh functionality. - Refactored ParameterRenderComponent to conditionally render based on dialog inputs. - Improved DropdownComponent to accept additional props for better flexibility. These changes improve the overall functionality and usability of the dropdown components within the application. * Set unknown to none to hide unavailable fields * Update astradb.py * Refactor Dropdown Component for Enhanced Usability - Removed unnecessary state initialization and improved code readability. - Updated button elements within the dropdown to enhance user interaction. - Added loading state indication for the refresh button. - Filtered out null values from options metadata for cleaner rendering. These changes streamline the dropdown functionality and improve the user experience. * Refactor NodeDialog, Dropdown, and ParameterRender Components - Commented out debug logs in NodeDialogComponent to clean up console output. - Enhanced Dropdown component to conditionally render icon options based on dialog inputs. - Updated ParameterRenderComponent to check for the length of dialog inputs before rendering. These changes improve code readability and ensure components behave correctly based on input conditions. * [autofix.ci] apply automated fixes * Cleanup some tests * Fix ruff style issue * [autofix.ci] apply automated fixes * Fix environment specification * [autofix.ci] apply automated fixes * Update starter project template * Update astradb.py * Remove backwards compatibility features * [autofix.ci] apply automated fixes * Small tweak to autodetect * [autofix.ci] apply automated fixes * Refactor NodeDialogComponent to Dynamically Render Inputs - Replaced static content in NodeDialogComponent with dynamic rendering based on dialogInputs. - Introduced NodeInputField and RenderInputParameters components for better modularity. - Enhanced footer with Cancel and Save buttons, improving user interaction. These changes enhance the flexibility and usability of the NodeDialogComponent, allowing it to adapt to varying input configurations. * Refactor NodeDialogComponent: Remove Unused Imports - Commented out unused imports in NodeDialogComponent to clean up the code. - This change enhances code readability and prepares the component for future updates. No functional changes were made; the focus was on improving code quality. * Refactor Dropdown and ParameterRender Components for Improved Readability and Functionality - Renamed functions in Dropdown component for clarity: `renderOptionsList` and `renderCreateOptionDialog` to `oldRenderOptionsList` and `renderCustomOptionDialog`, respectively. - Enhanced the rendering logic in Dropdown to streamline the display of options and metadata. - Simplified the return structure in ParameterRenderComponent to always render the RefreshParameterComponent, improving code consistency. - Updated RefreshParameterComponent to conditionally display the refresh button based on the presence of dialog inputs. These changes improve code readability and maintainability while ensuring consistent behavior across components. * [autofix.ci] apply automated fixes * Add the new naming conventions to deletion fields * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * Add new cloud provider options for database creation * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Make dialog inputs a dictionary of inputs * [autofix.ci] apply automated fixes * Update astradb.py * Update astradb.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Update astradb.py * [autofix.ci] apply automated fixes * added mock data for testing * Clean up the reactive flow * [autofix.ci] apply automated fixes * Fix the dialog inputs * Update Vector Store RAG.json * Update Vector Store RAG.json * Update astradb.py * Update astradb.py * [autofix.ci] apply automated fixes * Update astradb.py * Update astradb.py * Switch dialog inputs from list to dictionary * Update astradb.py * Refactor NodeDialogComponent to utilize useDialogSubmit hook for handling dialog submissions and streamline input rendering. Remove unused props and mock data, enhancing clarity and maintainability. Update DropdownComponent to remove unnecessary content prop. Introduce useDialogSubmit hook for improved API interaction and loading state management. * New structure for dialog inputs * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * No need for the input type on token * Flip order of ingest and search * [autofix.ci] apply automated fixes * Remove id field from factory * Remove other id field * [autofix.ci] apply automated fixes * Refactor directory_reader.py to simplify file filtering logic * Refactor flowSidebarComponent to filter out bundles and custom components in CategoryGroup * [autofix.ci] apply automated fixes * Refactor NodeDialogComponent to utilize dialogInputs directly, removing mock data and enhancing parameter rendering. Update Dropdown and ParameterRenderComponent types to accept single dialogInputs object. Remove unused useDialogSubmit hook. * ✨ (NodeDialogComponent/index.tsx): Introduce handleNewValue function to handle updating node template values based on user input 🔧 (NodeDialogComponent/index.tsx): Add support for process.env.PORT environment variable to be able to run app on a configurable port 🔧 (dropdownComponent/index.tsx): Add nodeId prop to Dropdown component to pass node id for better context 🔧 (parameterRenderComponent/index.tsx): Update handleOnNewValue prop to accept key parameter for better handling of new values 🔧 (parameterRenderComponent/types.ts): Add nodeId property to BaseInputProps type for better context and consistency * Don't load the new collection names from db * Update astradb.py * Temporary disabling of dialog inputs functionality * Update directory_reader.py * Fix problematic uv.lock line * Update uv.lock * Update Vector Store RAG.json * Update Vector Store RAG.json * refactor: enhance dropdown and refresh button logic for better user experience - Updated the dropdown component to disable the trigger button when there are no options available or when certain conditions are met. - Removed the old render options list to streamline the dropdown rendering process. - Improved the loading state handling in the dropdown to provide clearer feedback to users. - Refactored the refresh button logic to ensure it only displays when appropriate conditions are met, enhancing the component's responsiveness. * [autofix.ci] apply automated fixes * Allow combobox specification of api endpoint * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * Update Vector Store RAG.json * Add back api_endpoint option for compatibility * Update Vector Store RAG.json * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Hare <ericrhare@gmail.com> Co-authored-by: anovazzi1 <otavio2204@gmail.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org> Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
This commit is contained in:
parent
ae7b30c632
commit
a06cca4a8c
18 changed files with 1356 additions and 938 deletions
|
|
@ -53,15 +53,15 @@ class LCVectorStoreComponent(Component):
|
|||
trace_type = "retriever"
|
||||
|
||||
inputs = [
|
||||
DataInput(
|
||||
name="ingest_data",
|
||||
display_name="Ingest Data",
|
||||
),
|
||||
MultilineInput(
|
||||
name="search_query",
|
||||
display_name="Search Query",
|
||||
tool_mode=True,
|
||||
),
|
||||
DataInput(
|
||||
name="ingest_data",
|
||||
display_name="Ingest Data",
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
import os
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from astrapy import AstraDBAdmin, DataAPIClient
|
||||
from astrapy.admin import parse_api_endpoint
|
||||
from langchain_astradb import AstraDBVectorStore
|
||||
from astrapy import AstraDBAdmin, DataAPIClient, Database
|
||||
from langchain_astradb import AstraDBVectorStore, CollectionVectorServiceOptions
|
||||
|
||||
from langflow.base.vectorstores.model import LCVectorStoreComponent, check_cached_vector_store
|
||||
from langflow.helpers import docs_to_data
|
||||
from langflow.inputs import DictInput, FloatInput, MessageTextInput, NestedDictInput
|
||||
from langflow.inputs import FloatInput, NestedDictInput
|
||||
from langflow.io import (
|
||||
BoolInput,
|
||||
DataInput,
|
||||
DropdownInput,
|
||||
HandleInput,
|
||||
IntInput,
|
||||
|
|
@ -30,21 +29,82 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
|
||||
_cached_vector_store: AstraDBVectorStore | None = None
|
||||
|
||||
base_inputs = LCVectorStoreComponent.inputs
|
||||
if "search_query" not in [input_.name for input_ in base_inputs]:
|
||||
base_inputs.append(
|
||||
MessageTextInput(
|
||||
name="search_query",
|
||||
display_name="Search Query",
|
||||
tool_mode=True,
|
||||
)
|
||||
@dataclass
|
||||
class NewDatabaseInput:
|
||||
functionality: str = "create"
|
||||
fields: dict[str, dict] = field(
|
||||
default_factory=lambda: {
|
||||
"data": {
|
||||
"node": {
|
||||
"description": "Create a new database in Astra DB.",
|
||||
"display_name": "Create New Database",
|
||||
"field_order": ["new_database_name", "cloud_provider", "region"],
|
||||
"template": {
|
||||
"new_database_name": StrInput(
|
||||
name="new_database_name",
|
||||
display_name="New Database Name",
|
||||
info="Name of the new database to create in Astra DB.",
|
||||
required=True,
|
||||
),
|
||||
"cloud_provider": DropdownInput(
|
||||
name="cloud_provider",
|
||||
display_name="Cloud Provider",
|
||||
info="Cloud provider for the new database.",
|
||||
options=["Amazon Web Services", "Google Cloud Platform", "Microsoft Azure"],
|
||||
required=True,
|
||||
),
|
||||
"region": DropdownInput(
|
||||
name="region",
|
||||
display_name="Region",
|
||||
info="Region for the new database.",
|
||||
options=[],
|
||||
required=True,
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
if "ingest_data" not in [input_.name for input_ in base_inputs]:
|
||||
base_inputs.append(
|
||||
DataInput(
|
||||
name="ingest_data",
|
||||
display_name="Ingest Data",
|
||||
)
|
||||
|
||||
@dataclass
|
||||
class NewCollectionInput:
|
||||
functionality: str = "create"
|
||||
fields: dict[str, dict] = field(
|
||||
default_factory=lambda: {
|
||||
"data": {
|
||||
"node": {
|
||||
"description": "Create a new collection in Astra DB.",
|
||||
"display_name": "Create New Collection",
|
||||
"field_order": [
|
||||
"new_collection_name",
|
||||
"embedding_generation_provider",
|
||||
"embedding_generation_model",
|
||||
],
|
||||
"template": {
|
||||
"new_collection_name": StrInput(
|
||||
name="new_collection_name",
|
||||
display_name="New Collection Name",
|
||||
info="Name of the new collection to create in Astra DB.",
|
||||
required=True,
|
||||
),
|
||||
"embedding_generation_provider": DropdownInput(
|
||||
name="embedding_generation_provider",
|
||||
display_name="Embedding Generation Provider",
|
||||
info="Provider to use for generating embeddings.",
|
||||
options=[],
|
||||
required=True,
|
||||
),
|
||||
"embedding_generation_model": DropdownInput(
|
||||
name="embedding_generation_model",
|
||||
display_name="Embedding Generation Model",
|
||||
info="Model to use for generating embeddings.",
|
||||
options=[],
|
||||
required=True,
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
inputs = [
|
||||
|
|
@ -54,18 +114,37 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
info="Authentication token for accessing Astra DB.",
|
||||
value="ASTRA_DB_APPLICATION_TOKEN",
|
||||
required=True,
|
||||
advanced=os.getenv("ASTRA_ENHANCED", "false").lower() == "true",
|
||||
real_time_refresh=True,
|
||||
input_types=[],
|
||||
),
|
||||
StrInput(
|
||||
name="environment",
|
||||
display_name="Environment",
|
||||
info="The environment for the Astra DB API Endpoint.",
|
||||
advanced=True,
|
||||
),
|
||||
StrInput(
|
||||
name="api_endpoint",
|
||||
display_name="API Endpoint",
|
||||
info="The API endpoint for the Astra DB instance.",
|
||||
advanced=True,
|
||||
),
|
||||
DropdownInput(
|
||||
name="api_endpoint",
|
||||
name="database_name",
|
||||
display_name="Database",
|
||||
info="The Astra DB Database to use.",
|
||||
info="Select a database in Astra DB.",
|
||||
required=True,
|
||||
refresh_button=True,
|
||||
real_time_refresh=True,
|
||||
options=["Default database"],
|
||||
value="Default database",
|
||||
# dialog_inputs=asdict(NewDatabaseInput()),
|
||||
options=[],
|
||||
options_metadata=[
|
||||
{
|
||||
"collections": 0,
|
||||
}
|
||||
],
|
||||
value="",
|
||||
combobox=True,
|
||||
),
|
||||
DropdownInput(
|
||||
name="collection_name",
|
||||
|
|
@ -74,15 +153,17 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
required=True,
|
||||
refresh_button=True,
|
||||
real_time_refresh=True,
|
||||
options=["+ Create new collection"],
|
||||
value="+ Create new collection",
|
||||
),
|
||||
StrInput(
|
||||
name="collection_name_new",
|
||||
display_name="Collection Name",
|
||||
info="Name of the new collection to create.",
|
||||
advanced=os.getenv("LANGFLOW_HOST") is not None,
|
||||
required=os.getenv("LANGFLOW_HOST") is None,
|
||||
# dialog_inputs=asdict(NewCollectionInput()),
|
||||
options=[],
|
||||
options_metadata=[
|
||||
{
|
||||
"provider": None,
|
||||
"model": None,
|
||||
"records": 0,
|
||||
"icon": "",
|
||||
}
|
||||
],
|
||||
value="",
|
||||
),
|
||||
StrInput(
|
||||
name="keyspace",
|
||||
|
|
@ -90,21 +171,14 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
info="Optional keyspace within Astra DB to use for the collection.",
|
||||
advanced=True,
|
||||
),
|
||||
DropdownInput(
|
||||
name="embedding_choice",
|
||||
display_name="Embedding Model or Astra Vectorize",
|
||||
info="Determines whether to use Astra Vectorize for the collection.",
|
||||
options=["Embedding Model", "Astra Vectorize"],
|
||||
real_time_refresh=True,
|
||||
value="Embedding Model",
|
||||
),
|
||||
HandleInput(
|
||||
name="embedding_model",
|
||||
display_name="Embedding Model",
|
||||
input_types=["Embeddings"],
|
||||
info="Allows an embedding model configuration.",
|
||||
required=True,
|
||||
),
|
||||
*base_inputs,
|
||||
*LCVectorStoreComponent.inputs,
|
||||
IntInput(
|
||||
name="number_of_results",
|
||||
display_name="Number of Search Results",
|
||||
|
|
@ -162,33 +236,190 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
),
|
||||
]
|
||||
|
||||
def del_fields(self, build_config, field_list):
|
||||
for field in field_list:
|
||||
if field in build_config:
|
||||
del build_config[field]
|
||||
@classmethod
|
||||
def map_cloud_providers(cls):
|
||||
return {
|
||||
"Amazon Web Services": {
|
||||
"id": "aws",
|
||||
"regions": ["us-east-2", "ap-south-1", "eu-west-1"],
|
||||
},
|
||||
"Google Cloud Platform": {
|
||||
"id": "gcp",
|
||||
"regions": ["us-east1"],
|
||||
},
|
||||
"Microsoft Azure": {
|
||||
"id": "azure",
|
||||
"regions": ["westus3"],
|
||||
},
|
||||
}
|
||||
|
||||
return build_config
|
||||
@classmethod
|
||||
def create_database_api(
|
||||
cls,
|
||||
token: str,
|
||||
new_database_name: str,
|
||||
cloud_provider: str,
|
||||
region: str,
|
||||
):
|
||||
client = DataAPIClient(token=token)
|
||||
|
||||
def insert_in_dict(self, build_config, field_name, new_parameters):
|
||||
# Insert the new key-value pair after the found key
|
||||
for new_field_name, new_parameter in new_parameters.items():
|
||||
# Get all the items as a list of tuples (key, value)
|
||||
items = list(build_config.items())
|
||||
# Get the admin object
|
||||
admin_client = client.get_admin(token=token)
|
||||
|
||||
# Find the index of the key to insert after
|
||||
idx = len(items)
|
||||
for i, (key, _) in enumerate(items):
|
||||
if key == field_name:
|
||||
idx = i + 1
|
||||
break
|
||||
# Call the create database function
|
||||
return admin_client.create_database(
|
||||
name=new_database_name,
|
||||
cloud_provider=cloud_provider,
|
||||
region=region,
|
||||
)
|
||||
|
||||
items.insert(idx, (new_field_name, new_parameter))
|
||||
@classmethod
|
||||
def create_collection_api(
|
||||
cls,
|
||||
token: str,
|
||||
database_name: str,
|
||||
new_collection_name: str,
|
||||
dimension: int | None = None,
|
||||
embedding_generation_provider: str | None = None,
|
||||
embedding_generation_model: str | None = None,
|
||||
):
|
||||
client = DataAPIClient(token=token)
|
||||
api_endpoint = cls.get_api_endpoint_static(token=token, database_name=database_name)
|
||||
|
||||
# Clear the original dictionary and update with the modified items
|
||||
build_config.clear()
|
||||
build_config.update(items)
|
||||
# Get the database object
|
||||
database = client.get_database(api_endpoint=api_endpoint, token=token)
|
||||
|
||||
return build_config
|
||||
# Build vectorize options, if needed
|
||||
vectorize_options = None
|
||||
if not dimension:
|
||||
vectorize_options = CollectionVectorServiceOptions(
|
||||
provider=embedding_generation_provider,
|
||||
model_name=embedding_generation_model,
|
||||
authentication=None,
|
||||
parameters=None,
|
||||
)
|
||||
|
||||
# Create the collection
|
||||
return database.create_collection(
|
||||
name=new_collection_name,
|
||||
dimension=dimension,
|
||||
service=vectorize_options,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_database_list_static(cls, token: str, environment: str | None = None):
|
||||
client = DataAPIClient(token=token, environment=environment)
|
||||
|
||||
# Get the admin object
|
||||
admin_client = client.get_admin(token=token)
|
||||
|
||||
# Get the list of databases
|
||||
db_list = list(admin_client.list_databases())
|
||||
|
||||
# Generate the api endpoint for each database
|
||||
return {
|
||||
db.info.name: {
|
||||
"api_endpoint": (api_endpoint := f"https://{db.info.id}-{db.info.region}.apps.astra.datastax.com"),
|
||||
"collections": len(
|
||||
list(
|
||||
client.get_database(
|
||||
api_endpoint=api_endpoint, token=token, keyspace=db.info.keyspace
|
||||
).list_collection_names(keyspace=db.info.keyspace)
|
||||
)
|
||||
),
|
||||
}
|
||||
for db in db_list
|
||||
}
|
||||
|
||||
def get_database_list(self):
|
||||
return self.get_database_list_static(token=self.token, environment=self.environment)
|
||||
|
||||
@classmethod
|
||||
def get_api_endpoint_static(
|
||||
cls,
|
||||
token: str,
|
||||
environment: str | None = None,
|
||||
api_endpoint: str | None = None,
|
||||
database_name: str | None = None,
|
||||
):
|
||||
# Check if an api endpoint is provided
|
||||
if api_endpoint:
|
||||
return api_endpoint
|
||||
|
||||
# Check if the database_name is like a url
|
||||
if database_name and database_name.startswith("https://"):
|
||||
return database_name
|
||||
|
||||
# If the database is not set, nothing we can do.
|
||||
if not database_name:
|
||||
return None
|
||||
|
||||
# Otherwise, get the URL from the database list
|
||||
return cls.get_database_list_static(token=token, environment=environment).get(database_name).get("api_endpoint")
|
||||
|
||||
def get_api_endpoint(self):
|
||||
return self.get_api_endpoint_static(
|
||||
token=self.token,
|
||||
environment=self.environment,
|
||||
api_endpoint=self.api_endpoint,
|
||||
database_name=self.database_name,
|
||||
)
|
||||
|
||||
def get_keyspace(self):
|
||||
keyspace = self.keyspace
|
||||
|
||||
if keyspace:
|
||||
return keyspace.strip()
|
||||
|
||||
return None
|
||||
|
||||
def get_database_object(self):
|
||||
try:
|
||||
client = DataAPIClient(token=self.token, environment=self.environment)
|
||||
|
||||
return client.get_database(
|
||||
api_endpoint=self.get_api_endpoint(),
|
||||
token=self.token,
|
||||
keyspace=self.get_keyspace(),
|
||||
)
|
||||
except Exception as e: # noqa: BLE001
|
||||
self.log(f"Error getting database: {e}")
|
||||
|
||||
return None
|
||||
|
||||
def collection_exists(self):
|
||||
try:
|
||||
client = DataAPIClient(token=self.token, environment=self.environment)
|
||||
database = client.get_database(
|
||||
api_endpoint=self.get_api_endpoint(),
|
||||
token=self.token,
|
||||
keyspace=self.get_keyspace(),
|
||||
)
|
||||
|
||||
return self.collection_name in list(database.list_collection_names(keyspace=self.get_keyspace()))
|
||||
except Exception as e: # noqa: BLE001
|
||||
self.log(f"Error getting collection status: {e}")
|
||||
|
||||
return False
|
||||
|
||||
def collection_data(self, collection_name: str, database: Database | None = None):
|
||||
try:
|
||||
if not database:
|
||||
client = DataAPIClient(token=self.token, environment=self.environment)
|
||||
|
||||
database = client.get_database(
|
||||
api_endpoint=self.get_api_endpoint(),
|
||||
token=self.token,
|
||||
keyspace=self.get_keyspace(),
|
||||
)
|
||||
|
||||
collection = database.get_collection(collection_name, keyspace=self.get_keyspace())
|
||||
|
||||
return collection.estimated_document_count()
|
||||
except Exception as e: # noqa: BLE001
|
||||
self.log(f"Error checking collection data: {e}")
|
||||
|
||||
return None
|
||||
|
||||
def get_vectorize_providers(self):
|
||||
try:
|
||||
|
|
@ -196,7 +427,7 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
|
||||
# Get the admin object
|
||||
admin = AstraDBAdmin(token=self.token)
|
||||
db_admin = admin.get_database_admin(self.get_api_endpoint())
|
||||
db_admin = admin.get_database_admin(api_endpoint=self.get_api_endpoint())
|
||||
|
||||
# Get the list of embedding providers
|
||||
embedding_providers = db_admin.find_embedding_providers().as_dict()
|
||||
|
|
@ -207,6 +438,7 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
display_name = provider_data["displayName"]
|
||||
models = [model["name"] for model in provider_data["models"]]
|
||||
|
||||
# TODO: https://astra.datastax.com/api/v2/graphql
|
||||
vectorize_providers_mapping[display_name] = [provider_key, models]
|
||||
|
||||
# Sort the resulting dictionary
|
||||
|
|
@ -216,319 +448,142 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
|
||||
return {}
|
||||
|
||||
def get_database_list(self):
|
||||
# Get the admin object
|
||||
db_admin = AstraDBAdmin(token=self.token)
|
||||
db_list = list(db_admin.list_databases())
|
||||
|
||||
# Generate the api endpoint for each database
|
||||
return {db.info.name: f"https://{db.info.id}-{db.info.region}.apps.astra.datastax.com" for db in db_list}
|
||||
|
||||
def get_api_endpoint(self):
|
||||
# Get the database name (or endpoint)
|
||||
database = self.api_endpoint
|
||||
|
||||
# If the database is not set, get the first database in the list
|
||||
if not database or database == "Default database":
|
||||
database, _ = next(iter(self.get_database_list().items()))
|
||||
|
||||
# If the database is a URL, return it
|
||||
if database.startswith("https://"):
|
||||
return database
|
||||
|
||||
# Otherwise, get the URL from the database list
|
||||
return self.get_database_list().get(database)
|
||||
|
||||
def get_database(self):
|
||||
try:
|
||||
client = DataAPIClient(token=self.token)
|
||||
|
||||
return client.get_database(
|
||||
api_endpoint=self.get_api_endpoint(),
|
||||
token=self.token,
|
||||
)
|
||||
except Exception as e: # noqa: BLE001
|
||||
self.log(f"Error getting database: {e}")
|
||||
|
||||
return None
|
||||
|
||||
def _initialize_database_options(self):
|
||||
if not self.token:
|
||||
return ["Default database"]
|
||||
try:
|
||||
databases = ["Default database", *list(self.get_database_list().keys())]
|
||||
return [
|
||||
{"name": name, "collections": info["collections"]} for name, info in self.get_database_list().items()
|
||||
]
|
||||
except Exception as e: # noqa: BLE001
|
||||
self.log(f"Error fetching databases: {e}")
|
||||
|
||||
return ["Default database"]
|
||||
|
||||
return databases
|
||||
return []
|
||||
|
||||
def _initialize_collection_options(self):
|
||||
database = self.get_database()
|
||||
database = self.get_database_object()
|
||||
if database is None:
|
||||
return ["+ Create new collection"]
|
||||
return []
|
||||
|
||||
try:
|
||||
collections = [collection.name for collection in database.list_collections(keyspace=self.keyspace or None)]
|
||||
collection_list = list(database.list_collections(keyspace=self.get_keyspace()))
|
||||
|
||||
return [
|
||||
{
|
||||
"name": col.name,
|
||||
"records": self.collection_data(collection_name=col.name, database=database),
|
||||
"provider": (
|
||||
col.options.vector.service.provider
|
||||
if col.options.vector and col.options.vector.service
|
||||
else None
|
||||
),
|
||||
"icon": "",
|
||||
"model": (
|
||||
col.options.vector.service.model_name
|
||||
if col.options.vector and col.options.vector.service
|
||||
else None
|
||||
),
|
||||
}
|
||||
for col in collection_list
|
||||
]
|
||||
except Exception as e: # noqa: BLE001
|
||||
self.log(f"Error fetching collections: {e}")
|
||||
|
||||
return ["+ Create new collection"]
|
||||
|
||||
return [*collections, "+ Create new collection"]
|
||||
|
||||
def get_collection_choice(self):
|
||||
collection_name = self.collection_name
|
||||
if collection_name == "+ Create new collection":
|
||||
return self.collection_name_new
|
||||
|
||||
return collection_name
|
||||
|
||||
def get_collection_options(self):
|
||||
# Only get the options if the collection exists
|
||||
database = self.get_database()
|
||||
if database is None:
|
||||
return None
|
||||
|
||||
collection_name = self.get_collection_choice()
|
||||
|
||||
try:
|
||||
collection = database.get_collection(collection_name, keyspace=self.keyspace or None)
|
||||
collection_options = collection.options()
|
||||
except Exception as _: # noqa: BLE001
|
||||
return None
|
||||
|
||||
return collection_options.vector
|
||||
return []
|
||||
|
||||
def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None):
|
||||
# Always attempt to update the database list
|
||||
if field_name in {"token", "api_endpoint", "collection_name"}:
|
||||
# Update the database selector
|
||||
build_config["api_endpoint"]["options"] = self._initialize_database_options()
|
||||
if not self.token or not self.token.startswith("AstraCS:"):
|
||||
build_config["database_name"]["info"] = "Add a Valid Token to Select a Database"
|
||||
else:
|
||||
build_config["database_name"]["info"] = "Select a Database from Astra DB"
|
||||
|
||||
# Set the default API endpoint if not set
|
||||
if build_config["api_endpoint"]["value"] == "Default database":
|
||||
build_config["api_endpoint"]["value"] = build_config["api_endpoint"]["options"][0]
|
||||
# Refresh the database name options
|
||||
if field_name in ["token", "environment"] or not build_config["database_name"]["options"]:
|
||||
# Reset the list of collections
|
||||
build_config["collection_name"]["options"] = []
|
||||
build_config["collection_name"]["options_metadata"] = []
|
||||
build_config["database_name"]["value"] = []
|
||||
|
||||
# Update the collection selector
|
||||
build_config["collection_name"]["options"] = self._initialize_collection_options()
|
||||
# Get the list of databases
|
||||
database_options = self._initialize_database_options()
|
||||
build_config["database_name"]["options"] = [db["name"] for db in database_options]
|
||||
build_config["database_name"]["options_metadata"] = [
|
||||
{k: v for k, v in db.items() if k not in ["name"]} for db in database_options
|
||||
]
|
||||
|
||||
# Update the choice of embedding model based on collection name
|
||||
# Get list of regions for a given cloud provider
|
||||
"""
|
||||
cloud_provider = (
|
||||
build_config["database_name"]["dialog_inputs"]["fields"]["data"]["node"]["template"]["cloud_provider"][
|
||||
"value"
|
||||
]
|
||||
or "Amazon Web Services"
|
||||
)
|
||||
build_config["database_name"]["dialog_inputs"]["fields"]["data"]["node"]["template"]["region"][
|
||||
"options"
|
||||
] = self.map_cloud_providers()[cloud_provider]["regions"]
|
||||
"""
|
||||
|
||||
return build_config
|
||||
|
||||
# Refresh the collection name options
|
||||
if field_name in ["database_name", "api_endpoint"] or not build_config["collection_name"]["options"]:
|
||||
build_config["collection_name"]["value"] = None
|
||||
|
||||
# Reset the list of collections
|
||||
collection_options = self._initialize_collection_options()
|
||||
build_config["collection_name"]["options"] = [col["name"] for col in collection_options]
|
||||
build_config["collection_name"]["options_metadata"] = [
|
||||
{k: v for k, v in col.items() if k not in ["name"]} for col in collection_options
|
||||
]
|
||||
|
||||
return build_config
|
||||
|
||||
# Hide embedding model option if opriona_metadata provider is not null
|
||||
if field_name == "collection_name":
|
||||
# Detect if it is a new collection
|
||||
is_new_collection = field_value == "+ Create new collection"
|
||||
# Find location of the name in the options list
|
||||
index_of_name = build_config["collection_name"]["options"].index(field_value)
|
||||
value_of_provider = build_config["collection_name"]["options_metadata"][index_of_name]["provider"]
|
||||
|
||||
# Set the advanced and required fields based on the collection choice
|
||||
build_config["embedding_choice"].update(
|
||||
{
|
||||
"advanced": not is_new_collection,
|
||||
"value": "Embedding Model" if is_new_collection else build_config["embedding_choice"].get("value"),
|
||||
}
|
||||
)
|
||||
|
||||
# Set the advanced field for the embedding model
|
||||
build_config["embedding_model"]["advanced"] = not is_new_collection
|
||||
|
||||
# Set the advanced and required fields for the new collection name
|
||||
build_config["collection_name_new"].update(
|
||||
{
|
||||
"advanced": not is_new_collection,
|
||||
"required": is_new_collection,
|
||||
"value": "" if not is_new_collection else build_config["collection_name_new"].get("value"),
|
||||
}
|
||||
)
|
||||
|
||||
# Get the collection options for the selected collection
|
||||
collection_options = self.get_collection_options()
|
||||
|
||||
# If the collection options are available (DB exists), show the advanced options
|
||||
if collection_options:
|
||||
build_config["embedding_choice"]["advanced"] = True
|
||||
|
||||
if collection_options.service:
|
||||
# Remove unnecessary fields when a service is set
|
||||
self.del_fields(
|
||||
build_config,
|
||||
[
|
||||
"embedding_provider",
|
||||
"model",
|
||||
"z_01_model_parameters",
|
||||
"z_02_api_key_name",
|
||||
"z_03_provider_api_key",
|
||||
"z_04_authentication",
|
||||
],
|
||||
)
|
||||
|
||||
# Update the providers mapping
|
||||
updates = {
|
||||
"embedding_model": {"advanced": True},
|
||||
"embedding_choice": {"value": "Astra Vectorize"},
|
||||
}
|
||||
else:
|
||||
# Update the providers mapping
|
||||
updates = {
|
||||
"embedding_model": {"advanced": False},
|
||||
"embedding_provider": {"advanced": False},
|
||||
"embedding_choice": {"value": "Embedding Model"},
|
||||
}
|
||||
|
||||
# Apply updates to the build_config
|
||||
for key, value in updates.items():
|
||||
build_config[key].update(value)
|
||||
|
||||
elif field_name == "embedding_choice":
|
||||
if field_value == "Astra Vectorize":
|
||||
if value_of_provider:
|
||||
build_config["embedding_model"]["advanced"] = True
|
||||
|
||||
# Update the providers mapping
|
||||
vectorize_providers = self.get_vectorize_providers()
|
||||
|
||||
new_parameter = DropdownInput(
|
||||
name="embedding_provider",
|
||||
display_name="Embedding Provider",
|
||||
options=vectorize_providers.keys(),
|
||||
value="",
|
||||
required=True,
|
||||
real_time_refresh=True,
|
||||
).to_dict()
|
||||
|
||||
self.insert_in_dict(build_config, "embedding_choice", {"embedding_provider": new_parameter})
|
||||
build_config["embedding_model"]["required"] = False
|
||||
else:
|
||||
build_config["embedding_model"]["advanced"] = False
|
||||
build_config["embedding_model"]["required"] = True
|
||||
|
||||
self.del_fields(
|
||||
build_config,
|
||||
[
|
||||
"embedding_provider",
|
||||
"model",
|
||||
"z_01_model_parameters",
|
||||
"z_02_api_key_name",
|
||||
"z_03_provider_api_key",
|
||||
"z_04_authentication",
|
||||
],
|
||||
)
|
||||
# For the final step, get the list of vectorize providers
|
||||
"""
|
||||
vectorize_providers = self.get_vectorize_providers()
|
||||
if not vectorize_providers:
|
||||
return build_config
|
||||
|
||||
elif field_name == "embedding_provider":
|
||||
self.del_fields(
|
||||
build_config,
|
||||
["model", "z_01_model_parameters", "z_02_api_key_name", "z_03_provider_api_key", "z_04_authentication"],
|
||||
)
|
||||
# Allow the user to see the embedding provider options
|
||||
provider_options = build_config["collection_name"]["dialog_inputs"]["fields"]["data"]["node"]["template"][
|
||||
"embedding_generation_provider"
|
||||
]["options"]
|
||||
if not provider_options:
|
||||
# If the collection is set, allow user to see embedding options
|
||||
build_config["collection_name"]["dialog_inputs"]["fields"]["data"]["node"]["template"][
|
||||
"embedding_generation_provider"
|
||||
]["options"] = ["Bring your own", "Nvidia", *[key for key in vectorize_providers if key != "Nvidia"]]
|
||||
|
||||
# Update the providers mapping
|
||||
vectorize_providers = self.get_vectorize_providers()
|
||||
model_options = vectorize_providers[field_value][1]
|
||||
# And allow the user to see the models based on a selected provider
|
||||
model_options = build_config["collection_name"]["dialog_inputs"]["fields"]["data"]["node"]["template"][
|
||||
"embedding_generation_model"
|
||||
]["options"]
|
||||
if not model_options:
|
||||
embedding_provider = build_config["collection_name"]["dialog_inputs"]["fields"]["data"]["node"]["template"][
|
||||
"embedding_generation_provider"
|
||||
]["value"]
|
||||
|
||||
new_parameter = DropdownInput(
|
||||
name="model",
|
||||
display_name="Model",
|
||||
info="The embedding model to use for the selected provider. Each provider has a different set of "
|
||||
"models available (full list at "
|
||||
"https://docs.datastax.com/en/astra-db-serverless/databases/embedding-generation.html):\n\n"
|
||||
f"{', '.join(model_options)}",
|
||||
options=model_options,
|
||||
value=None,
|
||||
required=True,
|
||||
real_time_refresh=True,
|
||||
).to_dict()
|
||||
|
||||
self.insert_in_dict(build_config, "embedding_provider", {"model": new_parameter})
|
||||
|
||||
elif field_name == "model":
|
||||
self.del_fields(
|
||||
build_config,
|
||||
["z_01_model_parameters", "z_02_api_key_name", "z_03_provider_api_key", "z_04_authentication"],
|
||||
)
|
||||
|
||||
new_parameter_1 = DictInput(
|
||||
name="z_01_model_parameters",
|
||||
display_name="Model Parameters",
|
||||
list=True,
|
||||
).to_dict()
|
||||
|
||||
new_parameter_2 = MessageTextInput(
|
||||
name="z_02_api_key_name",
|
||||
display_name="API Key Name",
|
||||
info="The name of the embeddings provider API key stored on Astra. "
|
||||
"If set, it will override the 'ProviderKey' in the authentication parameters.",
|
||||
).to_dict()
|
||||
|
||||
new_parameter_3 = SecretStrInput(
|
||||
load_from_db=False,
|
||||
name="z_03_provider_api_key",
|
||||
display_name="Provider API Key",
|
||||
info="An alternative to the Astra Authentication that passes an API key for the provider "
|
||||
"with each request to Astra DB. "
|
||||
"This may be used when Vectorize is configured for the collection, "
|
||||
"but no corresponding provider secret is stored within Astra's key management system.",
|
||||
).to_dict()
|
||||
|
||||
new_parameter_4 = DictInput(
|
||||
name="z_04_authentication",
|
||||
display_name="Authentication Parameters",
|
||||
list=True,
|
||||
).to_dict()
|
||||
|
||||
self.insert_in_dict(
|
||||
build_config,
|
||||
"model",
|
||||
{
|
||||
"z_01_model_parameters": new_parameter_1,
|
||||
"z_02_api_key_name": new_parameter_2,
|
||||
"z_03_provider_api_key": new_parameter_3,
|
||||
"z_04_authentication": new_parameter_4,
|
||||
},
|
||||
)
|
||||
build_config["collection_name"]["dialog_inputs"]["fields"]["data"]["node"]["template"][
|
||||
"embedding_generation_model"
|
||||
]["options"] = vectorize_providers.get(embedding_provider, [[], []])[1]
|
||||
"""
|
||||
|
||||
return build_config
|
||||
|
||||
def build_vectorize_options(self, **kwargs):
|
||||
for attribute in [
|
||||
"embedding_provider",
|
||||
"model",
|
||||
"z_01_model_parameters",
|
||||
"z_02_api_key_name",
|
||||
"z_03_provider_api_key",
|
||||
"z_04_authentication",
|
||||
]:
|
||||
if not hasattr(self, attribute):
|
||||
setattr(self, attribute, None)
|
||||
|
||||
# Fetch values from kwargs if any self.* attributes are None
|
||||
provider_mapping = self.get_vectorize_providers()
|
||||
provider_value = provider_mapping.get(self.embedding_provider, [None])[0] or kwargs.get("embedding_provider")
|
||||
model_name = self.model or kwargs.get("model")
|
||||
authentication = {**(self.z_04_authentication or {}), **kwargs.get("z_04_authentication", {})}
|
||||
parameters = self.z_01_model_parameters or kwargs.get("z_01_model_parameters", {})
|
||||
|
||||
# Set the API key name if provided
|
||||
api_key_name = self.z_02_api_key_name or kwargs.get("z_02_api_key_name")
|
||||
provider_key = self.z_03_provider_api_key or kwargs.get("z_03_provider_api_key")
|
||||
if api_key_name:
|
||||
authentication["providerKey"] = api_key_name
|
||||
if authentication:
|
||||
provider_key = None
|
||||
authentication["providerKey"] = authentication["providerKey"].split(".")[0]
|
||||
|
||||
# Set authentication and parameters to None if no values are provided
|
||||
if not authentication:
|
||||
authentication = None
|
||||
if not parameters:
|
||||
parameters = None
|
||||
|
||||
return {
|
||||
# must match astrapy.info.CollectionVectorServiceOptions
|
||||
"collection_vector_service_options": {
|
||||
"provider": provider_value,
|
||||
"modelName": model_name,
|
||||
"authentication": authentication,
|
||||
"parameters": parameters,
|
||||
},
|
||||
"collection_embedding_api_key": provider_key,
|
||||
}
|
||||
|
||||
@check_cached_vector_store
|
||||
def build_vector_store(self, vectorize_options=None):
|
||||
def build_vector_store(self):
|
||||
try:
|
||||
from langchain_astradb import AstraDBVectorStore
|
||||
except ImportError as e:
|
||||
|
|
@ -538,36 +593,9 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
)
|
||||
raise ImportError(msg) from e
|
||||
|
||||
# Initialize parameters based on the collection name
|
||||
is_new_collection = self.get_collection_options() is None
|
||||
|
||||
# Get the embedding model
|
||||
embedding_params = {"embedding": self.embedding_model} if self.embedding_choice == "Embedding Model" else {}
|
||||
|
||||
# Use the embedding model if the choice is set to "Embedding Model"
|
||||
if self.embedding_choice == "Astra Vectorize" and is_new_collection:
|
||||
from astrapy.info import CollectionVectorServiceOptions
|
||||
|
||||
# Build the vectorize options dictionary
|
||||
dict_options = vectorize_options or self.build_vectorize_options(
|
||||
embedding_provider=getattr(self, "embedding_provider", None) or None,
|
||||
model=getattr(self, "model", None) or None,
|
||||
z_01_model_parameters=getattr(self, "z_01_model_parameters", None) or None,
|
||||
z_02_api_key_name=getattr(self, "z_02_api_key_name", None) or None,
|
||||
z_03_provider_api_key=getattr(self, "z_03_provider_api_key", None) or None,
|
||||
z_04_authentication=getattr(self, "z_04_authentication", {}) or {},
|
||||
)
|
||||
|
||||
# Set the embedding dictionary
|
||||
embedding_params = {
|
||||
"collection_vector_service_options": CollectionVectorServiceOptions.from_dict(
|
||||
dict_options.get("collection_vector_service_options")
|
||||
),
|
||||
"collection_embedding_api_key": dict_options.get("collection_embedding_api_key"),
|
||||
}
|
||||
|
||||
# Get the running environment for Langflow
|
||||
environment = parse_api_endpoint(self.get_api_endpoint()).environment if self.get_api_endpoint() else None
|
||||
# Get the embedding model and additional params
|
||||
embedding_params = {"embedding": self.embedding_model} if self.embedding_model else {}
|
||||
additional_params = self.astradb_vectorstore_kwargs or {}
|
||||
|
||||
# Get Langflow version and platform information
|
||||
__version__ = get_version_info()["version"]
|
||||
|
|
@ -577,9 +605,16 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
|
||||
# Bundle up the auto-detect parameters
|
||||
autodetect_params = {
|
||||
# TODO: May want to expose this option
|
||||
"autodetect_collection": not is_new_collection,
|
||||
"content_field": self.content_field or None,
|
||||
"autodetect_collection": self.collection_exists(), # TODO: May want to expose this option
|
||||
"content_field": (
|
||||
self.content_field
|
||||
if self.content_field and embedding_params
|
||||
else (
|
||||
"page_content"
|
||||
if embedding_params and self.collection_data(collection_name=self.collection_name) == 0
|
||||
else None
|
||||
)
|
||||
),
|
||||
"ignore_invalid_documents": self.ignore_invalid_documents,
|
||||
}
|
||||
|
||||
|
|
@ -589,15 +624,15 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
# Astra DB Authentication Parameters
|
||||
token=self.token,
|
||||
api_endpoint=self.get_api_endpoint(),
|
||||
namespace=self.keyspace or None,
|
||||
collection_name=self.get_collection_choice(),
|
||||
environment=environment,
|
||||
namespace=self.get_keyspace(),
|
||||
collection_name=self.collection_name,
|
||||
environment=self.environment,
|
||||
# Astra DB Usage Tracking Parameters
|
||||
ext_callers=[(f"{langflow_prefix}langflow", __version__)],
|
||||
# Astra DB Vector Store Parameters
|
||||
**autodetect_params or {},
|
||||
**embedding_params or {},
|
||||
**self.astradb_vectorstore_kwargs or {},
|
||||
**autodetect_params,
|
||||
**embedding_params,
|
||||
**additional_params,
|
||||
)
|
||||
except Exception as e:
|
||||
msg = f"Error initializing AstraDBVectorStore: {e}"
|
||||
|
|
@ -619,8 +654,8 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
if documents and self.deletion_field:
|
||||
self.log(f"Deleting documents where {self.deletion_field}")
|
||||
try:
|
||||
database = self.get_database()
|
||||
collection = database.get_collection(self.get_collection_choice(), keyspace=self.keyspace or None)
|
||||
database = self.get_database_object()
|
||||
collection = database.get_collection(self.collection_name, keyspace=self.get_keyspace())
|
||||
delete_values = list({doc.metadata[self.deletion_field] for doc in documents})
|
||||
self.log(f"Deleting documents where {self.deletion_field} matches {delete_values}.")
|
||||
collection.delete_many({f"metadata.{self.deletion_field}": {"$in": delete_values}})
|
||||
|
|
@ -639,11 +674,12 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
self.log("No documents to add to the Vector Store.")
|
||||
|
||||
def _map_search_type(self) -> str:
|
||||
if self.search_type == "Similarity with score threshold":
|
||||
return "similarity_score_threshold"
|
||||
if self.search_type == "MMR (Max Marginal Relevance)":
|
||||
return "mmr"
|
||||
return "similarity"
|
||||
search_type_mapping = {
|
||||
"Similarity with score threshold": "similarity_score_threshold",
|
||||
"MMR (Max Marginal Relevance)": "mmr",
|
||||
}
|
||||
|
||||
return search_type_mapping.get(self.search_type, "similarity")
|
||||
|
||||
def _build_search_args(self):
|
||||
query = self.search_query if isinstance(self.search_query, str) and self.search_query.strip() else None
|
||||
|
|
@ -700,10 +736,12 @@ class AstraDBVectorStoreComponent(LCVectorStoreComponent):
|
|||
data = docs_to_data(docs)
|
||||
self.log(f"Converted documents to data: {len(data)}")
|
||||
self.status = data
|
||||
|
||||
return data
|
||||
|
||||
def get_retriever_kwargs(self):
|
||||
search_args = self._build_search_args()
|
||||
|
||||
return {
|
||||
"search_type": self._map_search_type(),
|
||||
"search_kwargs": search_args,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -80,6 +80,7 @@ class BaseInputMixin(BaseModel, validate_assignment=True): # type: ignore[call-
|
|||
|
||||
refresh_button: bool | None = None
|
||||
"""Specifies if the field should have a refresh button. Defaults to False."""
|
||||
|
||||
refresh_button_text: str | None = None
|
||||
"""Specifies the text for the refresh button. Defaults to None."""
|
||||
|
||||
|
|
@ -158,8 +159,12 @@ class RangeMixin(BaseModel):
|
|||
class DropDownMixin(BaseModel):
|
||||
options: list[str] | None = None
|
||||
"""List of options for the field. Only used when is_list=True. Default is an empty list."""
|
||||
options_metadata: list[dict[str, Any]] | None = None
|
||||
"""List of dictionaries with metadata for each option."""
|
||||
combobox: CoalesceBool = False
|
||||
"""Variable that defines if the user can insert custom values in the dropdown."""
|
||||
dialog_inputs: dict[str, Any] | None = None
|
||||
"""Dictionary of dialog inputs for the field. Default is an empty object."""
|
||||
|
||||
|
||||
class MultilineMixin(BaseModel):
|
||||
|
|
|
|||
|
|
@ -424,11 +424,16 @@ class DropdownInput(BaseInputMixin, DropDownMixin, MetadataTraceMixin, ToolModeM
|
|||
field_type (SerializableFieldTypes): The field type of the input. Defaults to FieldTypes.TEXT.
|
||||
options (Optional[Union[list[str], Callable]]): List of options for the field.
|
||||
Default is None.
|
||||
options_metadata (Optional[list[dict[str, str]]): List of dictionaries with metadata for each option.
|
||||
Default is None.
|
||||
combobox (CoalesceBool): Variable that defines if the user can insert custom values in the dropdown.
|
||||
"""
|
||||
|
||||
field_type: SerializableFieldTypes = FieldTypes.TEXT
|
||||
options: list[str] = Field(default_factory=list)
|
||||
options_metadata: list[dict[str, Any]] = Field(default_factory=list)
|
||||
combobox: CoalesceBool = False
|
||||
dialog_inputs: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class MultiselectInput(BaseInputMixin, ListableInputMixin, DropDownMixin, MetadataTraceMixin, ToolModeMixin):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import os
|
||||
|
||||
import pytest
|
||||
from astrapy.db import AstraDB
|
||||
from astrapy import DataAPIClient
|
||||
from langchain_astradb import AstraDBVectorStore, CollectionVectorServiceOptions
|
||||
from langchain_core.documents import Document
|
||||
from langflow.components.embeddings import OpenAIEmbeddingsComponent
|
||||
|
|
@ -30,14 +30,21 @@ ALL_COLLECTIONS = [
|
|||
|
||||
@pytest.fixture
|
||||
def astradb_client():
|
||||
client = AstraDB(api_endpoint=get_astradb_api_endpoint(), token=get_astradb_application_token())
|
||||
yield client
|
||||
api_client = DataAPIClient(token=get_astradb_application_token())
|
||||
client = api_client.get_database(get_astradb_api_endpoint())
|
||||
|
||||
yield client # Provide the client to the test functions
|
||||
|
||||
# Cleanup: Drop all collections after tests
|
||||
for collection in ALL_COLLECTIONS:
|
||||
client.delete_collection(collection)
|
||||
try: # noqa: SIM105
|
||||
client.drop_collection(collection)
|
||||
except Exception: # noqa: BLE001, S110
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.api_key_required
|
||||
async def test_base(astradb_client: AstraDB):
|
||||
async def test_base(astradb_client: DataAPIClient):
|
||||
application_token = get_astradb_application_token()
|
||||
api_endpoint = get_astradb_api_endpoint()
|
||||
|
||||
|
|
@ -56,7 +63,7 @@ async def test_base(astradb_client: AstraDB):
|
|||
)
|
||||
|
||||
assert results["search_results"] == []
|
||||
assert astradb_client.collection(BASIC_COLLECTION)
|
||||
assert astradb_client.get_collection(BASIC_COLLECTION)
|
||||
|
||||
|
||||
@pytest.mark.api_key_required
|
||||
|
|
@ -92,8 +99,8 @@ def test_astra_vectorize():
|
|||
|
||||
store = None
|
||||
try:
|
||||
# Get the vectorize options
|
||||
options = {"provider": "nvidia", "modelName": "NV-Embed-QA"}
|
||||
options_comp = {"embedding_provider": "nvidia", "model": "NV-Embed-QA"}
|
||||
|
||||
store = AstraDBVectorStore(
|
||||
collection_name=VECTORIZE_COLLECTION,
|
||||
|
|
@ -106,7 +113,6 @@ def test_astra_vectorize():
|
|||
records = [Data.from_document(d) for d in documents]
|
||||
|
||||
component = AstraDBVectorStoreComponent()
|
||||
vectorize_options = component.build_vectorize_options(**options_comp)
|
||||
|
||||
component.build(
|
||||
token=application_token,
|
||||
|
|
@ -115,9 +121,8 @@ def test_astra_vectorize():
|
|||
ingest_data=records,
|
||||
search_query="test",
|
||||
number_of_results=2,
|
||||
pre_delete_collection=True,
|
||||
)
|
||||
vector_store = component.build_vector_store(vectorize_options)
|
||||
vector_store = component.build_vector_store()
|
||||
records = component.search_documents(vector_store=vector_store)
|
||||
|
||||
assert len(records) == 2
|
||||
|
|
@ -141,14 +146,6 @@ def test_astra_vectorize_with_provider_api_key():
|
|||
"authentication": {"providerKey": "openai"},
|
||||
}
|
||||
|
||||
options_comp = {
|
||||
"embedding_provider": "openai",
|
||||
"model": "text-embedding-3-small",
|
||||
"z_01_model_parameters": {},
|
||||
"z_03_provider_api_key": "openai",
|
||||
"z_04_authentication": {},
|
||||
}
|
||||
|
||||
store = AstraDBVectorStore(
|
||||
collection_name=VECTORIZE_COLLECTION_OPENAI,
|
||||
api_endpoint=api_endpoint,
|
||||
|
|
@ -160,7 +157,6 @@ def test_astra_vectorize_with_provider_api_key():
|
|||
records = [Data.from_document(d) for d in documents]
|
||||
|
||||
component = AstraDBVectorStoreComponent()
|
||||
vectorize_options = component.build_vectorize_options(**options_comp)
|
||||
|
||||
component.build(
|
||||
token=application_token,
|
||||
|
|
@ -169,10 +165,9 @@ def test_astra_vectorize_with_provider_api_key():
|
|||
ingest_data=records,
|
||||
search_query="test",
|
||||
number_of_results=2,
|
||||
pre_delete_collection=True,
|
||||
)
|
||||
|
||||
vector_store = component.build_vector_store(vectorize_options)
|
||||
vector_store = component.build_vector_store()
|
||||
records = component.search_documents(vector_store=vector_store)
|
||||
|
||||
assert len(records) == 2
|
||||
|
|
@ -195,12 +190,6 @@ def test_astra_vectorize_passes_authentication():
|
|||
"parameters": {},
|
||||
"authentication": {"providerKey": "openai"},
|
||||
}
|
||||
options_comp = {
|
||||
"embedding_provider": "openai",
|
||||
"model": "text-embedding-3-small",
|
||||
"z_01_model_parameters": {},
|
||||
"z_04_authentication": {"providerKey": "openai"},
|
||||
}
|
||||
|
||||
store = AstraDBVectorStore(
|
||||
collection_name=VECTORIZE_COLLECTION_OPENAI_WITH_AUTH,
|
||||
|
|
@ -213,7 +202,6 @@ def test_astra_vectorize_passes_authentication():
|
|||
records = [Data.from_document(d) for d in documents]
|
||||
|
||||
component = AstraDBVectorStoreComponent()
|
||||
vectorize_options = component.build_vectorize_options(**options_comp)
|
||||
|
||||
component.build(
|
||||
token=application_token,
|
||||
|
|
@ -222,10 +210,9 @@ def test_astra_vectorize_passes_authentication():
|
|||
ingest_data=records,
|
||||
search_query="test",
|
||||
number_of_results=2,
|
||||
pre_delete_collection=True,
|
||||
)
|
||||
|
||||
vector_store = component.build_vector_store(vectorize_options)
|
||||
vector_store = component.build_vector_store()
|
||||
records = component.search_documents(vector_store=vector_store)
|
||||
|
||||
assert len(records) == 2
|
||||
|
|
|
|||
351
src/frontend/package-lock.json
generated
351
src/frontend/package-lock.json
generated
|
|
@ -4040,9 +4040,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz",
|
||||
"integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.0.tgz",
|
||||
"integrity": "sha512-qFcFto9figFLz2g25DxJ1WWL9+c91fTxnGuwhToCl8BaqDsDYMl/kOnBXAyAqkkzAWimYMSWNPWEjt+ADAHuoQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
|
@ -4052,9 +4052,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz",
|
||||
"integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.30.0.tgz",
|
||||
"integrity": "sha512-vqrQdusvVl7dthqNjWCL043qelBK+gv9v3ZiqdxgaJvmZyIAAXMjeGVSqZynKq69T7062T5VrVTuikKSAAVP6A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4064,9 +4064,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz",
|
||||
"integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.0.tgz",
|
||||
"integrity": "sha512-617pd92LhdA9+wpixnzsyhVft3szYiN16aNUMzVkf2N+yAk8UXY226Bfp36LvxYTUt7MO/ycqGFjQgJ0wlMaWQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4076,9 +4076,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz",
|
||||
"integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.30.0.tgz",
|
||||
"integrity": "sha512-Y3b4oDoaEhCypg8ajPqigKDcpi5ZZovemQl9Edpem0uNv6UUjXv7iySBpGIUTSs2ovWOzYpfw9EbFJXF/fJHWw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4088,9 +4088,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz",
|
||||
"integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.30.0.tgz",
|
||||
"integrity": "sha512-3REQJ4f90sFIBfa0BUokiCdrV/E4uIjhkWe1bMgCkhFXbf4D8YN6C4zwJL881GM818qVYE9BO3dGwjKhpo2ABA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4100,9 +4100,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz",
|
||||
"integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.0.tgz",
|
||||
"integrity": "sha512-ZtY3Y8icbe3Cc+uQicsXG5L+CRGUfLZjW6j2gn5ikpltt3Whqjfo5mkyZ86UiuHF9Q3ZsaQeW7YswlHnN+lAcg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4112,9 +4112,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz",
|
||||
"integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.30.0.tgz",
|
||||
"integrity": "sha512-bsPGGzfiHXMhQGuFGpmo2PyTwcrh2otL6ycSZAFTESviUoBOuxF7iBbAL5IJXc/69peXl5rAtbewBFeASZ9O0g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
|
@ -4124,9 +4124,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz",
|
||||
"integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.30.0.tgz",
|
||||
"integrity": "sha512-kvyIECEhs2DrrdfQf++maCWJIQ974EI4txlz1nNSBaCdtf7i5Xf1AQCEJWOC5rEBisdaMFFnOWNLYt7KpFqy5A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
|
@ -4136,9 +4136,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz",
|
||||
"integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.30.0.tgz",
|
||||
"integrity": "sha512-CFE7zDNrokaotXu+shwIrmWrFxllg79vciH4E/zeK7NitVuWEaXRzS0mFfFvyhZfn8WfVOG/1E9u8/DFEgK7WQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4148,9 +4148,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz",
|
||||
"integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.30.0.tgz",
|
||||
"integrity": "sha512-MctNTBlvMcIBP0t8lV/NXiUwFg9oK5F79CxLU+a3xgrdJjfBLVIEHSAjQ9+ipofN2GKaMLnFFXLltg1HEEPaGQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4160,9 +4160,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz",
|
||||
"integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.30.0.tgz",
|
||||
"integrity": "sha512-fBpoYwLEPivL3q368+gwn4qnYnr7GVwM6NnMo8rJ4wb0p/Y5lg88vQRRP077gf+tc25akuqd+1Sxbn9meODhwA==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
|
|
@ -4172,9 +4172,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz",
|
||||
"integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.30.0.tgz",
|
||||
"integrity": "sha512-1hiHPV6dUaqIMXrIjN+vgJqtfkLpqHS1Xsg0oUfUVD98xGp1wX89PIXgDF2DWra1nxAd8dfE0Dk59MyeKaBVAw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
|
|
@ -4184,9 +4184,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz",
|
||||
"integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.30.0.tgz",
|
||||
"integrity": "sha512-U0xcC80SMpEbvvLw92emHrNjlS3OXjAM0aVzlWfar6PR0ODWCTQtKeeB+tlAPGfZQXicv1SpWwRz9Hyzq3Jx3g==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
|
|
@ -4196,9 +4196,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz",
|
||||
"integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.30.0.tgz",
|
||||
"integrity": "sha512-VU/P/IODrNPasgZDLIFJmMiLGez+BN11DQWfTVlViJVabyF3JaeaJkP6teI8760f18BMGCQOW9gOmuzFaI1pUw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
|
|
@ -4208,9 +4208,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz",
|
||||
"integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.30.0.tgz",
|
||||
"integrity": "sha512-laQVRvdbKmjXuFA3ZiZj7+U24FcmoPlXEi2OyLfbpY2MW1oxLt9Au8q9eHd0x6Pw/Kw4oe9gwVXWwIf2PVqblg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4220,9 +4220,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz",
|
||||
"integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.30.0.tgz",
|
||||
"integrity": "sha512-3wzKzduS7jzxqcOvy/ocU/gMR3/QrHEFLge5CD7Si9fyHuoXcidyYZ6jyx8OPYmCcGm3uKTUl+9jUSAY74Ln5A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4232,9 +4232,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz",
|
||||
"integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.30.0.tgz",
|
||||
"integrity": "sha512-jROwnI1+wPyuv696rAFHp5+6RFhXGGwgmgSfzE8e4xfit6oLRg7GyMArVUoM3ChS045OwWr9aTnU+2c1UdBMyw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4244,9 +4244,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz",
|
||||
"integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.30.0.tgz",
|
||||
"integrity": "sha512-duzweyup5WELhcXx5H1jokpr13i3BV9b48FMiikYAwk/MT1LrMYYk2TzenBd0jj4ivQIt58JWSxc19y4SvLP4g==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
|
|
@ -4256,9 +4256,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz",
|
||||
"integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.30.0.tgz",
|
||||
"integrity": "sha512-DYvxS0M07PvgvavMIybCOBYheyrqlui6ZQBHJs6GqduVzHSZ06TPPvlfvnYstjODHQ8UUXFwt5YE+h0jFI8kwg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4585,9 +4585,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.1.tgz",
|
||||
"integrity": "sha512-rQ4dS6GAdmtzKiCRt3LFVxl37FaY1cgL9kSUTnhQ2xc3fmHOd7jdJK/V4pSZMG1ruGTd0bsi34O2R0Olg9Zo/w==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.4.tgz",
|
||||
"integrity": "sha512-ut3zfiTLORMxhr6y/GBxkHmzcGuVpwJYX4qyXWuBKkpw/0g0S5iO1/wW7RnLnZbAi8wS/n0atRZoaZlXWBkeJg==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
|
|
@ -4602,16 +4602,16 @@
|
|||
"url": "https://opencollective.com/swc"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-darwin-arm64": "1.10.1",
|
||||
"@swc/core-darwin-x64": "1.10.1",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.10.1",
|
||||
"@swc/core-linux-arm64-gnu": "1.10.1",
|
||||
"@swc/core-linux-arm64-musl": "1.10.1",
|
||||
"@swc/core-linux-x64-gnu": "1.10.1",
|
||||
"@swc/core-linux-x64-musl": "1.10.1",
|
||||
"@swc/core-win32-arm64-msvc": "1.10.1",
|
||||
"@swc/core-win32-ia32-msvc": "1.10.1",
|
||||
"@swc/core-win32-x64-msvc": "1.10.1"
|
||||
"@swc/core-darwin-arm64": "1.10.4",
|
||||
"@swc/core-darwin-x64": "1.10.4",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.10.4",
|
||||
"@swc/core-linux-arm64-gnu": "1.10.4",
|
||||
"@swc/core-linux-arm64-musl": "1.10.4",
|
||||
"@swc/core-linux-x64-gnu": "1.10.4",
|
||||
"@swc/core-linux-x64-musl": "1.10.4",
|
||||
"@swc/core-win32-arm64-msvc": "1.10.4",
|
||||
"@swc/core-win32-ia32-msvc": "1.10.4",
|
||||
"@swc/core-win32-x64-msvc": "1.10.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/helpers": "*"
|
||||
|
|
@ -4623,9 +4623,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-arm64": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.1.tgz",
|
||||
"integrity": "sha512-NyELPp8EsVZtxH/mEqvzSyWpfPJ1lugpTQcSlMduZLj1EASLO4sC8wt8hmL1aizRlsbjCX+r0PyL+l0xQ64/6Q==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.4.tgz",
|
||||
"integrity": "sha512-sV/eurLhkjn/197y48bxKP19oqcLydSel42Qsy2zepBltqUx+/zZ8+/IS0Bi7kaWVFxerbW1IPB09uq8Zuvm3g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4639,9 +4639,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.1.tgz",
|
||||
"integrity": "sha512-L4BNt1fdQ5ZZhAk5qoDfUnXRabDOXKnXBxMDJ+PWLSxOGBbWE6aJTnu4zbGjJvtot0KM46m2LPAPY8ttknqaZA==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.4.tgz",
|
||||
"integrity": "sha512-gjYNU6vrAUO4+FuovEo9ofnVosTFXkF0VDuo1MKPItz6e2pxc2ale4FGzLw0Nf7JB1sX4a8h06CN16/pLJ8Q2w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4655,9 +4655,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.1.tgz",
|
||||
"integrity": "sha512-Y1u9OqCHgvVp2tYQAJ7hcU9qO5brDMIrA5R31rwWQIAKDkJKtv3IlTHF0hrbWk1wPR0ZdngkQSJZple7G+Grvw==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.4.tgz",
|
||||
"integrity": "sha512-zd7fXH5w8s+Sfvn2oO464KDWl+ZX1MJiVmE4Pdk46N3PEaNwE0koTfgx2vQRqRG4vBBobzVvzICC3618WcefOA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
|
@ -4671,9 +4671,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.1.tgz",
|
||||
"integrity": "sha512-tNQHO/UKdtnqjc7o04iRXng1wTUXPgVd8Y6LI4qIbHVoVPwksZydISjMcilKNLKIwOoUQAkxyJ16SlOAeADzhQ==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.4.tgz",
|
||||
"integrity": "sha512-+UGfoHDxsMZgFD3tABKLeEZHqLNOkxStu+qCG7atGBhS4Slri6h6zijVvf4yI5X3kbXdvc44XV/hrP/Klnui2A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4687,9 +4687,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.1.tgz",
|
||||
"integrity": "sha512-x0L2Pd9weQ6n8dI1z1Isq00VHFvpBClwQJvrt3NHzmR+1wCT/gcYl1tp9P5xHh3ldM8Cn4UjWCw+7PaUgg8FcQ==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.4.tgz",
|
||||
"integrity": "sha512-cDDj2/uYsOH0pgAnDkovLZvKJpFmBMyXkxEG6Q4yw99HbzO6QzZ5HDGWGWVq/6dLgYKlnnmpjZCPPQIu01mXEg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4703,9 +4703,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.1.tgz",
|
||||
"integrity": "sha512-yyYEwQcObV3AUsC79rSzN9z6kiWxKAVJ6Ntwq2N9YoZqSPYph+4/Am5fM1xEQYf/kb99csj0FgOelomJSobxQA==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.4.tgz",
|
||||
"integrity": "sha512-qJXh9D6Kf5xSdGWPINpLGixAbB5JX8JcbEJpRamhlDBoOcQC79dYfOMEIxWPhTS1DGLyFakAx2FX/b2VmQmj0g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4719,9 +4719,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.1.tgz",
|
||||
"integrity": "sha512-tcaS43Ydd7Fk7sW5ROpaf2Kq1zR+sI5K0RM+0qYLYYurvsJruj3GhBCaiN3gkzd8m/8wkqNqtVklWaQYSDsyqA==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.4.tgz",
|
||||
"integrity": "sha512-A76lIAeyQnHCVt0RL/pG+0er8Qk9+acGJqSZOZm67Ve3B0oqMd871kPtaHBM0BW3OZAhoILgfHW3Op9Q3mx3Cw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4735,9 +4735,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.1.tgz",
|
||||
"integrity": "sha512-D3Qo1voA7AkbOzQ2UGuKNHfYGKL6eejN8VWOoQYtGHHQi1p5KK/Q7V1ku55oxXBsj79Ny5FRMqiRJpVGad7bjQ==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-e6j5kBu4fIY7fFxFxnZI0MlEovRvp50Lg59Fw+DVbtqHk3C85dckcy5xKP+UoXeuEmFceauQDczUcGs19SRGSQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4751,9 +4751,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.1.tgz",
|
||||
"integrity": "sha512-WalYdFoU3454Og+sDKHM1MrjvxUGwA2oralknXkXL8S0I/8RkWZOB++p3pLaGbTvOO++T+6znFbQdR8KRaa7DA==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-RSYHfdKgNXV/amY5Tqk1EWVsyQnhlsM//jeqMLw5Fy9rfxP592W9UTumNikNRPdjI8wKKzNMXDb1U29tQjN0dg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
|
|
@ -4767,9 +4767,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.1.tgz",
|
||||
"integrity": "sha512-JWobfQDbTnoqaIwPKQ3DVSywihVXlQMbDuwik/dDWlj33A8oEHcjPOGs4OqcA3RHv24i+lfCQpM3Mn4FAMfacA==",
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-1ujYpaqfqNPYdwKBlvJnOqcl+Syn3UrQ4XE0Txz6zMYgyh6cdU6a3pxqLqIUSJ12MtXRA9ZUhEz1ekU3LfLWXw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4876,20 +4876,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "5.62.9",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.62.9.tgz",
|
||||
"integrity": "sha512-lwePd8hNYhyQ4nM/iRQ+Wz2cDtspGeZZHFZmCzHJ7mfKXt+9S301fULiY2IR2byJYY6Z03T427E5PoVfMexHjw==",
|
||||
"version": "5.62.15",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.62.15.tgz",
|
||||
"integrity": "sha512-wT20X14CxcWY8YLJ/1pnsXn/y1Q2uRJZYWW93PWRtZt+3/JlGZyiyTcO4pGnqycnP7CokCROAyatsraosqZsDA==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-query": {
|
||||
"version": "5.62.9",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.62.9.tgz",
|
||||
"integrity": "sha512-jFUH9pOsOyN2ugGIR8tjz2+bRC0PEp25LvpNvYIgiEegP5Xbfi9phuNOMnjFugyg3GM0WI/HfUEE7eM2vmcbxg==",
|
||||
"version": "5.62.15",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.62.15.tgz",
|
||||
"integrity": "sha512-Ny3xxsOWmEQCFyHiV3CF7t6+QAV+LpBEREiXyllKR4+tStyd8smOAa98ZHmEx0ZNy36M31K8enifB5wTSYAKJw==",
|
||||
"dependencies": {
|
||||
"@tanstack/query-core": "5.62.9"
|
||||
"@tanstack/query-core": "5.62.15"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
|
|
@ -5284,9 +5284,9 @@
|
|||
"integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="
|
||||
},
|
||||
"node_modules/@types/d3-shape": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz",
|
||||
"integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==",
|
||||
"version": "3.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz",
|
||||
"integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==",
|
||||
"dependencies": {
|
||||
"@types/d3-path": "*"
|
||||
}
|
||||
|
|
@ -5474,9 +5474,9 @@
|
|||
"integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.17.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz",
|
||||
"integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==",
|
||||
"version": "20.17.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.12.tgz",
|
||||
"integrity": "sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
|
|
@ -5767,9 +5767,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ace-builds": {
|
||||
"version": "1.37.1",
|
||||
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.37.1.tgz",
|
||||
"integrity": "sha512-6/jxFucA1z1C3hgLlVkTE5/znZ+iYvD301vfwtybiMc3k76IDykliCD0xh/eYZMJUfsJtaOQHZ2AJO5ey0PHWw=="
|
||||
"version": "1.37.2",
|
||||
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.37.2.tgz",
|
||||
"integrity": "sha512-jkJccO2a75aC6HWIPcRBhMA99IRbvBDoy1lXvjr3QfHYa0rZtaC6ZY2RjlcEFrcFdaNAOHe8jMaei5p1rbDKGw=="
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
|
|
@ -6141,9 +6141,9 @@
|
|||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/bare-events": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz",
|
||||
"integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==",
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.2.tgz",
|
||||
"integrity": "sha512-KSdMqLj1ZERZMP1PTmnLK7SqJu9z9/SbwUUPZly2puMtfVcytC+jl6mb/9XYiqq0PXcx1rNDS+Qvl1g54Lho6A==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
|
|
@ -6458,9 +6458,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/canvas": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/canvas/-/canvas-3.0.0.tgz",
|
||||
"integrity": "sha512-NtcIBY88FjymQy+g2g5qnuP5IslrbWCQ3A6rSr1PeuYxVRapRZ3BZCrDyAakvI6CuDYidgZaf55ygulFVwROdg==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/canvas/-/canvas-3.0.1.tgz",
|
||||
"integrity": "sha512-PcpVF4f8RubAeN/jCQQ/UymDKzOiLmRPph8fOTzDnlsUihkO/AUlxuhaa7wGRc3vMcCbV1fzuvyu5cWZlIcn1w==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
|
|
@ -7392,17 +7392,17 @@
|
|||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
||||
},
|
||||
"node_modules/effect": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/effect/-/effect-3.12.0.tgz",
|
||||
"integrity": "sha512-b/u9s3b9HfTo0qygVouegP0hkbiuxRIeaCe1ppf8P88hPyl6lKCbErtn7Az4jG7LuU7f0Wgm4c8WXbMcL2j8+g==",
|
||||
"version": "3.12.1",
|
||||
"resolved": "https://registry.npmjs.org/effect/-/effect-3.12.1.tgz",
|
||||
"integrity": "sha512-aAZdh56Yp1ehOFYeMcHHctTtxfqm6kkOdZFTXK6Zf0QoaKKc1hPG6ocjrKOc0axE8JbG4eZw351ogNLrM4vo9w==",
|
||||
"dependencies": {
|
||||
"fast-check": "^3.23.1"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.75",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.75.tgz",
|
||||
"integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q=="
|
||||
"version": "1.5.76",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz",
|
||||
"integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ=="
|
||||
},
|
||||
"node_modules/elkjs": {
|
||||
"version": "0.9.3",
|
||||
|
|
@ -7907,15 +7907,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.4"
|
||||
"micromatch": "^4.0.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6.0"
|
||||
|
|
@ -8269,12 +8269,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/framer-motion": {
|
||||
"version": "11.15.0",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.15.0.tgz",
|
||||
"integrity": "sha512-MLk8IvZntxOMg7lDBLw2qgTHHv664bYoYmnFTmE0Gm/FW67aOJk0WM3ctMcG+Xhcv+vh5uyyXwxvxhSeJzSe+w==",
|
||||
"version": "11.16.0",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.16.0.tgz",
|
||||
"integrity": "sha512-oL2AWqLQuw0+CNEUa0sz3mWC/n3i147CckvpQn8bLRs30b+HxTxlRi0YR2FpHHhAbWV7DKjNdHU42KHLfBWh/g==",
|
||||
"dependencies": {
|
||||
"motion-dom": "^11.14.3",
|
||||
"motion-utils": "^11.14.3",
|
||||
"motion-dom": "^11.16.0",
|
||||
"motion-utils": "^11.16.0",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
@ -8792,9 +8792,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/hono": {
|
||||
"version": "4.6.14",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.6.14.tgz",
|
||||
"integrity": "sha512-j4VkyUp2xazGJ8eCCLN1Vm/bxdvm/j5ZuU9AIjLu9vapn2M44p9L3Ktr9Vnb2RN2QtcR/wVjZVMlT5k7GJQgPw==",
|
||||
"version": "4.6.16",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.6.16.tgz",
|
||||
"integrity": "sha512-iE6xOPwDYlfnZFwk6BfIMMIH4WZm3pPhz6rc1uJM/OPew0pjG5K6p8WTLaMBY1/szF/T0TaEjprMpwn16BA0NQ==",
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
}
|
||||
|
|
@ -9540,9 +9540,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/katex": {
|
||||
"version": "0.16.18",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.18.tgz",
|
||||
"integrity": "sha512-LRuk0rPdXrecAFwQucYjMiIs0JFefk6N1q/04mlw14aVIVgxq1FO0MA9RiIIGVaKOB5GIP5GH4aBBNraZERmaQ==",
|
||||
"version": "0.16.19",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.19.tgz",
|
||||
"integrity": "sha512-3IA6DYVhxhBabjSLTNO9S4+OliA3Qvb8pBQXMfC4WxXJgLwZgnfDl0BmB4z6nBMdznBsZ+CGM8DrGZ5hcguDZg==",
|
||||
"funding": [
|
||||
"https://opencollective.com/katex",
|
||||
"https://github.com/sponsors/katex"
|
||||
|
|
@ -11478,14 +11478,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/motion-dom": {
|
||||
"version": "11.14.3",
|
||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.14.3.tgz",
|
||||
"integrity": "sha512-lW+D2wBy5vxLJi6aCP0xyxTxlTfiu+b+zcpVbGVFUxotwThqhdpPRSmX8xztAgtZMPMeU0WGVn/k1w4I+TbPqA=="
|
||||
"version": "11.16.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.16.0.tgz",
|
||||
"integrity": "sha512-4bmEwajSdrljzDAYpu6ceEdtI4J5PH25fmN8YSx7Qxk6OMrC10CXM0D5y+VO/pFZjhmCvm2bGf7Rus482kwhzA==",
|
||||
"dependencies": {
|
||||
"motion-utils": "^11.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-utils": {
|
||||
"version": "11.14.3",
|
||||
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.14.3.tgz",
|
||||
"integrity": "sha512-Xg+8xnqIJTpr0L/cidfTTBFkvRw26ZtGGuIhA94J9PQ2p4mEa06Xx7QVYZH0BP+EpMSaDlu+q0I0mmvwADPsaQ=="
|
||||
"version": "11.16.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.16.0.tgz",
|
||||
"integrity": "sha512-ngdWPjg31rD4WGXFi0eZ00DQQqKKu04QExyv/ymlC+3k+WIgYVFbt6gS5JsFPbJODTF/r8XiE/X+SsoT9c0ocw=="
|
||||
},
|
||||
"node_modules/mri": {
|
||||
"version": "1.2.0",
|
||||
|
|
@ -12210,9 +12213,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss-load-config/node_modules/yaml": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz",
|
||||
"integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==",
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
|
||||
"integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
|
|
@ -13603,9 +13606,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz",
|
||||
"integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==",
|
||||
"version": "4.30.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.0.tgz",
|
||||
"integrity": "sha512-sDnr1pcjTgUT69qBksNF1N1anwfbyYG6TBQ22b03bII8EdiUQ7J0TlozVaTMjT/eEJAO49e1ndV7t+UZfL1+vA==",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.6"
|
||||
},
|
||||
|
|
@ -13617,25 +13620,25 @@
|
|||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.29.1",
|
||||
"@rollup/rollup-android-arm64": "4.29.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.29.1",
|
||||
"@rollup/rollup-darwin-x64": "4.29.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.29.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.29.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.29.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.29.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.29.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.29.1",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.29.1",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.29.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.29.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.29.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.29.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.29.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.29.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.29.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.29.1",
|
||||
"@rollup/rollup-android-arm-eabi": "4.30.0",
|
||||
"@rollup/rollup-android-arm64": "4.30.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.30.0",
|
||||
"@rollup/rollup-darwin-x64": "4.30.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.30.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.30.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.30.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.30.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.30.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.30.0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.30.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.30.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.30.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.30.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.30.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.30.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.30.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.30.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.30.0",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
import { ParameterRenderComponent } from "@/components/core/parameterRenderComponent";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { getCustomParameterTitle } from "@/customization/components/custom-parameter";
|
||||
import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value";
|
||||
import useFlowStore from "@/stores/flowStore";
|
||||
import { InputFieldType } from "@/types/api";
|
||||
import { cloneDeep } from "lodash";
|
||||
|
||||
export const NodeDialog = ({
|
||||
open,
|
||||
onClose,
|
||||
dialogInputs,
|
||||
nodeId,
|
||||
}: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
dialogInputs: any;
|
||||
nodeId: string;
|
||||
}) => {
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const setNode = useFlowStore((state) => state.setNode);
|
||||
|
||||
const handleNewValue = (value: string, key: string) => {
|
||||
let rawValue = value;
|
||||
|
||||
if (typeof value === "object" && value) {
|
||||
rawValue = (value as { value: string }).value;
|
||||
}
|
||||
|
||||
const template = cloneDeep(dialogInputs?.fields?.data?.node?.template);
|
||||
template[key].value = value;
|
||||
|
||||
const newNode = cloneDeep(nodes.find((node) => node.id === nodeId));
|
||||
if (newNode) {
|
||||
const template = newNode.data.node.template;
|
||||
const databaseFields = template.database_name.dialog_inputs.fields;
|
||||
const nodeTemplate = databaseFields.data.node.template;
|
||||
|
||||
nodeTemplate[key].value = rawValue;
|
||||
}
|
||||
setNode(nodeId, newNode!);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onClose}>
|
||||
<DialogContent className="max-w-[700px] gap-2 px-1 py-6">
|
||||
<DialogHeader className="px-5 pb-3">
|
||||
<DialogTitle>
|
||||
<div className="flex items-center">
|
||||
<span className="pb-2">
|
||||
{dialogInputs.fields?.data?.node?.display_name}
|
||||
</span>
|
||||
</div>
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
<div className="flex items-center gap-2">
|
||||
{dialogInputs.fields?.data?.node?.description}
|
||||
</div>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex flex-col gap-5 overflow-y-auto px-5">
|
||||
{Object.entries(dialogInputs?.fields?.data?.node?.template ?? {}).map(
|
||||
([key, value]) => (
|
||||
<div key={key}>
|
||||
<div>
|
||||
{getCustomParameterTitle({
|
||||
title:
|
||||
dialogInputs?.fields?.data?.node?.template[key]
|
||||
.display_name ?? "",
|
||||
nodeId,
|
||||
isFlexView: false,
|
||||
})}
|
||||
</div>
|
||||
<ParameterRenderComponent
|
||||
handleOnNewValue={(value: string) =>
|
||||
handleNewValue(value, key)
|
||||
}
|
||||
name={key}
|
||||
nodeId={nodeId}
|
||||
templateData={value as Partial<InputFieldType>}
|
||||
templateValue={
|
||||
dialogInputs?.fields?.data?.node?.template[key].value
|
||||
}
|
||||
editNode={false}
|
||||
handleNodeClass={() => {}}
|
||||
nodeClass={dialogInputs.fields?.data?.node}
|
||||
disabled={false}
|
||||
placeholder=""
|
||||
isToolMode={false}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
|
||||
<DialogFooter className="px-5 pt-3">
|
||||
<Button variant="outline" onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button>{dialogInputs.functionality}</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default NodeDialog;
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
|
||||
import NodeDialog from "@/CustomNodes/GenericNode/components/NodeDialogComponent";
|
||||
import { mutateTemplate } from "@/CustomNodes/helpers/mutate-template";
|
||||
import useAlertStore from "@/stores/alertStore";
|
||||
import { PopoverAnchor } from "@radix-ui/react-popover";
|
||||
import Fuse from "fuse.js";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { ChangeEvent, useEffect, useRef, useState } from "react";
|
||||
import { DropDownComponent } from "../../../types/components";
|
||||
import { cn, formatPlaceholderName } from "../../../utils/utils";
|
||||
import { cn, formatName, formatPlaceholderName } from "../../../utils/utils";
|
||||
import { default as ForwardedIconComponent } from "../../common/genericIconComponent";
|
||||
import ShadTooltip from "../../common/shadTooltipComponent";
|
||||
import { Button } from "../../ui/button";
|
||||
|
|
@ -13,6 +17,7 @@ import {
|
|||
CommandGroup,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
} from "../../ui/command";
|
||||
import {
|
||||
Popover,
|
||||
|
|
@ -20,24 +25,32 @@ import {
|
|||
PopoverContentWithoutPortal,
|
||||
PopoverTrigger,
|
||||
} from "../../ui/popover";
|
||||
import { BaseInputProps } from "../parameterRenderComponent/types";
|
||||
|
||||
export default function Dropdown({
|
||||
disabled,
|
||||
isLoading,
|
||||
value,
|
||||
options,
|
||||
optionsMetaData,
|
||||
combobox,
|
||||
onSelect,
|
||||
editNode = false,
|
||||
id = "",
|
||||
children,
|
||||
name,
|
||||
}: DropDownComponent): JSX.Element {
|
||||
dialogInputs,
|
||||
...baseInputProps
|
||||
}: BaseInputProps & DropDownComponent): JSX.Element {
|
||||
const nodeId = baseInputProps?.nodeId;
|
||||
|
||||
const placeholderName = name
|
||||
? formatPlaceholderName(name)
|
||||
: "Choose an option...";
|
||||
|
||||
const { firstWord } = formatName(name);
|
||||
const [open, setOpen] = useState(children ? true : false);
|
||||
const [openDialog, setOpenDialog] = useState(false);
|
||||
|
||||
const refButton = useRef<HTMLButtonElement>(null);
|
||||
|
||||
|
|
@ -58,6 +71,28 @@ export default function Dropdown({
|
|||
setCustomValue(value);
|
||||
};
|
||||
|
||||
const { nodeClass, handleNodeClass } = baseInputProps;
|
||||
|
||||
const postTemplateValue = usePostTemplateValue({
|
||||
parameterId: name || "",
|
||||
nodeId: id,
|
||||
node: nodeClass!,
|
||||
});
|
||||
|
||||
const { isPending } = postTemplateValue;
|
||||
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
|
||||
const handleRefreshButtonPress = () => {
|
||||
mutateTemplate(
|
||||
value,
|
||||
nodeClass!,
|
||||
handleNodeClass,
|
||||
postTemplateValue,
|
||||
setErrorData,
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (disabled && value !== "") {
|
||||
onSelect("", undefined, true);
|
||||
|
|
@ -77,7 +112,12 @@ export default function Dropdown({
|
|||
const renderTriggerButton = () => (
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
disabled={disabled}
|
||||
disabled={
|
||||
disabled ||
|
||||
(Object.keys(options).length === 0 &&
|
||||
!combobox &&
|
||||
!dialogInputs?.fields?.data?.node?.template)
|
||||
}
|
||||
variant="primary"
|
||||
size="xs"
|
||||
role="combobox"
|
||||
|
|
@ -91,7 +131,22 @@ export default function Dropdown({
|
|||
"w-full justify-between font-normal",
|
||||
)}
|
||||
>
|
||||
<span className="truncate" data-testid={`value-dropdown-${id}`}>
|
||||
<span
|
||||
className="flex items-center gap-2 truncate"
|
||||
data-testid={`value-dropdown-${id}`}
|
||||
>
|
||||
{optionsMetaData?.[
|
||||
filteredOptions.findIndex((option) => option === value)
|
||||
]?.icon && (
|
||||
<ForwardedIconComponent
|
||||
name={
|
||||
optionsMetaData[
|
||||
filteredOptions.findIndex((option) => option === value)
|
||||
].icon
|
||||
}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
)}
|
||||
{value &&
|
||||
value !== "" &&
|
||||
filteredOptions.find((option) => option === value)
|
||||
|
|
@ -126,36 +181,132 @@ export default function Dropdown({
|
|||
</div>
|
||||
);
|
||||
|
||||
const renderCustomOptionDialog = () => (
|
||||
<CommandGroup className="flex flex-col">
|
||||
<CommandItem className="flex cursor-pointer items-center justify-start gap-2 truncate py-3 text-xs font-semibold text-muted-foreground">
|
||||
<Button
|
||||
className="w-full"
|
||||
unstyled
|
||||
onClick={() => {
|
||||
setOpenDialog(true);
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2 pl-1">
|
||||
<ForwardedIconComponent
|
||||
name="Plus"
|
||||
className="h-3 w-3 text-primary"
|
||||
/>
|
||||
{`New ${firstWord}`}
|
||||
</div>
|
||||
</Button>
|
||||
</CommandItem>
|
||||
<CommandItem className="flex cursor-pointer items-center justify-start gap-2 truncate py-3 text-xs font-semibold text-muted-foreground">
|
||||
<Button
|
||||
className="w-full"
|
||||
unstyled
|
||||
onClick={() => {
|
||||
handleRefreshButtonPress();
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2 pl-1">
|
||||
<ForwardedIconComponent
|
||||
name="RefreshCcw"
|
||||
className={cn(
|
||||
"h-3 w-3 text-primary",
|
||||
isPending && "animate-spin",
|
||||
)}
|
||||
/>
|
||||
Refresh list
|
||||
</div>
|
||||
</Button>
|
||||
</CommandItem>
|
||||
<NodeDialog
|
||||
open={openDialog}
|
||||
dialogInputs={dialogInputs}
|
||||
onClose={() => setOpenDialog(false)}
|
||||
nodeId={nodeId!}
|
||||
/>
|
||||
</CommandGroup>
|
||||
);
|
||||
|
||||
const renderOptionsList = () => (
|
||||
<CommandList>
|
||||
<CommandEmpty>No values found.</CommandEmpty>
|
||||
<CommandGroup defaultChecked={false}>
|
||||
{filteredOptions?.map((option, index) => (
|
||||
<div>
|
||||
<CommandItem
|
||||
value={option}
|
||||
onSelect={(currentValue) => {
|
||||
onSelect(currentValue);
|
||||
setOpen(false);
|
||||
}}
|
||||
className="items-center overflow-hidden truncate hover:cursor-pointer"
|
||||
data-testid={`${option}-${index}-option`}
|
||||
>
|
||||
{customValue === option && (
|
||||
<span className="text-muted-foreground">Text: </span>
|
||||
)}
|
||||
<span className="truncate">{option}</span>
|
||||
<ForwardedIconComponent
|
||||
name="Check"
|
||||
className={cn(
|
||||
"ml-auto h-4 w-4 shrink-0 text-primary",
|
||||
value === option ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
</CommandItem>
|
||||
</div>
|
||||
<ShadTooltip key={index} delayDuration={700} content={option}>
|
||||
<div>
|
||||
<CommandItem
|
||||
value={option}
|
||||
onSelect={(currentValue) => {
|
||||
onSelect(currentValue);
|
||||
setOpen(false);
|
||||
}}
|
||||
className="items-center"
|
||||
data-testid={`${option}-${index}-option`}
|
||||
>
|
||||
<div className="flex w-full items-center gap-2">
|
||||
{optionsMetaData?.[index]?.icon ? (
|
||||
<ForwardedIconComponent
|
||||
name={optionsMetaData?.[index]?.icon}
|
||||
className="h-4 w-4 shrink-0 text-primary"
|
||||
/>
|
||||
) : null}
|
||||
<div
|
||||
className={cn("flex truncate", {
|
||||
"flex-col":
|
||||
optionsMetaData && optionsMetaData?.length > 0,
|
||||
"w-full pl-2": !optionsMetaData?.[index]?.icon,
|
||||
})}
|
||||
>
|
||||
<div className="flex truncate">{option}</div>
|
||||
{optionsMetaData && optionsMetaData?.length > 0 ? (
|
||||
<div className="flex w-full items-center text-muted-foreground">
|
||||
{Object.entries(optionsMetaData?.[index] || {})
|
||||
.filter(
|
||||
([key, value]) => value !== null && key !== "icon",
|
||||
)
|
||||
.map(([key, value], i, arr) => (
|
||||
<div
|
||||
key={key}
|
||||
className={cn("flex items-center", {
|
||||
truncate: i === arr.length - 1,
|
||||
})}
|
||||
>
|
||||
{i > 0 && (
|
||||
<ForwardedIconComponent
|
||||
name="Circle"
|
||||
className="mx-1 h-1 w-1 overflow-visible fill-muted-foreground"
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={cn("text-xs", {
|
||||
truncate: i === arr.length - 1,
|
||||
})}
|
||||
>{`${String(value)} ${key}`}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="ml-auto flex">
|
||||
<ForwardedIconComponent
|
||||
name="Check"
|
||||
className={cn(
|
||||
"h-4 w-4 shrink-0 text-primary",
|
||||
value === option ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CommandItem>
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
))}
|
||||
</CommandGroup>
|
||||
<CommandSeparator />
|
||||
{dialogInputs && dialogInputs?.fields && renderCustomOptionDialog()}
|
||||
</CommandList>
|
||||
);
|
||||
|
||||
|
|
@ -175,17 +326,11 @@ export default function Dropdown({
|
|||
</PopoverContentDropdown>
|
||||
);
|
||||
|
||||
if (Object.keys(options).length === 0 && !combobox) {
|
||||
return isLoading ? (
|
||||
if (Object.keys(options).length === 0 && !combobox && isLoading) {
|
||||
return (
|
||||
<div>
|
||||
<span className="text-sm italic">Loading...</span>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<span className="text-sm italic">
|
||||
No parameters are available for display.
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,20 +10,28 @@ export default function DropdownComponent({
|
|||
combobox,
|
||||
options,
|
||||
name,
|
||||
dialogInputs,
|
||||
optionsMetaData,
|
||||
...baseInputProps
|
||||
}: InputProps<string, DropDownComponentType>) {
|
||||
const onChange = (value: any, dbValue?: boolean, skipSnapshot?: boolean) => {
|
||||
handleOnNewValue({ value, load_from_db: dbValue }, { skipSnapshot });
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
options={options}
|
||||
optionsMetaData={optionsMetaData}
|
||||
onSelect={onChange}
|
||||
combobox={combobox}
|
||||
value={value || ""}
|
||||
id={`dropdown_${id}`}
|
||||
name={name}
|
||||
dialogInputs={dialogInputs}
|
||||
handleOnNewValue={handleOnNewValue} // TODO: Remove this
|
||||
{...baseInputProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,8 +177,6 @@ const CustomInputPopover = ({
|
|||
const [isFocused, setIsFocused] = useState(false);
|
||||
const memoizedOptions = useMemo(() => new Set<string>(options), [options]);
|
||||
|
||||
console.log(nodeStyle);
|
||||
|
||||
const PopoverContentInput = editNode
|
||||
? PopoverContent
|
||||
: PopoverContentWithoutPortal;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ export function RefreshParameterComponent({
|
|||
const isFlexView = FLEX_VIEW_TYPES.includes(templateData.type ?? "");
|
||||
|
||||
return (
|
||||
(children || templateData.refresh_button) && (
|
||||
(children ||
|
||||
(templateData.refresh_button && !templateData.dialog_inputs)) && (
|
||||
<div
|
||||
className={cn(
|
||||
"flex w-full items-center justify-center gap-3",
|
||||
|
|
@ -53,18 +54,19 @@ export function RefreshParameterComponent({
|
|||
)}
|
||||
>
|
||||
{children}
|
||||
{templateData.refresh_button && (
|
||||
<div className="shrink-0 flex-col">
|
||||
<RefreshButton
|
||||
isLoading={postTemplateValue.isPending}
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
button_text={templateData.refresh_button_text}
|
||||
handleUpdateValues={handleRefreshButtonPress}
|
||||
id={"refresh-button-" + name}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{templateData.refresh_button &&
|
||||
!templateData.dialog_inputs?.fields?.data?.node?.template && (
|
||||
<div className="shrink-0 flex-col">
|
||||
<RefreshButton
|
||||
isLoading={postTemplateValue.isPending}
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
button_text={templateData.refresh_button_text}
|
||||
handleUpdateValues={handleRefreshButtonPress}
|
||||
id={"refresh-button-" + name}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ export function StrRenderComponent({
|
|||
return (
|
||||
<DropdownComponent
|
||||
{...baseInputProps}
|
||||
dialogInputs={templateData.dialog_inputs}
|
||||
options={templateData.options}
|
||||
optionsMetaData={templateData.options_metadata}
|
||||
combobox={templateData.combobox}
|
||||
name={templateData?.name!}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ export function ParameterRenderComponent({
|
|||
placeholder,
|
||||
isToolMode,
|
||||
}: {
|
||||
handleOnNewValue: handleOnNewValueType;
|
||||
handleOnNewValue:
|
||||
| handleOnNewValueType
|
||||
| ((value: string, key: string) => void);
|
||||
name: string;
|
||||
nodeId: string;
|
||||
templateData: Partial<InputFieldType>;
|
||||
|
|
@ -57,13 +59,14 @@ export function ParameterRenderComponent({
|
|||
id,
|
||||
value: templateValue,
|
||||
editNode,
|
||||
handleOnNewValue,
|
||||
handleOnNewValue: handleOnNewValue as handleOnNewValueType,
|
||||
disabled,
|
||||
nodeClass,
|
||||
handleNodeClass,
|
||||
readonly: templateData.readonly,
|
||||
placeholder,
|
||||
isToolMode,
|
||||
nodeId,
|
||||
};
|
||||
|
||||
if (TEXT_FIELD_TYPES.includes(templateData.type ?? "")) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export type BaseInputProps<valueType = any> = {
|
|||
placeholder?: string;
|
||||
isToolMode?: boolean;
|
||||
metadata?: any;
|
||||
nodeId?: string;
|
||||
};
|
||||
|
||||
// Generic type for composing input props
|
||||
|
|
@ -81,6 +82,8 @@ export type DropDownComponentType = {
|
|||
combobox?: boolean;
|
||||
options: string[];
|
||||
name: string;
|
||||
dialogInputs?: any;
|
||||
optionsMetaData?: any[];
|
||||
};
|
||||
|
||||
export type TextAreaComponentType = {
|
||||
|
|
|
|||
|
|
@ -54,11 +54,13 @@ export type DropDownComponent = {
|
|||
value: string;
|
||||
combobox?: boolean;
|
||||
options: string[];
|
||||
optionsMetaData?: any[];
|
||||
onSelect: (value: string, dbValue?: boolean, snapshot?: boolean) => void;
|
||||
editNode?: boolean;
|
||||
id?: string;
|
||||
children?: ReactNode;
|
||||
name?: string;
|
||||
dialogInputs?: any;
|
||||
};
|
||||
export type ParameterComponentType = {
|
||||
selected?: boolean;
|
||||
|
|
|
|||
|
|
@ -728,6 +728,19 @@ export const formatPlaceholderName = (name) => {
|
|||
return `Select ${prefix} ${formattedName}`;
|
||||
};
|
||||
|
||||
export const formatName = (name) => {
|
||||
const formattedName = name
|
||||
.split("_")
|
||||
.map((word: string) => word.toLowerCase())
|
||||
.join(" ");
|
||||
|
||||
const firstWord =
|
||||
formattedName.split(" ")[0].charAt(0).toUpperCase() +
|
||||
formattedName.split(" ")[0].slice(1);
|
||||
|
||||
return { formattedName, firstWord };
|
||||
};
|
||||
|
||||
export const isStringArray = (value: unknown): value is string[] => {
|
||||
return (
|
||||
Array.isArray(value) && value.every((item) => typeof item === "string")
|
||||
|
|
|
|||
6
uv.lock
generated
6
uv.lock
generated
|
|
@ -6629,12 +6629,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/39/1b/d0b013bf7d1af7cf0a6a4fce13f5fe5813ab225313755367b36e714a63f8/pycryptodome-3.21.0-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:18caa8cfbc676eaaf28613637a89980ad2fd96e00c564135bf90bc3f0b34dd93", size = 2254397 },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/71/4cbd3870d3e926c34706f705d6793159ac49d9a213e3ababcdade5864663/pycryptodome-3.21.0-cp36-abi3-win32.whl", hash = "sha256:280b67d20e33bb63171d55b1067f61fbd932e0b1ad976b3a184303a3dad22764", size = 1775641 },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/1d/81d59d228381576b92ecede5cd7239762c14001a828bdba30d64896e9778/pycryptodome-3.21.0-cp36-abi3-win_amd64.whl", hash = "sha256:b7aa25fc0baa5b1d95b7633af4f5f1838467f1815442b22487426f94e0d66c53", size = 1812863 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/b3/09ff7072e6d96c9939c24cf51d3c389d7c345bf675420355c22402f71b68/pycryptodome-3.21.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:2cb635b67011bc147c257e61ce864879ffe6d03342dc74b6045059dfbdedafca", size = 1691593 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/91/38e43628148f68ba9b68dedbc323cf409e537fd11264031961fd7c744034/pycryptodome-3.21.0-pp27-pypy_73-win32.whl", hash = "sha256:4c26a2f0dc15f81ea3afa3b0c87b87e501f235d332b7f27e2225ecb80c0b1cdd", size = 1765997 },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/16/ae464d4ac338c1dd41f89c41f9488e54f7d2a3acf93bb920bb193b99f8e3/pycryptodome-3.21.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d5ebe0763c982f069d3877832254f64974139f4f9655058452603ff559c482e8", size = 1615855 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/8c/b0cee957eee1950ce7655006b26a8894cee1dc4b8747ae913684352786eb/pycryptodome-3.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee86cbde706be13f2dec5a42b52b1c1d1cbb90c8e405c68d0755134735c8dc6", size = 1650018 },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/4d/d7138068089b99f6b0368622e60f97a577c936d75f533552a82613060c58/pycryptodome-3.21.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fd54003ec3ce4e0f16c484a10bc5d8b9bd77fa662a12b85779a2d2d85d67ee0", size = 1687977 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/02/90ae1ac9f28be4df0ed88c127bf4acc1b102b40053e172759d4d1c54d937/pycryptodome-3.21.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5dfafca172933506773482b0e18f0cd766fd3920bd03ec85a283df90d8a17bc6", size = 1788273 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue