Subs List - UI improvements

This commit is contained in:
Johnny Gear 2026-01-30 14:58:37 -06:00
parent 3fea0a5a1b
commit 3445b7b0ff
6 changed files with 110 additions and 14 deletions

View file

@ -13,6 +13,7 @@ class BaseModel(Model):
class User(BaseModel): class User(BaseModel):
telegram_username = TextField(unique=True) telegram_username = TextField(unique=True)
telegram_chat_id = IntegerField() telegram_chat_id = IntegerField()
telegram_photo_url = TextField(null=True)
class Meta: class Meta:
table_name = 'user' table_name = 'user'

View file

@ -10,7 +10,10 @@ api = Blueprint('api', __name__)
def subs(): def subs():
return jsonify( return jsonify(
[ [
{"sub_username": dsu.sub.telegram_username} {
"sub_username": dsu.sub.telegram_username,
"telegram_photo_url": dsu.sub.telegram_photo_url
}
for dsu for dsu
in domsubusers_list(current_user.db_user) in domsubusers_list(current_user.db_user)
] ]

View file

@ -84,6 +84,9 @@ def login():
if hmac_string == tg_data['hash']: if hmac_string == tg_data['hash']:
try: try:
db_user = user_get(tg_data['username']) db_user = user_get(tg_data['username'])
db_user.telegram_photo_url = request.args.get("photo_url")
db_user.save()
login_user(FlaskUser(db_user)) login_user(FlaskUser(db_user))
except: except:
flash("Login failed. Please try again.") flash("Login failed. Please try again.")

View file

@ -2,7 +2,13 @@ import { Container, Title, Card, Text, Box, Flex, Badge } from "@mantine/core";
import { TimeValue } from "@mantine/dates"; import { TimeValue } from "@mantine/dates";
import { IconPencil, IconPlus, IconTrash } from "@tabler/icons-react"; import { IconPencil, IconPlus, IconTrash } from "@tabler/icons-react";
import React from "react"; import React from "react";
import { Params, useLoaderData, useParams, useFetcher } from "react-router"; import {
Params,
useLoaderData,
useParams,
useFetcher,
Link,
} from "react-router";
import { ConfirmDialogButton } from "./ConfirmDialogButton"; import { ConfirmDialogButton } from "./ConfirmDialogButton";
import { NavigateButton } from "./NavigateButton"; import { NavigateButton } from "./NavigateButton";
@ -36,9 +42,10 @@ export const SubOrderSets: React.FC = () => {
return ( return (
<Container> <Container>
<Title order={1} mb="lg"> <Box mb="lg">
Order Sets for {sub_username} <Title order={1}>Order Sets for {sub_username}</Title>
</Title> <Link to={`/dashboard/`}>Return to all subs</Link>
</Box>
<Flex gap="md" wrap="wrap"> <Flex gap="md" wrap="wrap">
{orderSets {orderSets
? orderSets.map( ? orderSets.map(

View file

@ -1,21 +1,54 @@
import React from "react"; import React from "react";
import { Container } from "@mantine/core"; import { Container, Text, Title, Flex, Card, Image } from "@mantine/core";
import { useLoaderData, Link } from "react-router"; import { useLoaderData } from "react-router";
import { IconPencil } from "@tabler/icons-react";
import { NavigateButton } from "./NavigateButton";
export const subsListLoader = () => export const subsListLoader = () =>
fetch("/api/subs").then((response) => response.json()); fetch("/api/subs").then((response) => response.json());
export const SubsList: React.FC = () => { export const SubsList: React.FC = () => {
const subs = useLoaderData<{ sub_username: string }[]>(); const subs =
useLoaderData<{ sub_username: string; telegram_photo_url: string }[]>();
return ( return (
<Container> <Container>
<h1>Subs</h1> <Title order={1} mb="lg">
{subs.map(({ sub_username }) => ( Subs
<Link key={sub_username} to={`/dashboard/subs/${sub_username}`}> </Title>
Orders for {sub_username} <Flex gap="md" wrap="wrap">
</Link> {subs.map(({ sub_username, telegram_photo_url }) => (
))} <Card
key={sub_username}
shadow="sm"
padding="lg"
radius="md"
withBorder
bg="gray.2"
w="320px"
>
{telegram_photo_url ? (
<Card.Section>
<Image
src={telegram_photo_url}
height={280}
alt={`Profile picture for ${sub_username}`}
/>
</Card.Section>
) : null}
<Flex direction="column" gap="md" mt="md" h="100%">
<Text fw={500}>{sub_username}</Text>
<Flex gap="md" justify="end">
<NavigateButton to={`/dashboard/subs/${sub_username}`}>
<IconPencil style={{ marginRight: "0.5rem" }} />
Edit
</NavigateButton>
</Flex>
</Flex>
</Card>
))}
</Flex>
</Container> </Container>
); );
}; };

View file

@ -0,0 +1,49 @@
"""Peewee migrations -- 004_add_user_photo_url.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(
'user',
telegram_photo_url=pw.TextField(null=True))
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
migrator.remove_fields('user', 'telegram_photo_url')