From 675f9cb1a8d122be794e064286ee4b259fad320f Mon Sep 17 00:00:00 2001 From: David Whittaker Date: Mon, 19 May 2025 11:42:24 -0700 Subject: [PATCH] fixes plugin configuration not loading --- src/dispatch/individual/models.py | 25 ++++++++++++++++--- src/dispatch/plugin/models.py | 17 +++++++------ .../static/dispatch/src/plugin/store.js | 9 +++++++ 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/dispatch/individual/models.py b/src/dispatch/individual/models.py index 61be564e5643..979301b946f7 100644 --- a/src/dispatch/individual/models.py +++ b/src/dispatch/individual/models.py @@ -4,7 +4,15 @@ from pydantic import field_validator, Field, ConfigDict from urllib.parse import urlparse -from sqlalchemy import Column, ForeignKey, Integer, PrimaryKeyConstraint, String, Table, UniqueConstraint +from sqlalchemy import ( + Column, + ForeignKey, + Integer, + PrimaryKeyConstraint, + String, + Table, + UniqueConstraint, +) from sqlalchemy.orm import relationship from sqlalchemy_utils import TSVectorType @@ -25,7 +33,9 @@ assoc_individual_contact_filters = Table( "assoc_individual_contact_filters", Base.metadata, - Column("individual_contact_id", Integer, ForeignKey("individual_contact.id", ondelete="CASCADE")), + Column( + "individual_contact_id", Integer, ForeignKey("individual_contact.id", ondelete="CASCADE") + ), Column("search_filter_id", Integer, ForeignKey("search_filter.id", ondelete="CASCADE")), PrimaryKeyConstraint("individual_contact_id", "search_filter_id"), ) @@ -33,6 +43,7 @@ class IndividualContact(Base, ContactMixin, ProjectMixin, TimeStampMixin): """SQLAlchemy model for individual contact resources.""" + __table_args__ = (UniqueConstraint("email", "project_id"),) id = Column(Integer, primary_key=True) @@ -66,6 +77,7 @@ class IndividualContact(Base, ContactMixin, ProjectMixin, TimeStampMixin): class IndividualContactBase(ContactBase): """Base Pydantic model for individual contact resources.""" + mobile_phone: str | None = Field(default=None) office_phone: str | None = Field(default=None) title: str | None = Field(default=None) @@ -86,19 +98,22 @@ def weblink_validator(cls, v: str | None) -> str | None: class IndividualContactCreate(IndividualContactBase): """Pydantic model for creating an individual contact resource.""" + filters: list[SearchFilterRead] | None = None project: ProjectRead class IndividualContactUpdate(IndividualContactBase): """Pydantic model for updating an individual contact resource.""" + filters: list[SearchFilterRead] | None = None project: ProjectRead | None = None class IndividualContactRead(IndividualContactBase): """Pydantic model for reading an individual contact resource.""" - id: PrimaryKey + + id: PrimaryKey | None = None filters: list[SearchFilterRead] = [] created_at: datetime | None = None updated_at: datetime | None = None @@ -107,6 +122,7 @@ class IndividualContactRead(IndividualContactBase): # Creating a more minimal version that doesn't inherit from ContactBase to avoid email validation issues in tests class IndividualContactReadMinimal(DispatchBase): """Pydantic model for reading a minimal individual contact resource.""" + id: PrimaryKey created_at: datetime | None = None updated_at: datetime | None = None @@ -130,11 +146,12 @@ class IndividualContactReadMinimal(DispatchBase): extra="ignore", validate_default=False, validate_assignment=False, - arbitrary_types_allowed=True + arbitrary_types_allowed=True, ) class IndividualContactPagination(Pagination): """Pydantic model for paginated individual contact results.""" + total: int items: list[IndividualContactRead] = [] diff --git a/src/dispatch/plugin/models.py b/src/dispatch/plugin/models.py index 4ba88d733077..1be6585a0e82 100644 --- a/src/dispatch/plugin/models.py +++ b/src/dispatch/plugin/models.py @@ -1,4 +1,5 @@ import logging +import json from pydantic import SecretStr from pydantic.json import pydantic_encoder @@ -150,7 +151,9 @@ def configuration(self, configuration): if configuration: plugin = plugins.get(self.plugin.slug) config_object = plugin.configuration_schema.parse_obj(configuration) - self._configuration = config_object.json(encoder=show_secrets_encoder) + self._configuration = json.dumps( + config_object.model_dump(), default=show_secrets_encoder + ) # Pydantic models... @@ -166,7 +169,7 @@ class PluginRead(PluginBase): author_url: str type: str multiple: bool - configuration_schema: Any + configuration_schema: Any | None = None description: str | None = None @@ -192,8 +195,8 @@ class PluginEventPagination(Pagination): class PluginInstanceRead(PluginBase): id: PrimaryKey enabled: bool | None = None - configuration: dict | None = None - configuration_schema: Any + configuration: Any | None = None + configuration_schema: Any | None = None plugin: PluginRead project: ProjectRead | None = None broken: bool | None = None @@ -202,7 +205,7 @@ class PluginInstanceRead(PluginBase): class PluginInstanceReadMinimal(PluginBase): id: PrimaryKey enabled: bool | None = None - configuration_schema: Any + configuration_schema: Any | None = None plugin: PluginRead project: ProjectRead | None = None broken: bool | None = None @@ -210,7 +213,7 @@ class PluginInstanceReadMinimal(PluginBase): class PluginInstanceCreate(PluginBase): enabled: bool | None = None - configuration: dict | None = None + configuration: Any | None = None plugin: PluginRead project: ProjectRead @@ -218,7 +221,7 @@ class PluginInstanceCreate(PluginBase): class PluginInstanceUpdate(PluginBase): id: PrimaryKey = None enabled: bool | None = None - configuration: dict | None = None + configuration: Any | None = None class KeyValue(DispatchBase): diff --git a/src/dispatch/static/dispatch/src/plugin/store.js b/src/dispatch/static/dispatch/src/plugin/store.js index d18360600f82..6dfbbf20ecbd 100644 --- a/src/dispatch/static/dispatch/src/plugin/store.js +++ b/src/dispatch/static/dispatch/src/plugin/store.js @@ -165,6 +165,15 @@ function convertToFormkit(json_schema) { formkit_schema.push(title) for (const [key, value] of Object.entries(json_schema.properties)) { var obj = {} + + // Check for anyOf and look for the object with the format parameter + if (value.anyOf) { + const formatObj = value.anyOf.find((v) => v.format) + if (formatObj) { + value.type = formatObj.type + value.format = formatObj.format + } + } if (value.type == "string" || value.type == "password") { obj = { $formkit: "text",