Skip to content
Open
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
14 changes: 14 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,17 @@ services:
interval: 5s
timeout: 5s
retries: 10

postgres:
image: postgres:16
environment:
POSTGRES_DB: database_app_test
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
ports:
- "5432:5432"
healthcheck:
test: [ "CMD", "pg_isready", "-U", "app", "-d", "database_app_test" ]
interval: 5s
timeout: 5s
retries: 10
11 changes: 11 additions & 0 deletions example/inertia-pingcrm-app/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
APP_NAME="Inertia Tickets"
APP_ENV=local
APP_URL=http://localhost:8000
APP_DEBUG=true

DB_CONNECTION=postgres
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=inertia
DB_USERNAME=local
DB_PASSWORD=secret
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
from fastapi import Request
from fastapi.responses import RedirectResponse
from fastapi_startkit.inertia import Inertia

from app.http.requests.auth import LoginRequest
from app.models.User import User


async def create():
return Inertia.render('Auth/Login', {})

async def store(request: Request):
form = await request.json()
email = form.get("email")
password = form.get("password")

async def store(request: LoginRequest):
email = request.email
password = request.password

user = await User.where("email", email).first()
if user and user.password == password:
request.session["user_id"] = user.id
return RedirectResponse(url="/", status_code=303)
# if user and user.password == password:
# 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.'}
})


async def destroy(request: Request):
request.session.clear()
return RedirectResponse(url="/login", status_code=303)
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
from fastapi import Request
from fastapi.responses import RedirectResponse
from fastapi_startkit.inertia import Inertia

from app.models.User import User


async def index():
users = await User.query().limit(10).get()
users = await User.query().limit(10).paginate()

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': [],
},
}
'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.result
],
'meta': {
'current_page': users.current_page,
'last_page': users.last_page,
'per_page': users.last_page,
'total': users.total,
},
})


Expand All @@ -38,7 +38,7 @@ async def store(request: Request):
return RedirectResponse(url="/users", status_code=303)


async def edit(user: str):
async def edit(user: int):
u = await User.find(user)
return Inertia.render('Users/Edit', {
'user': {
Expand All @@ -48,13 +48,12 @@ async def edit(user: str):
'email': u.email,
'owner': u.owner,
'photo': u.photo_path,
'password': '',
'deleted_at': None,
}
})


async def update(request: Request, user: str):
async def update(request: Request, user: int):
u = await User.find(user)
form = await request.json()
await u.update(form)
Expand Down
6 changes: 6 additions & 0 deletions example/inertia-pingcrm-app/app/http/requests/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from pydantic import BaseModel, Field


class LoginRequest(BaseModel):
email: str = Field(min_length=1)
password: str = Field(min_length=1)
17 changes: 8 additions & 9 deletions example/inertia-pingcrm-app/bootstrap/application.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
from pathlib import Path

from config.database import DatabaseConfig
from providers.fastapi_provider import FastAPIProvider
from starlette.middleware.trustedhost import TrustedHostMiddleware

from starlette.middleware.sessions import SessionMiddleware

from authentication.middlewares.auth import AuthMiddleware, NotAuthenticated
from fastapi_startkit import Application
from fastapi_startkit.exceptions import ExceptionHandler as BaseHandler
from fastapi_startkit.inertia import InertiaProvider
from fastapi_startkit.logging import LogProvider
from fastapi_startkit.masoniteorm import DatabaseProvider
from fastapi_startkit.vite import ViteProvider
from starlette.middleware.sessions import SessionMiddleware
from starlette.middleware.trustedhost import TrustedHostMiddleware
from starlette.responses import RedirectResponse

from authentication.middlewares.auth import AuthMiddleware, NotAuthenticated
from config.database import DatabaseConfig
from providers.fastapi_provider import FastAPIProvider


