Save and edit order pool scheduling
This commit is contained in:
parent
14009ad6d3
commit
0511e0f488
7 changed files with 154 additions and 3 deletions
|
|
@ -32,6 +32,13 @@ class OrdersPool(BaseModel):
|
||||||
|
|
||||||
user = ForeignKeyField(column_name='user_id', field='id', model=User, backref='orders_pools')
|
user = ForeignKeyField(column_name='user_id', field='id', model=User, backref='orders_pools')
|
||||||
|
|
||||||
|
scheduled = BooleanField(default=False)
|
||||||
|
probability = FloatField(null=True)
|
||||||
|
weekdays = BooleanField(null=True)
|
||||||
|
weekends = BooleanField(null=True)
|
||||||
|
time = TextField(null=True)
|
||||||
|
confirm_delay = IntegerField(null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
table_name = 'orders_pool'
|
table_name = 'orders_pool'
|
||||||
|
|
||||||
|
|
|
||||||
21
flask/api.py
21
flask/api.py
|
|
@ -73,6 +73,21 @@ def sub_order_set(username, set_id):
|
||||||
with database.atomic() as transaction:
|
with database.atomic() as transaction:
|
||||||
try:
|
try:
|
||||||
op.name = request.json['name']
|
op.name = request.json['name']
|
||||||
|
|
||||||
|
op.scheduled = request.json['scheduled']
|
||||||
|
if op.scheduled:
|
||||||
|
op.probability = request.json['probability']
|
||||||
|
op.weekdays = request.json['weekdays']
|
||||||
|
op.weekends = request.json['weekends']
|
||||||
|
op.time = request.json['time']
|
||||||
|
op.confirm_delay = request.json['confirm_delay']
|
||||||
|
else:
|
||||||
|
op.probability = None
|
||||||
|
op.weekdays = None
|
||||||
|
op.weekends = None
|
||||||
|
op.time = None
|
||||||
|
op.confirm_delay = None
|
||||||
|
|
||||||
op.save()
|
op.save()
|
||||||
|
|
||||||
for updated_order in request.json['orders']:
|
for updated_order in request.json['orders']:
|
||||||
|
|
@ -106,6 +121,12 @@ def sub_order_set(username, set_id):
|
||||||
{
|
{
|
||||||
'id': op.id,
|
'id': op.id,
|
||||||
'name': op.name,
|
'name': op.name,
|
||||||
|
'scheduled': op.scheduled,
|
||||||
|
'probability': op.probability,
|
||||||
|
'weekdays': op.weekdays,
|
||||||
|
'weekends': op.weekends,
|
||||||
|
'time': op.time,
|
||||||
|
'confirm_delay': op.confirm_delay,
|
||||||
'orders': [{
|
'orders': [{
|
||||||
'id': order.id,
|
'id': order.id,
|
||||||
'name': order.name,
|
'name': order.name,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mantine/core": "^8.3.12",
|
"@mantine/core": "^8.3.12",
|
||||||
|
"@mantine/dates": "^8.3.13",
|
||||||
"@mantine/form": "^8.3.13",
|
"@mantine/form": "^8.3.13",
|
||||||
"@mantine/notifications": "^8.3.13",
|
"@mantine/notifications": "^8.3.13",
|
||||||
"@tabler/icons-react": "^3.36.1",
|
"@tabler/icons-react": "^3.36.1",
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,14 @@ import {
|
||||||
Title,
|
Title,
|
||||||
Box,
|
Box,
|
||||||
Affix,
|
Affix,
|
||||||
|
Checkbox,
|
||||||
|
Chip,
|
||||||
|
Collapse,
|
||||||
|
NumberInput,
|
||||||
|
Text,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { notifications } from "@mantine/notifications";
|
import { notifications } from "@mantine/notifications";
|
||||||
|
import { TimeInput } from "@mantine/dates";
|
||||||
import { randomId } from "@mantine/hooks";
|
import { randomId } from "@mantine/hooks";
|
||||||
import { useForm } from "@mantine/form";
|
import { useForm } from "@mantine/form";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
@ -51,14 +57,25 @@ type FormOrderSet = Omit<OrderSet, "orders"> & {
|
||||||
export const SubOrderSet: React.FC = () => {
|
export const SubOrderSet: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { username, set_id } = useParams();
|
const { username, set_id } = useParams();
|
||||||
const { id, name, orders } = useLoaderData<OrderSet>();
|
const orderSet = useLoaderData<OrderSet>();
|
||||||
|
const [showScheduling, setShowScheduling] = React.useState(
|
||||||
|
orderSet.scheduled,
|
||||||
|
);
|
||||||
|
|
||||||
const form = useForm<FormOrderSet>({
|
const form = useForm<FormOrderSet>({
|
||||||
mode: "uncontrolled",
|
mode: "uncontrolled",
|
||||||
initialValues: { id, name, orders },
|
initialValues: orderSet,
|
||||||
validate: {
|
validate: {
|
||||||
name: (value: string) =>
|
name: (value: string) =>
|
||||||
value.length < 1 ? "Please enter a name" : null,
|
value.length < 1 ? "Please enter a name" : null,
|
||||||
|
time: (value: string, values: FormOrderSet) =>
|
||||||
|
values.scheduled && (!value || value.length < 1)
|
||||||
|
? "Please set a time"
|
||||||
|
: null,
|
||||||
|
probability: (value: number, values: FormOrderSet) =>
|
||||||
|
values.scheduled && (!value || value === 0.0)
|
||||||
|
? "Please set a probability > 0"
|
||||||
|
: null,
|
||||||
orders: {
|
orders: {
|
||||||
name: (value: string) =>
|
name: (value: string) =>
|
||||||
value.length < 1 ? "Please enter a name" : null,
|
value.length < 1 ? "Please enter a name" : null,
|
||||||
|
|
@ -68,6 +85,11 @@ export const SubOrderSet: React.FC = () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
onValuesChange: (values) => {
|
||||||
|
if (values.scheduled !== showScheduling) {
|
||||||
|
setShowScheduling(values.scheduled);
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSubmit = React.useCallback(
|
const handleSubmit = React.useCallback(
|
||||||
|
|
@ -151,11 +173,50 @@ export const SubOrderSet: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<Container pb="xl">
|
<Container pb="xl">
|
||||||
<Box mb="lg">
|
<Box mb="lg">
|
||||||
<Title order={1}>{name}</Title>
|
<Title order={1}>{orderSet.name}</Title>
|
||||||
<Link to={`/dashboard/subs/${username}`}>Return to {username}</Link>
|
<Link to={`/dashboard/subs/${username}`}>Return to {username}</Link>
|
||||||
</Box>
|
</Box>
|
||||||
<form id="order-set" onSubmit={handleSubmit}>
|
<form id="order-set" onSubmit={handleSubmit}>
|
||||||
<TextInput {...form.getInputProps("name")} label="Name" />
|
<TextInput {...form.getInputProps("name")} label="Name" />
|
||||||
|
<Checkbox
|
||||||
|
{...form.getInputProps("scheduled", { type: "checkbox" })}
|
||||||
|
label="Scheduled"
|
||||||
|
mb="sm"
|
||||||
|
mt="lg"
|
||||||
|
/>
|
||||||
|
<Collapse in={showScheduling}>
|
||||||
|
<Paper bg="gray.2">
|
||||||
|
<Input.Wrapper
|
||||||
|
error={form.getInputProps("probability").error}
|
||||||
|
label="Probability"
|
||||||
|
>
|
||||||
|
<Slider
|
||||||
|
{...form.getInputProps("probability")}
|
||||||
|
domain={[0, 1]}
|
||||||
|
step={0.05}
|
||||||
|
/>
|
||||||
|
</Input.Wrapper>
|
||||||
|
<Flex my="md" gap="sm">
|
||||||
|
<Chip {...form.getInputProps("weekdays", { type: "checkbox" })}>
|
||||||
|
Weekdays
|
||||||
|
</Chip>
|
||||||
|
<Chip {...form.getInputProps("weekends", { type: "checkbox" })}>
|
||||||
|
Weekends
|
||||||
|
</Chip>
|
||||||
|
</Flex>
|
||||||
|
<TimeInput {...form.getInputProps("time")} label="Time" />
|
||||||
|
<NumberInput
|
||||||
|
{...form.getInputProps("confirm_delay")}
|
||||||
|
label="Confirmation Due After"
|
||||||
|
allowDecimal={false}
|
||||||
|
allowNegative={false}
|
||||||
|
min={1}
|
||||||
|
max={168}
|
||||||
|
rightSection={<Text mr="xl">hours</Text>}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
</Collapse>
|
||||||
|
|
||||||
<Title order={2} mt="lg" mb="sm">
|
<Title order={2} mt="lg" mb="sm">
|
||||||
Orders
|
Orders
|
||||||
</Title>
|
</Title>
|
||||||
|
|
|
||||||
6
flask/vite/src/index.d.ts
vendored
6
flask/vite/src/index.d.ts
vendored
|
|
@ -16,4 +16,10 @@ type OrderSet = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
orders: OrderSetOrder[];
|
orders: OrderSetOrder[];
|
||||||
|
scheduled: boolean;
|
||||||
|
probability: number;
|
||||||
|
weekdays: boolean;
|
||||||
|
weekends: boolean;
|
||||||
|
time: string;
|
||||||
|
confirm_delay: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
import { Notifications } from "@mantine/notifications";
|
import { Notifications } from "@mantine/notifications";
|
||||||
|
|
||||||
import "@mantine/core/styles.css";
|
import "@mantine/core/styles.css";
|
||||||
|
import "@mantine/dates/styles.css";
|
||||||
import "@mantine/notifications/styles.css";
|
import "@mantine/notifications/styles.css";
|
||||||
|
|
||||||
import { SubsList, subsListLoader } from "./SubsList";
|
import { SubsList, subsListLoader } from "./SubsList";
|
||||||
|
|
|
||||||
54
migrations/003_add_order_scheduling.py
Normal file
54
migrations/003_add_order_scheduling.py
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
"""Peewee migrations -- 003_add_order_scheduling.py.
|
||||||
|
|
||||||
|
Some examples (model - class or model name)::
|
||||||
|
|
||||||
|
> Model = migrator.orm['table_name'] # Return model in current state by name
|
||||||
|
> Model = migrator.ModelClass # Return model in current state by name
|
||||||
|
|
||||||
|
> migrator.sql(sql) # Run custom SQL
|
||||||
|
> migrator.run(func, *args, **kwargs) # Run python function with the given args
|
||||||
|
> migrator.create_model(Model) # Create a model (could be used as decorator)
|
||||||
|
> migrator.remove_model(model, cascade=True) # Remove a model
|
||||||
|
> migrator.add_fields(model, **fields) # Add fields to a model
|
||||||
|
> migrator.change_fields(model, **fields) # Change fields
|
||||||
|
> migrator.remove_fields(model, *field_names, cascade=True)
|
||||||
|
> migrator.rename_field(model, old_field_name, new_field_name)
|
||||||
|
> migrator.rename_table(model, new_table_name)
|
||||||
|
> migrator.add_index(model, *col_names, unique=False)
|
||||||
|
> migrator.add_not_null(model, *field_names)
|
||||||
|
> migrator.add_default(model, field_name, default)
|
||||||
|
> migrator.add_constraint(model, name, sql)
|
||||||
|
> migrator.drop_index(model, *col_names)
|
||||||
|
> migrator.drop_not_null(model, *field_names)
|
||||||
|
> migrator.drop_constraints(model, *constraints)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from contextlib import suppress
|
||||||
|
|
||||||
|
import peewee as pw
|
||||||
|
from peewee_migrate import Migrator
|
||||||
|
|
||||||
|
|
||||||
|
with suppress(ImportError):
|
||||||
|
import playhouse.postgres_ext as pw_pext
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
|
||||||
|
"""Write your migrations here."""
|
||||||
|
|
||||||
|
migrator.add_fields(
|
||||||
|
'orders_pool',
|
||||||
|
|
||||||
|
scheduled=pw.BooleanField(default=False),
|
||||||
|
probability=pw.FloatField(null=True),
|
||||||
|
weekdays=pw.BooleanField(null=True),
|
||||||
|
weekends=pw.BooleanField(null=True),
|
||||||
|
time=pw.TextField(null=True),
|
||||||
|
confirm_delay=pw.IntegerField(null=True))
|
||||||
|
|
||||||
|
|
||||||
|
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
|
||||||
|
"""Write your rollback migrations here."""
|
||||||
|
|
||||||
|
migrator.remove_fields('orders_pool', 'scheduled', 'probability', 'weekdays', 'weekends', 'time', 'confirm_delay')
|
||||||
Loading…
Reference in a new issue