diff --git a/.gitignore b/.gitignore
index b005cd56..1a8c145d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.pyc
.vscode/
+.idea/
.mypy_cache/
.DS_Store
node_modules/
diff --git a/admin_ui/src/components/FormAdd.vue b/admin_ui/src/components/FormAdd.vue
index f024a1ff..1cc5cffe 100644
--- a/admin_ui/src/components/FormAdd.vue
+++ b/admin_ui/src/components/FormAdd.vue
@@ -33,7 +33,7 @@
v-on:submit.prevent="submitForm($event)"
ref="form"
>
-
+
@@ -47,7 +47,7 @@ import axios from "axios"
import { defineComponent, type PropType } from "vue"
import NewForm from "./NewForm.vue"
-import type { APIResponseMessage, FormConfig, Schema } from "../interfaces"
+import type { APIResponseMessage, Enum, Choices, FormConfig, Schema } from "../interfaces"
import { convertFormValue, parseErrorResponse } from "@/utils"
import FormErrors from "./FormErrors.vue"
@@ -92,6 +92,14 @@ export default defineComponent({
}
},
methods: {
+ enumToChoices (data: Enum): Choices {
+ var choices: Choices = {}
+ for (let index = 0; index < data.enum.length; index++) {
+ const element = data.enum[index];
+ choices[element] = {display_name: element, value: element}
+ }
+ return choices
+ },
resetForm() {
this.successMessage = null
this.errors = []
diff --git a/admin_ui/src/components/NewForm.vue b/admin_ui/src/components/NewForm.vue
index d31a7703..3a8d423b 100644
--- a/admin_ui/src/components/NewForm.vue
+++ b/admin_ui/src/components/NewForm.vue
@@ -4,19 +4,37 @@
v-bind:key="property.title"
v-for="(property, columnName) in schema.properties"
>
-
-
+
+
+
+
+
+
+
+
@@ -26,11 +44,15 @@ import { defineComponent, type PropType } from "vue"
import InputField from "./InputField.vue"
import { type Schema, getType, getFormat, isNullable } from "@/interfaces"
+
export default defineComponent({
props: {
schema: {
type: Object as PropType,
required: true
+ },
+ etc: {
+ type: Function,
}
},
components: {
diff --git a/admin_ui/src/interfaces.ts b/admin_ui/src/interfaces.ts
index d3bf2c84..43d00aa1 100644
--- a/admin_ui/src/interfaces.ts
+++ b/admin_ui/src/interfaces.ts
@@ -114,12 +114,23 @@ export interface SchemaExtra {
time_resolution: { [key: string]: number }
}
+export interface Enum {
+ title: string
+ type: string
+ enum: string[]
+}
+
+export interface SchemaEnum {
+ [key: string]: Enum
+}
+
export interface Schema {
extra: SchemaExtra
properties: Properties
required: string[]
title: string
type: string
+ $defs: SchemaEnum
}
export interface Properties {
@@ -145,6 +156,7 @@ export interface Property {
anyOf?: AnyOf[]
format?: string
maxLength?: number
+ $ref: string | null
}
export interface ForeignKey {
diff --git a/docs/source/sidebar_links/examples/app.py b/docs/source/sidebar_links/examples/app.py
index e8e7ed39..72bef042 100644
--- a/docs/source/sidebar_links/examples/app.py
+++ b/docs/source/sidebar_links/examples/app.py
@@ -14,7 +14,7 @@
tables=[Director, Movie],
sidebar_links={
"Top Movies": "/admin/#/movie?__order=-box_office",
- "Google": "https://google.com"
+ "Google": "https://google.com",
},
),
),
diff --git a/e2e/test_forms.py b/e2e/test_forms.py
index 9af3cd92..b2121684 100644
--- a/e2e/test_forms.py
+++ b/e2e/test_forms.py
@@ -2,6 +2,7 @@
from piccolo_admin.example.forms.csv import FORM as CSV_FORM
from piccolo_admin.example.forms.image import FORM as IMAGE_FORM
+from piccolo_admin.example.forms.selections import FORM as SELECTION_FORM
from piccolo_admin.example.forms.nullable import FORM as NULLABLE_FORM
from .conftest import BASE_URL
@@ -57,6 +58,20 @@ def test_image_form(page: Page, dev_server):
download = download_info.value
assert download.suggested_filename == "movie_listings.jpg"
+def test_form_enum_support(page: Page, dev_server):
+ """
+ Make sure custom forms support the usage of Enum's.
+
+ form_page = FormPage(
+ page=page,
+ form_slug=SELECTION_FORM.slug,
+ )
+ form_page.reset()
+
+ page.locator('input[name="option"]').select_option("One")
+ form_page.submit_form()
+
+ assert f"You selected Options.ONE from the drop down." in page.content()
def test_nullable_form(page: Page, dev_server):
"""
diff --git a/piccolo_admin/example/forms/__init__.py b/piccolo_admin/example/forms/__init__.py
index 6cf310ae..204171a1 100644
--- a/piccolo_admin/example/forms/__init__.py
+++ b/piccolo_admin/example/forms/__init__.py
@@ -2,6 +2,7 @@
from .csv import FORM as CSV_FORM
from .email import FORM as EMAIL_FORM
from .image import FORM as IMAGE_FORM
+from .selections import FORM as SELECTION_FORM
from .nullable import FORM as MEGA_FORM
FORMS = [
@@ -9,5 +10,6 @@
CSV_FORM,
EMAIL_FORM,
IMAGE_FORM,
+ SELECTION_FORM,
MEGA_FORM,
]
diff --git a/piccolo_admin/example/forms/selections.py b/piccolo_admin/example/forms/selections.py
new file mode 100644
index 00000000..4d003651
--- /dev/null
+++ b/piccolo_admin/example/forms/selections.py
@@ -0,0 +1,33 @@
+from enum import Enum
+
+from pydantic import BaseModel
+from starlette.requests import Request
+
+from piccolo_admin.endpoints import FormConfig
+
+
+class Options(Enum):
+ ONE = "One"
+ TWO = "Two"
+ THREE = "Three"
+
+
+class SelectionModel(BaseModel):
+ option: Options = Options.ONE
+
+
+def selection(request: Request, data: SelectionModel):
+ """
+ A very simple example of a form which provides a selection drop down.
+ """
+ return (
+ f"You selected {data.option} from the drop down."
+ )
+
+
+FORM = FormConfig(
+ name="Selection",
+ pydantic_model=SelectionModel,
+ endpoint=selection,
+ description="Provides an example usage of drop downs within custom forms.",
+)