class ExceptionHandler(BaseHandler):
def register(self):
self.register_render(
Expand All @@ -24,7 +24,7 @@ def register(self):


app: Application = Application(
base_path=str(Path.cwd()),
base_path=Path(__file__).resolve().parent.parent,
providers=[
LogProvider,
(DatabaseProvider, DatabaseConfig),
Expand All @@ -35,7 +35,6 @@ def register(self):
exception_handler=ExceptionHandler,
)


app.add_middleware(AuthMiddleware)
app.add_middleware(SessionMiddleware, secret_key="...")
app.add_middleware(TrustedHostMiddleware, allowed_hosts=["*"])
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import MainMenuItem from '@/Components/Menu/MainMenuItem';
import { Building, CircleGauge, Printer, Users } from 'lucide-react';
import MainMenuItem from "@/Components/Menu/MainMenuItem"
import { Building, CircleGauge, Printer, Users } from "lucide-react"

interface MainMenuProps {
className?: string;
className?: string;
}

export default function MainMenu({ className }: MainMenuProps) {
return (
<div className={className}>
<MainMenuItem
text="Dashboard"
link="dashboard"
icon={<CircleGauge size={20} />}
/>
<MainMenuItem
text="Organizations"
link="organizations"
icon={<Building size={20} />}
/>
<MainMenuItem
text="Contacts"
link="contacts"
icon={<Users size={20} />}
/>
<MainMenuItem
text="Reports"
link="reports"
icon={<Printer size={20} />}
/>
</div>
);
return (
<div className={className}>
<MainMenuItem
text="Dashboard"
link="dashboard"
icon={<CircleGauge size={20}/>}
/>
<MainMenuItem
text="Organizations"
link="organizations"
icon={<Building size={20}/>}
/>
<MainMenuItem
text="Contacts"
link="contacts"
icon={<Users size={20}/>}
/>
<MainMenuItem
text="Users"
link="users"
icon={<Users size={20}/>}
/>
<MainMenuItem
text="Reports"
link="reports"
icon={<Printer size={20}/>}
/>
</div>
)
}
70 changes: 35 additions & 35 deletions example/inertia-pingcrm-app/resources/js/Layouts/MainLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
import { Head } from '@inertiajs/react';
import MainMenu from '@/Components/Menu/MainMenu';
import FlashMessages from '@/Components/Messages/FlashMessages';
import TopHeader from '@/Components/Header/TopHeader';
import BottomHeader from '@/Components/Header/BottomHeader';
import BottomHeader from "@/Components/Header/BottomHeader"
import TopHeader from "@/Components/Header/TopHeader"
import MainMenu from "@/Components/Menu/MainMenu"
import FlashMessages from "@/Components/Messages/FlashMessages"
import { Head } from "@inertiajs/react"

interface MainLayoutProps {
title?: string;
children: React.ReactNode;
title?: string;
children: React.ReactNode;
}

export default function MainLayout({ title, children }: MainLayoutProps) {
return (
<>
<Head title={title} />
<div className="flex flex-col">
<div className="flex flex-col h-screen">
<div className="md:flex">
<TopHeader />
<BottomHeader />
</div>
<div className="flex flex-grow overflow-hidden">
<MainMenu className="flex-shrink-0 hidden w-56 p-12 overflow-y-auto bg-indigo-800 md:block" />
{/**
* We need to scroll the content of the page, not the whole page.
* So we need to add `scroll-region="true"` to the div below.
*
* [Read more](https://inertiajs.com/pages#scroll-regions)
*/}
<div
className="w-full px-4 py-8 overflow-hidden overflow-y-auto md:p-12"
scroll-region="true"
>
<FlashMessages />
{children}
return (
<>
<Head title={title}/>
<div className="flex flex-col">
<div className="flex flex-col h-screen">
<div className="md:flex">
<TopHeader/>
<BottomHeader/>
</div>
<div className="flex flex-grow overflow-hidden">
<MainMenu className="flex-shrink-0 hidden w-56 p-12 overflow-y-auto bg-indigo-800 md:block"/>
{/**
* We need to scroll the content of the page, not the whole page.
* So we need to add `scroll-region="true"` to the div below.
*
* [Read more](https://inertiajs.com/pages#scroll-regions)
*/}
<div
className="w-full px-4 py-8 overflow-hidden overflow-y-auto md:p-12"
scroll-region="true"
>
<FlashMessages/>
{children}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React from "react"

export default function LoginPage() {
const { data, setData, errors, post, processing } = useForm({
email: "johndoe@example.com",
email: "",
password: "secret",
remember: true,
})
Expand Down
Loading
Loading