Skip to content

Commit

Permalink
tests passing!
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin committed Dec 11, 2023
1 parent a62235e commit c7e0ad7
Show file tree
Hide file tree
Showing 15 changed files with 232 additions and 139 deletions.
12 changes: 9 additions & 3 deletions src/npm-fastui/src/components/FormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import Select, { StylesConfig } from 'react-select'
import { ClassName, useClassName } from '../hooks/className'
import { debounce, useRequest } from '../tools'

type PrivateOnChange = () => void

interface BaseFormFieldProps {
name: string
title: string[]
title: string | string[]
required: boolean
locked: boolean
error?: string
description?: string
displayMode?: 'default' | 'inline'
className?: ClassName
onChange?: () => void
onChange?: PrivateOnChange
}

export type FormFieldProps =
Expand Down Expand Up @@ -239,6 +241,7 @@ function findDefault(options: SelectOptions, value?: string): SelectOption | und
interface FormFieldSelectSearchProps extends BaseFormFieldProps {
type: 'FormFieldSelectSearch'
searchUrl: string
/** @TJS-type integer */
debounce?: number
initial?: SelectOption
multiple?: boolean
Expand Down Expand Up @@ -302,7 +305,10 @@ export const FormFieldSelectSearchComp: FC<FormFieldSelectSearchProps> = (props)
}

