Subs List - UI improvements
This commit is contained in:
parent
3fea0a5a1b
commit
3445b7b0ff
6 changed files with 110 additions and 14 deletions
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -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.")
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
49
migrations/004_add_user_photo_url.py
Normal file
49
migrations/004_add_user_photo_url.py
Normal 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')
|
||||||
Loading…
Reference in a new issue