From 91cf3bc97e319ded22dc8f348e5344bb3941b314 Mon Sep 17 00:00:00 2001 From: Bedram Tamang Date: Thu, 28 May 2026 15:34:48 -0700 Subject: [PATCH] feat: update inertia-pingcrm-app example with docker-compose and app updates Co-Authored-By: Claude Sonnet 4.6 --- .../auth/authenticated_session_controller.py | 12 +- .../http/controllers/contacts_controller.py | 99 +++++++++------- .../http/controllers/dashboard_controller.py | 2 +- .../app/http/controllers/images_controller.py | 1 + .../controllers/organizations_controller.py | 78 +++++++------ .../http/controllers/profile_controller.py | 25 ++-- .../http/controllers/reports_controller.py | 2 +- .../app/http/controllers/users_controller.py | 110 ++++++++++-------- .../app/http/requests/contact.py | 2 +- .../app/http/requests/organization.py | 2 +- .../app/http/requests/profile.py | 2 +- .../inertia-pingcrm-app/app/models/Account.py | 1 + .../inertia-pingcrm-app/app/models/Contact.py | 1 + .../app/models/Organization.py | 1 + .../inertia-pingcrm-app/app/models/User.py | 1 + .../bootstrap/application.py | 3 +- .../inertia-pingcrm-app/config/database.py | 42 +++---- example/inertia-pingcrm-app/config/logging.py | 29 ++--- example/inertia-pingcrm-app/config/storage.py | 2 +- .../databases/factories/UserFactory.py | 10 +- .../databases/seeds/database_seeder.py | 30 ++--- .../inertia-pingcrm-app/docker-compose.yml | 27 +++++ .../providers/fastapi_provider.py | 20 +++- 23 files changed, 298 insertions(+), 204 deletions(-) create mode 100644 example/inertia-pingcrm-app/docker-compose.yml diff --git a/example/inertia-pingcrm-app/app/http/controllers/auth/authenticated_session_controller.py b/example/inertia-pingcrm-app/app/http/controllers/auth/authenticated_session_controller.py index 139498de..9085c611 100644 --- a/example/inertia-pingcrm-app/app/http/controllers/auth/authenticated_session_controller.py +++ b/example/inertia-pingcrm-app/app/http/controllers/auth/authenticated_session_controller.py @@ -3,8 +3,10 @@ from fastapi_startkit.inertia import Inertia from app.models.User import User + async def create(): - return Inertia.render('Auth/Login', {}) + return Inertia.render("Auth/Login", {}) + async def store(request: Request): form = await request.json() @@ -16,9 +18,11 @@ async def store(request: Request): request.session["user_id"] = user.id return RedirectResponse(url="/", status_code=303) - return Inertia.render('Auth/Login', { - 'errors': {'email': 'These credentials do not match our records.'} - }) + return Inertia.render( + "Auth/Login", + {"errors": {"email": "These credentials do not match our records."}}, + ) + async def destroy(request: Request): request.session.clear() diff --git a/example/inertia-pingcrm-app/app/http/controllers/contacts_controller.py b/example/inertia-pingcrm-app/app/http/controllers/contacts_controller.py index e63d9e5f..929467bb 100644 --- a/example/inertia-pingcrm-app/app/http/controllers/contacts_controller.py +++ b/example/inertia-pingcrm-app/app/http/controllers/contacts_controller.py @@ -1,7 +1,11 @@ from fastapi import Depends from fastapi.responses import RedirectResponse from fastapi_startkit.inertia import Inertia -from app.http.requests.contact import ContactListRequest, ContactStoreRequest, ContactUpdateRequest +from app.http.requests.contact import ( + ContactListRequest, + ContactStoreRequest, + ContactUpdateRequest, +) from app.models.Contact import Contact from app.models.Organization import Organization @@ -9,38 +13,46 @@ async def index(filters: ContactListRequest = Depends()): paginator = await ( Contact.query() - .when(filters.search, lambda q: q.where('first_name', 'like', f'%{filters.search}%').or_where('last_name', 'like', f'%{filters.search}%')) + .when( + filters.search, + lambda q: q.where("first_name", "like", f"%{filters.search}%").or_where( + "last_name", "like", f"%{filters.search}%" + ), + ) .paginate(page=filters.page, per_page=filters.limit) ) - return Inertia.render('Contacts/Index', { - 'data': [ - { - 'id': c.id, - 'name': f"{c.first_name} {c.last_name}", - 'organization_id': c.organization_id, - 'organization': None, - 'city': c.city, - 'phone': c.phone, - 'deleted_at': None, - } for c in paginator.result - ], - 'meta': { - 'current_page': paginator.current_page, - 'last_page': paginator.last_page, - 'per_page': paginator.per_page, - 'total': paginator.total, + return Inertia.render( + "Contacts/Index", + { + "data": [ + { + "id": c.id, + "name": f"{c.first_name} {c.last_name}", + "organization_id": c.organization_id, + "organization": None, + "city": c.city, + "phone": c.phone, + "deleted_at": None, + } + for c in paginator.result + ], + "meta": { + "current_page": paginator.current_page, + "last_page": paginator.last_page, + "per_page": paginator.per_page, + "total": paginator.total, + }, }, - }) + ) async def create(): organizations = await Organization.query().limit(100).get() - return Inertia.render('Contacts/Create', { - 'organizations': [ - {'id': o.id, 'name': o.name} for o in organizations - ] - }) + return Inertia.render( + "Contacts/Create", + {"organizations": [{"id": o.id, "name": o.name} for o in organizations]}, + ) async def store(form: ContactStoreRequest): @@ -51,25 +63,26 @@ async def store(form: ContactStoreRequest): async def edit(contact: str): c = await Contact.find(contact) organizations = await Organization.query().limit(100).get() - return Inertia.render('Contacts/Edit', { - 'contact': { - 'id': c.id, - 'first_name': c.first_name, - 'last_name': c.last_name, - 'organization_id': c.organization_id, - 'email': c.email, - 'phone': c.phone, - 'address': c.address, - 'city': c.city, - 'region': c.region, - 'country': c.country, - 'postal_code': c.postal_code, - 'deleted_at': None, + return Inertia.render( + "Contacts/Edit", + { + "contact": { + "id": c.id, + "first_name": c.first_name, + "last_name": c.last_name, + "organization_id": c.organization_id, + "email": c.email, + "phone": c.phone, + "address": c.address, + "city": c.city, + "region": c.region, + "country": c.country, + "postal_code": c.postal_code, + "deleted_at": None, + }, + "organizations": [{"id": o.id, "name": o.name} for o in organizations], }, - 'organizations': [ - {'id': o.id, 'name': o.name} for o in organizations - ] - }) + ) async def update(form: ContactUpdateRequest, contact: str): diff --git a/example/inertia-pingcrm-app/app/http/controllers/dashboard_controller.py b/example/inertia-pingcrm-app/app/http/controllers/dashboard_controller.py index 30b4ea6d..92df4925 100644 --- a/example/inertia-pingcrm-app/app/http/controllers/dashboard_controller.py +++ b/example/inertia-pingcrm-app/app/http/controllers/dashboard_controller.py @@ -2,4 +2,4 @@ async def index(): - return Inertia.render('Dashboard/Index') + return Inertia.render("Dashboard/Index") diff --git a/example/inertia-pingcrm-app/app/http/controllers/images_controller.py b/example/inertia-pingcrm-app/app/http/controllers/images_controller.py index adac9dce..8aec23f0 100644 --- a/example/inertia-pingcrm-app/app/http/controllers/images_controller.py +++ b/example/inertia-pingcrm-app/app/http/controllers/images_controller.py @@ -1,5 +1,6 @@ from fastapi_startkit.storage import Storage + async def stream(path: str): """Stream a file from S3 back to the client.""" return Storage.disk("s3").stream(path) diff --git a/example/inertia-pingcrm-app/app/http/controllers/organizations_controller.py b/example/inertia-pingcrm-app/app/http/controllers/organizations_controller.py index 91a9d25f..55bcc28f 100644 --- a/example/inertia-pingcrm-app/app/http/controllers/organizations_controller.py +++ b/example/inertia-pingcrm-app/app/http/controllers/organizations_controller.py @@ -10,53 +10,64 @@ async def index(filters: OrganizationListRequest = Depends()): paginator = await ( Organization.query() - .when(filters.search, lambda q: q.where('name', 'like', f'%{filters.search}%')) + .when(filters.search, lambda q: q.where("name", "like", f"%{filters.search}%")) .paginate(page=filters.page, per_page=filters.limit) ) - return Inertia.render('Organizations/Index', { - 'data': [ - { - 'id': org.id, - 'name': org.name, - 'phone': org.phone, - 'city': org.city, - 'deleted_at': None, - } for org in paginator.result - ], - 'meta': { - 'current_page': paginator.current_page, - 'last_page': paginator.last_page, - 'per_page': paginator.per_page, - 'total': paginator.total, + return Inertia.render( + "Organizations/Index", + { + "data": [ + { + "id": org.id, + "name": org.name, + "phone": org.phone, + "city": org.city, + "deleted_at": None, + } + for org in paginator.result + ], + "meta": { + "current_page": paginator.current_page, + "last_page": paginator.last_page, + "per_page": paginator.per_page, + "total": paginator.total, + }, }, - }) + ) + async def create(): - return Inertia.render('Organizations/Create') + return Inertia.render("Organizations/Create") + async def store(request: Request): form = await request.json() - form["account_id"] = 1 # hardcoded for demo + form["account_id"] = 1 # hardcoded for demo await Organization.create(form) return RedirectResponse(url="/organizations", status_code=303) + async def edit(organization: str): org = await Organization.find(organization) - return Inertia.render('Organizations/Edit', { - 'organization': { - 'id': org.id, - 'name': org.name, - 'email': org.email, - 'phone': org.phone, - 'address': org.address, - 'city': org.city, - 'region': org.region, - 'country': org.country, - 'postal_code': org.postal_code, - 'deleted_at': None, - } - }) + return Inertia.render( + "Organizations/Edit", + { + "organization": { + "id": org.id, + "name": org.name, + "email": org.email, + "phone": org.phone, + "address": org.address, + "city": org.city, + "region": org.region, + "country": org.country, + "postal_code": org.postal_code, + "deleted_at": None, + } + }, + ) + async def update(request: Request, organization: str): org = await Organization.find(organization) @@ -64,6 +75,7 @@ async def update(request: Request, organization: str): await org.update(form) return RedirectResponse(url=f"/organizations/{organization}/edit", status_code=303) + async def destroy(organization: str): org = await Organization.find(organization) await org.delete() diff --git a/example/inertia-pingcrm-app/app/http/controllers/profile_controller.py b/example/inertia-pingcrm-app/app/http/controllers/profile_controller.py index b07bdcaf..82a0f4d4 100644 --- a/example/inertia-pingcrm-app/app/http/controllers/profile_controller.py +++ b/example/inertia-pingcrm-app/app/http/controllers/profile_controller.py @@ -25,16 +25,19 @@ async def save_photo(photo: Optional[UploadFile]) -> Optional[str]: async def edit(request: Request): user = await User.find(request.state.user["id"]) photo_url = f"/images/{user.photo_path}" if user.photo_path else None - return Inertia.render('Profile/Edit', { - 'user': { - 'id': user.id, - 'first_name': user.first_name, - 'last_name': user.last_name, - 'email': user.email, - 'photo': photo_url, - 'password': '', - } - }) + return Inertia.render( + "Profile/Edit", + { + "user": { + "id": user.id, + "first_name": user.first_name, + "last_name": user.last_name, + "email": user.email, + "photo": photo_url, + "password": "", + } + }, + ) async def update( @@ -48,7 +51,7 @@ async def update( update_data = form.validated() if photo_path: - update_data['photo_path'] = photo_path + update_data["photo_path"] = photo_path await user.update(update_data) return RedirectResponse(url="/profile", status_code=303) diff --git a/example/inertia-pingcrm-app/app/http/controllers/reports_controller.py b/example/inertia-pingcrm-app/app/http/controllers/reports_controller.py index a2166381..54bb9acf 100644 --- a/example/inertia-pingcrm-app/app/http/controllers/reports_controller.py +++ b/example/inertia-pingcrm-app/app/http/controllers/reports_controller.py @@ -2,4 +2,4 @@ async def index(): - return Inertia.render('Reports/Index', {}) + return Inertia.render("Reports/Index", {}) diff --git a/example/inertia-pingcrm-app/app/http/controllers/users_controller.py b/example/inertia-pingcrm-app/app/http/controllers/users_controller.py index c3980d6b..c3ee3dc6 100644 --- a/example/inertia-pingcrm-app/app/http/controllers/users_controller.py +++ b/example/inertia-pingcrm-app/app/http/controllers/users_controller.py @@ -26,30 +26,39 @@ async def _save_photo(photo: Optional[UploadFile]) -> Optional[str]: async def index(): users = await User.query().limit(10).get() - return Inertia.render('Users/Index', { - 'users': { - 'data': [ - { - 'id': u.id, - 'name': f"{u.first_name} {u.last_name}", - 'email': u.email, - 'owner': u.owner, - 'photo': u.photo_path, - 'deleted_at': None, - } for u in users - ], - 'links': {'first': None, 'last': None, 'prev': None, 'next': None}, - 'meta': { - 'current_page': 1, 'last_page': 1, 'per_page': 10, - 'from': 1, 'to': len(users), 'total': len(users), - 'path': '/users', 'links': [], - }, - } - }) + return Inertia.render( + "Users/Index", + { + "users": { + "data": [ + { + "id": u.id, + "name": f"{u.first_name} {u.last_name}", + "email": u.email, + "owner": u.owner, + "photo": u.photo_path, + "deleted_at": None, + } + for u in users + ], + "links": {"first": None, "last": None, "prev": None, "next": None}, + "meta": { + "current_page": 1, + "last_page": 1, + "per_page": 10, + "from": 1, + "to": len(users), + "total": len(users), + "path": "/users", + "links": [], + }, + } + }, + ) async def create(): - return Inertia.render('Users/Create', {}) + return Inertia.render("Users/Create", {}) async def store( @@ -57,21 +66,21 @@ async def store( first_name: str = Form(...), last_name: str = Form(...), email: str = Form(...), - password: str = Form(default=''), - owner: str = Form(default='0'), + password: str = Form(default=""), + owner: str = Form(default="0"), photo: Optional[UploadFile] = File(default=None), ): photo_path = await _save_photo(photo) user_data = { - 'first_name': first_name, - 'last_name': last_name, - 'email': email, - 'password': password, - 'owner': owner == '1', + "first_name": first_name, + "last_name": last_name, + "email": email, + "password": password, + "owner": owner == "1", } if photo_path: - user_data['photo_path'] = photo_path + user_data["photo_path"] = photo_path await User.create(user_data) return RedirectResponse(url="/users", status_code=303) @@ -79,18 +88,21 @@ async def store( async def edit(user: int): u = await User.find(user) - return Inertia.render('Users/Edit', { - 'user': { - 'id': u.id, - 'first_name': u.first_name, - 'last_name': u.last_name, - 'email': u.email, - 'owner': u.owner, - 'photo': u.photo_path, - 'password': '', - 'deleted_at': None, - } - }) + return Inertia.render( + "Users/Edit", + { + "user": { + "id": u.id, + "first_name": u.first_name, + "last_name": u.last_name, + "email": u.email, + "owner": u.owner, + "photo": u.photo_path, + "password": "", + "deleted_at": None, + } + }, + ) async def update( @@ -99,8 +111,8 @@ async def update( first_name: str = Form(...), last_name: str = Form(...), email: str = Form(...), - password: str = Form(default=''), - owner: str = Form(default='0'), + password: str = Form(default=""), + owner: str = Form(default="0"), photo: Optional[UploadFile] = File(default=None), ): u = await User.find(user) @@ -108,15 +120,15 @@ async def update( photo_path = await _save_photo(photo) update_data = { - 'first_name': first_name, - 'last_name': last_name, - 'email': email, - 'owner': owner == '1', + "first_name": first_name, + "last_name": last_name, + "email": email, + "owner": owner == "1", } if password: - update_data['password'] = password + update_data["password"] = password if photo_path: - update_data['photo_path'] = photo_path + update_data["photo_path"] = photo_path await u.update(update_data) return RedirectResponse(url=f"/users/{user}/edit", status_code=303) diff --git a/example/inertia-pingcrm-app/app/http/requests/contact.py b/example/inertia-pingcrm-app/app/http/requests/contact.py index 313263ba..28e939c2 100644 --- a/example/inertia-pingcrm-app/app/http/requests/contact.py +++ b/example/inertia-pingcrm-app/app/http/requests/contact.py @@ -3,7 +3,7 @@ class ContactListRequest: - def __init__(self, search: str = '', page: int = 1, limit: int = 10): + def __init__(self, search: str = "", page: int = 1, limit: int = 10): self.search = search self.page = page self.limit = limit diff --git a/example/inertia-pingcrm-app/app/http/requests/organization.py b/example/inertia-pingcrm-app/app/http/requests/organization.py index 67106d05..403fbe49 100644 --- a/example/inertia-pingcrm-app/app/http/requests/organization.py +++ b/example/inertia-pingcrm-app/app/http/requests/organization.py @@ -1,5 +1,5 @@ class OrganizationListRequest: - def __init__(self, search: str = '', page: int = 1, limit: int = 10): + def __init__(self, search: str = "", page: int = 1, limit: int = 10): self.search = search self.page = page self.limit = limit diff --git a/example/inertia-pingcrm-app/app/http/requests/profile.py b/example/inertia-pingcrm-app/app/http/requests/profile.py index 30c4c41a..2413c015 100644 --- a/example/inertia-pingcrm-app/app/http/requests/profile.py +++ b/example/inertia-pingcrm-app/app/http/requests/profile.py @@ -5,4 +5,4 @@ class ProfileUpdateRequest(RequestModel): first_name: str last_name: str email: str - password: str = '' + password: str = "" diff --git a/example/inertia-pingcrm-app/app/models/Account.py b/example/inertia-pingcrm-app/app/models/Account.py index 788f5ea6..d8333c9c 100644 --- a/example/inertia-pingcrm-app/app/models/Account.py +++ b/example/inertia-pingcrm-app/app/models/Account.py @@ -3,6 +3,7 @@ class Account(Model): """Account Model.""" + __table__ = "accounts" id: int diff --git a/example/inertia-pingcrm-app/app/models/Contact.py b/example/inertia-pingcrm-app/app/models/Contact.py index 4b7657c6..ba308543 100644 --- a/example/inertia-pingcrm-app/app/models/Contact.py +++ b/example/inertia-pingcrm-app/app/models/Contact.py @@ -4,6 +4,7 @@ class Contact(Model): """Contact Model.""" + __table__ = "contacts" id: int diff --git a/example/inertia-pingcrm-app/app/models/Organization.py b/example/inertia-pingcrm-app/app/models/Organization.py index a60b7e45..9019772e 100644 --- a/example/inertia-pingcrm-app/app/models/Organization.py +++ b/example/inertia-pingcrm-app/app/models/Organization.py @@ -4,6 +4,7 @@ class Organization(Model): """Organization Model.""" + __table__ = "organizations" id: int diff --git a/example/inertia-pingcrm-app/app/models/User.py b/example/inertia-pingcrm-app/app/models/User.py index dd77941b..b385c4d6 100644 --- a/example/inertia-pingcrm-app/app/models/User.py +++ b/example/inertia-pingcrm-app/app/models/User.py @@ -4,6 +4,7 @@ class User(Model): """User Model.""" + __table__ = "users" __hidden__ = ["password", "remember_token"] diff --git a/example/inertia-pingcrm-app/bootstrap/application.py b/example/inertia-pingcrm-app/bootstrap/application.py index a4c15289..a99b7d42 100644 --- a/example/inertia-pingcrm-app/bootstrap/application.py +++ b/example/inertia-pingcrm-app/bootstrap/application.py @@ -17,11 +17,12 @@ from fastapi_startkit.vite import ViteProvider from starlette.responses import RedirectResponse + class ExceptionHandler(BaseHandler): def register(self): self.register_render( NotAuthenticated, - lambda request, exc: RedirectResponse(url="/login", status_code=303) + lambda request, exc: RedirectResponse(url="/login", status_code=303), ) diff --git a/example/inertia-pingcrm-app/config/database.py b/example/inertia-pingcrm-app/config/database.py index a279ee24..b1e6323e 100644 --- a/example/inertia-pingcrm-app/config/database.py +++ b/example/inertia-pingcrm-app/config/database.py @@ -9,25 +9,25 @@ class DatabaseConfig: default: str = field(default_factory=lambda: env("DB_CONNECTION", "postgres")) - connections: Dict[str, Dict[str, Any]] = field(default_factory=lambda: { - "sqlite": SQLiteConfig( - driver="sqlite", - database=env("DB_DATABASE", "database.sqlite"), - options=None, - ), - "postgres": PostgresConfig( - driver="postgres", - host=env("DB_HOST", "127.0.0.1"), - database=env("DB_DATABASE", "forge"), - username=env("DB_USERNAME", "forge"), - password=env("DB_PASSWORD", ""), - port=int(env("DB_PORT", "5432")), - options=None, - ), - }) + connections: Dict[str, Dict[str, Any]] = field( + default_factory=lambda: { + "sqlite": SQLiteConfig( + driver="sqlite", + database=env("DB_DATABASE", "database.sqlite"), + options=None, + ), + "postgres": PostgresConfig( + driver="postgres", + host=env("DB_HOST", "127.0.0.1"), + database=env("DB_DATABASE", "forge"), + username=env("DB_USERNAME", "forge"), + password=env("DB_PASSWORD", ""), + port=int(env("DB_PORT", "5432")), + options=None, + ), + } + ) - migrations: Dict[str, Dict[str, Any]] = field(default_factory=lambda: { - "table": "migrations", - - "path": "databases/migrations" - }) + migrations: Dict[str, Dict[str, Any]] = field( + default_factory=lambda: {"table": "migrations", "path": "databases/migrations"} + ) diff --git a/example/inertia-pingcrm-app/config/logging.py b/example/inertia-pingcrm-app/config/logging.py index cbc45d7a..b6c9f63a 100644 --- a/example/inertia-pingcrm-app/config/logging.py +++ b/example/inertia-pingcrm-app/config/logging.py @@ -6,18 +6,19 @@ @dataclasses.dataclass class LoggingConfig: - default: str = dataclasses.field(default_factory=lambda: env('LOG_CHANNEL', 'stack')) + default: str = dataclasses.field( + default_factory=lambda: env("LOG_CHANNEL", "stack") + ) - channels: dict = dataclasses.field(default_factory=lambda: { - 'stack': StackChannel( - driver='stack', - channels=['daily', 'terminal'] - ), - 'daily': DailyChannel( - level=env('LOG_DAILY_LEVEL', 'debug'), - path=env('LOG_DAILY_PATH', 'storage/logs'), - ), - 'terminal': TerminalChannel( - level=env('LOG_TERMINAL_LEVEL', 'debug'), - ), - }) + channels: dict = dataclasses.field( + default_factory=lambda: { + "stack": StackChannel(driver="stack", channels=["daily", "terminal"]), + "daily": DailyChannel( + level=env("LOG_DAILY_LEVEL", "debug"), + path=env("LOG_DAILY_PATH", "storage/logs"), + ), + "terminal": TerminalChannel( + level=env("LOG_TERMINAL_LEVEL", "debug"), + ), + } + ) diff --git a/example/inertia-pingcrm-app/config/storage.py b/example/inertia-pingcrm-app/config/storage.py index 8c2f22a0..b195fbd9 100644 --- a/example/inertia-pingcrm-app/config/storage.py +++ b/example/inertia-pingcrm-app/config/storage.py @@ -28,4 +28,4 @@ class StorageConfig: use_path_style_endpoint=True, ), } - ) \ No newline at end of file + ) diff --git a/example/inertia-pingcrm-app/databases/factories/UserFactory.py b/example/inertia-pingcrm-app/databases/factories/UserFactory.py index 44888b2b..3c605acf 100644 --- a/example/inertia-pingcrm-app/databases/factories/UserFactory.py +++ b/example/inertia-pingcrm-app/databases/factories/UserFactory.py @@ -21,13 +21,15 @@ def definition(self): def configure(self): async def making(user): print(f"Making user: {user.name}") - + async def created(user): print(f"Created user: {user.name}") return self.after_making(making).after_creating(created) def suspended(self): - return self.state(lambda attributes: { - "account_status": "suspended", - }) + return self.state( + lambda attributes: { + "account_status": "suspended", + } + ) diff --git a/example/inertia-pingcrm-app/databases/seeds/database_seeder.py b/example/inertia-pingcrm-app/databases/seeds/database_seeder.py index 9487b08b..05181f83 100644 --- a/example/inertia-pingcrm-app/databases/seeds/database_seeder.py +++ b/example/inertia-pingcrm-app/databases/seeds/database_seeder.py @@ -14,27 +14,31 @@ async def run(self): """Run the database seeds.""" # Create Account account = await Account.create({"name": "Acme Corporation"}) - + # Create User - await User.first_or_create({ - "email": "johndoe@example.com", - }, { - "account_id": account.id, - "first_name": "John", - "last_name": "Doe", - "password": "secret", # TODO: Use hash - "owner": True - }) + await User.first_or_create( + { + "email": "johndoe@example.com", + }, + { + "account_id": account.id, + "first_name": "John", + "last_name": "Doe", + "password": "secret", # TODO: Use hash + "owner": True, + }, + ) # Create 5 more users await UserFactory.new().count(5).create(account_id=account.id) # Create 100 organizations - organizations = await OrganizationFactory.new().count(100).create(account_id=account.id) + organizations = ( + await OrganizationFactory.new().count(100).create(account_id=account.id) + ) # Create 100 contacts for _ in range(100): await ContactFactory.new().create( - account_id=account.id, - organization_id=random.choice(organizations).id + account_id=account.id, organization_id=random.choice(organizations).id ) diff --git a/example/inertia-pingcrm-app/docker-compose.yml b/example/inertia-pingcrm-app/docker-compose.yml new file mode 100644 index 00000000..23d5a303 --- /dev/null +++ b/example/inertia-pingcrm-app/docker-compose.yml @@ -0,0 +1,27 @@ +services: + db: + image: postgres:16-alpine + environment: + POSTGRES_USER: app + POSTGRES_PASSWORD: secret + POSTGRES_DB: database_app_test + ports: + - "5432:5432" + volumes: + - pgdata:/var/lib/postgresql/data + + minio: + image: minio/minio + command: server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + ports: + - "9000:9000" + - "9001:9001" + volumes: + - miniodata:/data + +volumes: + pgdata: + miniodata: diff --git a/example/inertia-pingcrm-app/providers/fastapi_provider.py b/example/inertia-pingcrm-app/providers/fastapi_provider.py index ccadf0e9..88230402 100644 --- a/example/inertia-pingcrm-app/providers/fastapi_provider.py +++ b/example/inertia-pingcrm-app/providers/fastapi_provider.py @@ -25,13 +25,23 @@ def boot(self) -> None: inertia = self.app.make("inertia") inertia.share("app_name", "Inertia Demo") inertia.version("v1.0.0") - inertia.share("auth", lambda request: {"user": getattr(request.state, "user", None)}) - inertia.share("flash", lambda request: { - "success": request.session.get("flash_success") if "session" in request.scope else None, - "error": request.session.get("flash_error") if "session" in request.scope else None, - }) + inertia.share( + "auth", lambda request: {"user": getattr(request.state, "user", None)} + ) + inertia.share( + "flash", + lambda request: { + "success": request.session.get("flash_success") + if "session" in request.scope + else None, + "error": request.session.get("flash_error") + if "session" in request.scope + else None, + }, + ) inertia.share("errors", {}) from routes.web import guest, auth + self.app.include_router(guest) self.app.include_router(auth)