const Label: FC<FormFieldProps> = (props) => {
const { title } = props
let { title } = props
if (!Array.isArray(title)) {
title = [title]
}
return (
<label htmlFor={inputId(props)} className={useClassName(props, { el: 'label' })}>
{title.map((t, i) => (
Expand Down
7 changes: 7 additions & 0 deletions src/npm-fastui/src/components/Iframe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@ import { ClassName } from '../hooks/className'

export interface IframeProps {
type: 'Iframe'
/**
* @format uri
* @maxLength 2083
* @minLength 1
*/
src: string
/** @TJS-type ["string", "integer"] */
width?: string | number
/** @TJS-type ["string", "integer"] */
height?: string | number
title?: string
className?: ClassName
Expand Down
1 change: 1 addition & 0 deletions src/npm-fastui/src/components/display.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export enum DisplayMode {

export interface DisplayProps {
type: 'Display'
/** @TJS-type JSON */
value?: JsonData
mode?: DisplayMode
title?: string
Expand Down
1 change: 1 addition & 0 deletions src/npm-fastui/src/components/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { FormFieldProps } from './FormField'

interface BaseFormProps {
formFields: FormFieldProps[]
/** @TJS-type object */
initial?: Record<string, any>
submitUrl: string
footer?: boolean | FastProps[]
Expand Down
4 changes: 4 additions & 0 deletions src/npm-fastui/src/components/heading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { slugify } from '../tools'

export interface HeadingProps {
type: 'Heading'
/**
* @TJS-enum [1, 2, 3, 4, 5, 6]
* @TJS-type integer
*/
level: 1 | 2 | 3 | 4 | 5 | 6
htmlId?: string
className?: ClassName
Expand Down
2 changes: 2 additions & 0 deletions src/npm-fastui/src/components/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export interface ImageProps {
type: 'Image'
src: string
alt?: string
/** @TJS-type ["string", "integer"] */
width?: number | string
/** @TJS-type ["string", "integer"] */
height?: number | string
referrerPolicy?:
| 'no-referrer'
Expand Down
4 changes: 4 additions & 0 deletions src/npm-fastui/src/components/pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ import { LinkListComp } from './LinkList'

export interface PaginationProps {
type: 'Pagination'
/** @TJS-type integer */
page: number
/** @TJS-type integer */
pageSize: number
/** @TJS-type integer */
total: number
/** @TJS-type integer */
pageCount: number
className?: ClassName
}
Expand Down
69 changes: 32 additions & 37 deletions src/python-fastui/fastui/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class Link(pydantic.BaseModel, extra='forbid'):
components: '_t.List[AnyComponent]'
on_click: _t.Union[events.AnyEvent, None] = pydantic.Field(default=None, serialization_alias='onClick')
mode: _t.Union[_t.Literal['navbar', 'tabs', 'vertical', 'pagination'], None] = None
active: _t.Union[bool, str, None] = None
active: _t.Union[str, bool, None] = None
locked: _t.Union[bool, None] = None
class_name: _class_name.ClassName = None
type: _t.Literal['Link'] = 'Link'
Expand All @@ -154,7 +154,7 @@ class Modal(pydantic.BaseModel, extra='forbid'):
body: '_t.List[AnyComponent]'
footer: '_t.Union[_t.List[AnyComponent], None]' = None
open_trigger: _t.Union[events.PageEvent, None] = pydantic.Field(default=None, serialization_alias='openTrigger')
open_context: _t.Union[events.EventContext, None] = pydantic.Field(default=None, serialization_alias='openContext')
open_context: _t.Union[events.ContextType, None] = pydantic.Field(default=None, serialization_alias='openContext')
class_name: _class_name.ClassName = None
type: _t.Literal['Modal'] = 'Modal'

Expand All @@ -174,9 +174,9 @@ class ServerLoad(pydantic.BaseModel, extra='forbid'):
class Image(pydantic.BaseModel, extra='forbid'):
src: str
alt: _t.Union[str, None] = None
width: _t.Union[int, float, str, None] = None
height: _t.Union[int, float, str, None] = None
referrerpolicy: _t.Union[
width: _t.Union[str, int, None] = None
height: _t.Union[str, int, None] = None
referrer_policy: _t.Union[
_t.Literal[
'no-referrer',
'no-referrer-when-downgrade',
Expand All @@ -188,7 +188,7 @@ class Image(pydantic.BaseModel, extra='forbid'):
'unsafe-url',
],
None,
] = None
] = pydantic.Field(None, serialization_alias='referrerPolicy')
loading: _t.Union[_t.Literal['eager', 'lazy'], None] = None
on_click: _t.Union[events.AnyEvent, None] = pydantic.Field(default=None, serialization_alias='onClick')
class_name: _class_name.ClassName = None
Expand All @@ -200,37 +200,32 @@ class Iframe(pydantic.BaseModel, extra='forbid'):
title: _t.Union[str, None] = None
width: _t.Union[str, int, None] = None
height: _t.Union[str, int, None] = None
class_name: _class_name.ClassName = None
type: _t.Literal['Iframe'] = 'Iframe'


AnyComponent = _te.TypeAliasType(
'AnyComponent',
_te.Annotated[
_t.Union[
Text,
Paragraph,
PageTitle,
Div,
Page,
Heading,
Markdown,
Code,
Button,
Link,
LinkList,
Navbar,
Modal,
ServerLoad,
Table,
Pagination,
Display,
Details,
Form,
ModelForm,
Image,
Iframe,
FormField,
],
pydantic.Field(discriminator='type'),
],
)
AnyComponent = _t.Union[
Text,
Paragraph,
PageTitle,
Div,
Page,
Heading,
Markdown,
Code,
Button,
Link,
LinkList,
Navbar,
Modal,
ServerLoad,
Table,
Pagination,
Display,
Details,
Form,
ModelForm,
Image,
Iframe,
FormField,
]
8 changes: 2 additions & 6 deletions src/python-fastui/fastui/components/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@


class DisplayMode(str, enum.Enum):
"""
How to a value.
"""

auto = 'auto' # default, same as None below
plain = 'plain'
datetime = 'datetime'
Expand All @@ -30,6 +26,7 @@ class DisplayMode(str, enum.Enum):

class DisplayBase(pydantic.BaseModel, ABC, defer_build=True):
mode: _t.Union[DisplayMode, None] = None
title: _t.Union[str, None] = None
on_click: _t.Union[events.AnyEvent, None] = pydantic.Field(default=None, serialization_alias='onClick')


Expand All @@ -39,7 +36,6 @@ class DisplayLookup(DisplayBase, extra='forbid'):
"""

field: str
title: _t.Union[str, None] = None
# percentage width - 0 to 100, specific to tables
table_width_percent: _t.Union[_te.Annotated[int, _at.Interval(ge=0, le=100)], None] = pydantic.Field(
default=None, serialization_alias='tableWidthPercent'
Expand All @@ -51,7 +47,7 @@ class Display(DisplayBase, extra='forbid'):
Description of how to display a value, either in a table or detail view.
"""

value: _t.Any
value: _t.Any = pydantic.Field(json_schema_extra={'type': 'JSON'})
type: _t.Literal['Display'] = 'Display'


Expand Down
13 changes: 9 additions & 4 deletions src/python-fastui/fastui/components/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,27 @@
if _t.TYPE_CHECKING:
from . import AnyComponent

# # alphabetical order matches typescript-json-schema
# InputHtmlType = _t.Literal['date', 'datetime-local', 'email', 'number', 'password', 'text', 'time', 'url']
InputHtmlType = _t.Literal['text', 'date', 'datetime-local', 'time', 'email', 'url', 'number', 'password']


class BaseFormField(pydantic.BaseModel, ABC, defer_build=True):
name: str
title: _t.Union[str, _t.List[str]]
title: _t.Union[_t.List[str], str]
required: bool = False
error: _t.Union[str, None] = None
locked: bool = False
description: _t.Union[str, None] = None
display_mode: _t.Union[_t.Literal['default', 'inline'], None] = pydantic.Field(
default=None, serialization_alias='displayMode'
)
class_name: _class_name.ClassName = None


class FormFieldInput(BaseFormField):
html_type: InputHtmlType = pydantic.Field(default='text', serialization_alias='htmlType')
initial: _t.Union[str, int, float, None] = None
initial: _t.Union[str, float, None] = None
placeholder: _t.Union[str, None] = None
type: _t.Literal['FormFieldInput'] = 'FormFieldInput'

Expand All @@ -43,7 +48,7 @@ class FormFieldFile(BaseFormField):


class FormFieldSelect(BaseFormField):
options: _t.Union[_t.List[forms.SelectOption], _t.List[forms.SelectGroup]]
options: forms.SelectOptions
multiple: _t.Union[bool, None] = None
initial: _t.Union[str, None] = None
vanilla: _t.Union[bool, None] = None
Expand Down Expand Up @@ -72,7 +77,7 @@ class BaseForm(pydantic.BaseModel, ABC, defer_build=True, extra='forbid'):
default=None, serialization_alias='displayMode'
)
submit_on_change: _t.Union[bool, None] = pydantic.Field(default=None, serialization_alias='submitOnChange')
footer: '_t.Union[bool, _t.List[AnyComponent], None]' = None
footer: '_t.Union[_t.List[AnyComponent], bool, None]' = None
class_name: _class_name.ClassName = None

@pydantic.model_validator(mode='after')
Expand Down
2 changes: 1 addition & 1 deletion src/python-fastui/fastui/components/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def fill_columns(self) -> _te.Self:

class Pagination(pydantic.BaseModel):
page: int
page_size: int
page_size: int = pydantic.Field(serialization_alias='pageSize')
total: int
class_name: _class_name.ClassName = None
type: _t.Literal['Pagination'] = 'Pagination'
Expand Down
6 changes: 3 additions & 3 deletions src/python-fastui/fastui/events.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from typing import Dict, Literal, Union

from pydantic import BaseModel, Field
from typing_extensions import Annotated, TypeAlias
from typing_extensions import Annotated, TypeAliasType

EventContext: TypeAlias = Dict[str, Union[str, int]]
ContextType = TypeAliasType('ContextType', Dict[str, Union[str, int]])


class PageEvent(BaseModel):
name: str
push_path: Union[str, None] = Field(default=None, serialization_alias='pushPath')
context: Union[EventContext, None] = None
context: Union[ContextType, None] = None
clear: Union[bool, None] = None
type: Literal['page'] = 'page'

Expand Down
5 changes: 4 additions & 1 deletion src/python-fastui/fastui/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,11 @@ class SelectGroup(_te.TypedDict):
options: _t.List[SelectOption]


SelectOptions = _te.TypeAliasType('SelectOptions', _t.Union[_t.List[SelectOption], _t.List[SelectGroup]])


class SelectSearchResponse(pydantic.BaseModel):
options: _t.Union[_t.List[SelectOption], _t.List[SelectGroup]]
options: SelectOptions


NestedDict: _te.TypeAlias = 'dict[str | int, NestedDict | str | list[str] | ds.UploadFile | list[ds.UploadFile]]'
Expand Down
Loading

0 comments on commit c7e0ad7

Please sign in to comment.