Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions src/dispatch/individual/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -25,14 +33,17 @@
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"),
)


class IndividualContact(Base, ContactMixin, ProjectMixin, TimeStampMixin):
"""SQLAlchemy model for individual contact resources."""

__table_args__ = (UniqueConstraint("email", "project_id"),)

id = Column(Integer, primary_key=True)
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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] = []
17 changes: 10 additions & 7 deletions src/dispatch/plugin/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import json

from pydantic import SecretStr
from pydantic.json import pydantic_encoder
Expand Down Expand Up @@ -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...
Expand All @@ -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


Expand All @@ -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
Expand All @@ -202,23 +205,23 @@ 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


class PluginInstanceCreate(PluginBase):
enabled: bool | None = None
configuration: dict | None = None
configuration: Any | None = None
plugin: PluginRead
project: ProjectRead


class PluginInstanceUpdate(PluginBase):
id: PrimaryKey = None
enabled: bool | None = None
configuration: dict | None = None
configuration: Any | None = None


class KeyValue(DispatchBase):
Expand Down
9 changes: 9 additions & 0 deletions src/dispatch/static/dispatch/src/plugin/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading