Compare commits

...

3 Commits

Author SHA1 Message Date
35448385c5 Adding foreign key to auto forms 2025-01-20 11:31:57 +01:00
fe84d6de2f Updating projet config 2025-01-20 11:30:47 +01:00
5dd885a061 Updating IDE config 2025-01-20 11:29:20 +01:00
10 changed files with 111 additions and 8 deletions

4
.gitignore vendored
View File

@@ -1,3 +1,7 @@
api/app/database.db
api/password
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/

View File

@@ -4,8 +4,9 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/api/app" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/api/.venv" />
<excludeFolder url="file://$MODULE_DIR$/api/venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.12 virtualenv at ~/projects/dev/python/budget_forecast/api/venv" jdkType="Python SDK" />
<orderEntry type="jdk" jdkName="Python 3.12 (budget-forecast)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

2
.idea/misc.xml generated
View File

@@ -3,5 +3,5 @@
<component name="Black">
<option name="sdkName" value="Python 3.12 (budget_forecast)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 virtualenv at ~/projects/dev/python/budget_forecast/api/venv" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (budget-forecast)" project-jdk-type="Python SDK" />
</project>

2
.idea/vcs.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/gui/app" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -2,16 +2,17 @@ from uuid import UUID, uuid4
from enum import Enum
from sqlmodel import Field, SQLModel, select
from pydantic import Field as PydField
from category.models import CategoryRead
class AccountType(Enum):
Asset = "Asset" # < Denotes a generic asset account.
Checkings = "Checkings" # < Standard checking account
Savings = "Savings" # < Typical savings account
Cash = "Cash" # < Denotes a shoe-box or pillowcase stuffed with cash
Liability = "Liability" # < Denotes a generic liability account.
CreditCard = "CreditCard" # < Credit card accounts
Loan = "Loan" # < Loan and mortgage accounts (liability)
@@ -69,10 +70,19 @@ class Account(AccountBaseId, table=True):
session.commit()
class AccountRead(AccountBaseId):
default_category: CategoryRead
# default_category: CategoryRead
pass
class AccountWrite(AccountBase):
pass
default_category_id: UUID = PydField(default=None, json_schema_extra={
"foreign_key": {
"reference": {
"resource": "categories",
"schema": "CategoryRead",
"label": "name"
}
}
})
class AccountCreate(AccountWrite):
pass

7
api/app/requirements.txt Normal file
View File

@@ -0,0 +1,7 @@
uvicorn
sqlmodel
alembic
fastapi
fastapi-pagination
fastapi-users[sqlmodel]
fastapi-users-db-sqlmodel

View File

@@ -1,11 +1,11 @@
{
"name": "auth-material-ui",
"name": "budget-forecast-gui",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "auth-material-ui",
"name": "budget-forecast-gui",
"version": "1.0.0",
"dependencies": {
"@emotion/react": "^11.8.2",

View File

@@ -1,8 +1,11 @@
import validator from "@rjsf/validator-ajv8";
import Form from "@rjsf/mui";
import { RegistryWidgetsType } from "@rjsf/utils";
import { useEffect, useState } from "react";
import { jsonschemaProvider } from "../../providers/jsonschema-provider";
import { useForm } from "@refinedev/core";
//import TextWidget from "@rjsf/core/src/components/widgets/TextWidget";
import CrudTextWidget from "./widgets/crud-text-widget";
type Props = {
schemaName: string,
@@ -11,6 +14,8 @@ type Props = {
//onSubmit: (data: IChangeEvent, event: FormEvent<any>) => void
}
const customWidgets: RegistryWidgetsType = { TextWidget: CrudTextWidget };
export const CrudForm: React.FC<Props> = ({schemaName, resource, id}) => {
const { onFinish, query, formLoading } = useForm({
resource: resource,
@@ -47,6 +52,7 @@ export const CrudForm: React.FC<Props> = ({schemaName, resource, id}) => {
onSubmit={(e) => onFinish(e.formData)}
validator={validator}
omitExtraData={true}
widgets={customWidgets}
/>
)
}

View File

@@ -0,0 +1,15 @@
import TextWidget from "@rjsf/core/lib/components/widgets/TextWidget";
import {FormContextType, getTemplate, RJSFSchema, StrictRJSFSchema, WidgetProps} from "@rjsf/utils";
import {ForeignKeyWidget} from "./foreign-key";
export default function CrudTextWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: WidgetProps<T, S, F>
) {
if (props.schema.hasOwnProperty("foreign_key")) {
return (<ForeignKeyWidget {...props} />);
}else {
return (<CrudTextWidget {...props} />);
}
}

View File

@@ -0,0 +1,60 @@
import { RJSFSchema, UiSchema, WidgetProps, RegistryWidgetsType } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';
import {Autocomplete, AutocompleteRenderInputParams, debounce} from "@mui/material";
import {useAutocomplete} from "@refinedev/mui";
import { Controller } from "react-hook-form";
import {useState, useEffect, useCallback} from "react";
import TextField from "@mui/material/TextField";
import {axiosInstance} from "@refinedev/simple-rest";
import {useList} from "@refinedev/core";
export const ForeignKeyWidget = (props: WidgetProps) => {
const [inputValue, setInputValue] = useState("");
const [selectedValue, setSelectedValue] = useState<string | null>(null);
const resource = props.schema.foreign_key.reference.resource
const { data, isLoading } = useList({
resource: resource,
pagination: { current: 1, pageSize: 10 },
sorters: [{ field: "name", order: "asc" }],
filters: [{ field: "name", operator: "contains", value: "input" }],
});
const options = data?.data || [];
// const fetchOptions = async (input: string) => {
// try {
//
// } catch (error) {
// console.error("Error fetching options:", error);
// }
// };
// // Debounced version of the fetch function
// const debouncedFetch = useCallback(debounce(fetchOptions, 300), []);
// // Trigger fetch whenever the inputValue changes
// useEffect(() => {
// if (inputValue) {
// debouncedFetch(inputValue);
// } else {
// setOptions([]); // Clear options when input is empty
// }
// }, [inputValue, debouncedFetch]);
return (
<Autocomplete
value={selectedValue}
onChange={(event, newValue) => setSelectedValue(String(newValue))}
inputValue={inputValue}
onInputChange={(event, newInputValue) => setInputValue(newInputValue)}
options={options}
getOptionLabel={(option) => option.name}
loading={isLoading}
renderInput={(params) => (
<TextField {...params} label="Search" variant="outlined" />
)}
/>
);
};