participantlist works!
This commit is contained in:
@ -78,7 +78,7 @@ async def read_users_me(
|
||||
|
||||
|
||||
@router.get("/anon")
|
||||
async def get_qnon_user(
|
||||
async def get_anon_user(
|
||||
anon_user: Annotated[schemas.AnonUser, Depends(services.get_anon_user)]
|
||||
) -> schemas.AnonUser:
|
||||
return anon_user
|
||||
|
||||
@ -5,7 +5,7 @@ from uuid import UUID
|
||||
import redis
|
||||
import asyncio
|
||||
|
||||
from ...dependencies import get_db, get_pubsub
|
||||
from ...dependencies import get_db, get_pubsub, get_redis
|
||||
from ...db import models
|
||||
|
||||
from ..auth import services as auth_services
|
||||
@ -43,7 +43,6 @@ def get_detailed_queue(
|
||||
db: Annotated[Session, Depends(get_db)],
|
||||
) -> schemas.QueueDetail:
|
||||
q = db.query(models.Queue).filter(models.Queue.id == queue_id).first()
|
||||
print("\n\n", queue_id, "\n\n", flush=True)
|
||||
if q:
|
||||
return schemas.QueueDetail(
|
||||
id=q.id,
|
||||
@ -63,10 +62,11 @@ def get_detailed_queue(
|
||||
)
|
||||
|
||||
|
||||
def join_queue(
|
||||
async def join_queue(
|
||||
queue_id: UUID,
|
||||
client: Annotated[auth_schemas.AnonUser, Depends(auth_services.get_anon_user)],
|
||||
db: Annotated[Session, Depends(get_db)],
|
||||
r: Annotated[redis.client.Redis, Depends(get_redis)],
|
||||
) -> schemas.QueueUser:
|
||||
q = get_queue_by_id(queue_id, db)
|
||||
if q:
|
||||
@ -78,6 +78,7 @@ def join_queue(
|
||||
)
|
||||
db.add(new_qu)
|
||||
db.commit()
|
||||
await r.publish(str(queue_id), "updated")
|
||||
return new_qu
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
@ -96,9 +97,8 @@ async def set_queue_listener(
|
||||
) -> schemas.QueueDetail:
|
||||
await ps.subscribe(str(queue_id))
|
||||
async for m in ps.listen():
|
||||
print(m, flush=True)
|
||||
if m.get("data", None) == b"updated":
|
||||
print("UPDATED", flush=True)
|
||||
break
|
||||
await ps.unsubscribe()
|
||||
new_queue = get_detailed_queue(queue_id=queue_id, db=db)
|
||||
return new_queue
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useContext } from "react";
|
||||
import "../styles.css";
|
||||
import { Button, Divider, Input, Spin } from "antd";
|
||||
import { Button, Spin } from "antd";
|
||||
import {
|
||||
ArrowLeftOutlined,
|
||||
CameraOutlined,
|
||||
FileTextOutlined,
|
||||
PlusOutlined,
|
||||
UserOutlined,
|
||||
@ -11,13 +10,34 @@ import {
|
||||
import Title from "antd/es/typography/Title";
|
||||
import tr from "../../config/translation";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useGetQueueDetailQuery } from "../../slice/QueueApi";
|
||||
import {
|
||||
useGetQueueDetailQuery,
|
||||
useJoinQueueMutation,
|
||||
} from "../../slice/QueueApi";
|
||||
import { MessageContext } from "../../App";
|
||||
|
||||
const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
|
||||
const navigate = useNavigate();
|
||||
const { data, isFetching, isError } = useGetQueueDetailQuery(props.id, {
|
||||
const messageApi = useContext(MessageContext);
|
||||
|
||||
const { data, refetch, isFetching, isError } = useGetQueueDetailQuery(
|
||||
props.id,
|
||||
{
|
||||
skip: !props.id,
|
||||
});
|
||||
}
|
||||
);
|
||||
const [joinQueue, { isLoading }] = useJoinQueueMutation();
|
||||
|
||||
const onJoinButtonClick = () => {
|
||||
joinQueue(props.id)
|
||||
.unwrap()
|
||||
.then(() =>
|
||||
messageApi.success(tr("Successfully joined queue ") + data.name)
|
||||
)
|
||||
.then(() => navigate(`/queue/${props.id}`))
|
||||
.then(() => refetch())
|
||||
.catch((e) => messageApi.error(tr(e.data.detail)));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
@ -48,7 +68,11 @@ const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
|
||||
{" "}
|
||||
{data?.participants?.remaining} / {data?.participants?.total}
|
||||
</p>
|
||||
<Button icon={<PlusOutlined />}>{tr("Join")}</Button>
|
||||
<Spin spinning={isLoading}>
|
||||
<Button icon={<PlusOutlined />} onClick={onJoinButtonClick}>
|
||||
{tr("Join")}
|
||||
</Button>
|
||||
</Spin>
|
||||
</div>
|
||||
)}
|
||||
</Spin>
|
||||
|
||||
@ -13,11 +13,15 @@ import tr from "../../config/translation";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import { StorePrototype } from "../../config/store";
|
||||
import AnonUserCard from "../user/AnonUserCard";
|
||||
|
||||
const QueueCard = (): JSX.Element => {
|
||||
const user = useSelector((state: StorePrototype) => state.auth.user);
|
||||
const { queueId } = useParams();
|
||||
const { data, isFetching } = useGetQueueDetailQuery(queueId);
|
||||
const { data, isFetching } = useGetQueueDetailQuery(queueId, {
|
||||
skip: !queueId,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<Spin
|
||||
@ -39,6 +43,14 @@ const QueueCard = (): JSX.Element => {
|
||||
{data?.participants?.remaining} / {data?.participants?.total}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<Title level={3} style={{ textAlign: "left" }}>
|
||||
{tr("Queue participants")}
|
||||
</Title>
|
||||
{data?.participants.users_list.map((v) => {
|
||||
return <AnonUserCard key={v.id} user={v} />;
|
||||
})}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -101,3 +101,25 @@
|
||||
.queue-info > * {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.anon-circle {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.anon-card {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
animation: 0.3s ease-out 0s 1 cardPopup;
|
||||
background: #001d39;
|
||||
margin-top: 0.5rem;
|
||||
margin-right: 1rem;
|
||||
margin-left: 1rem;
|
||||
border-radius: 10px;
|
||||
padding: 1rem;
|
||||
border: 2px solid #00d8a4;
|
||||
}
|
||||
|
||||
@ -1,7 +1,45 @@
|
||||
import React from "react";
|
||||
import { AnonUser } from "../../slice/AuthApi";
|
||||
import "../styles.css";
|
||||
import tr from "../../config/translation";
|
||||
import Title from "antd/es/typography/Title";
|
||||
import Paragraph from "antd/es/typography/Paragraph";
|
||||
|
||||
const UUIDToColor = (uuid: string): string => {};
|
||||
|
||||
const AnonUserCard = (): JSX.Element => {
|
||||
return;
|
||||
const UUIDToColor = (uuid: string): string => {
|
||||
return (
|
||||
"#" +
|
||||
uuid.split("-").reduce((store: string, v: string) => {
|
||||
return store + v.substring(0, 1);
|
||||
}, "") +
|
||||
uuid.substring(uuid.length - 1)
|
||||
);
|
||||
};
|
||||
|
||||
const getProfileText = (name: string): string => {
|
||||
return name.substring(0, 1);
|
||||
};
|
||||
|
||||
const AnonUserCard = (props: {
|
||||
user: AnonUser;
|
||||
backlight?: "self" | "active" | undefined;
|
||||
}): JSX.Element => {
|
||||
return (
|
||||
<div className="anon-card">
|
||||
<div
|
||||
className="anon-circle"
|
||||
style={{ background: UUIDToColor(props.user.id) }}
|
||||
>
|
||||
{props.user.name
|
||||
? getProfileText(props.user.name)
|
||||
: props.user.id.substring(0, 2)}
|
||||
</div>
|
||||
<p color="white" style={{ marginLeft: "10px" }}>
|
||||
{props.user.name
|
||||
? props.user.name
|
||||
: tr("Anonymous") + " #" + props.user.id.substring(0, 4)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnonUserCard;
|
||||
|
||||
@ -24,6 +24,11 @@ export type TokenResponse = {
|
||||
token_type: string;
|
||||
};
|
||||
|
||||
export type AnonUser = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export const AuthApi = createApi({
|
||||
reducerPath: "AuthApi",
|
||||
baseQuery: fetchBaseQuery({
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
|
||||
import { baseUrl } from "../config/baseUrl";
|
||||
import { RootState } from "../config/store";
|
||||
import { AnonUser } from "./AuthApi";
|
||||
|
||||
export type CreateQueueRequest = {
|
||||
name: string;
|
||||
@ -13,6 +14,17 @@ export type Queue = {
|
||||
description: string | null;
|
||||
};
|
||||
|
||||
export type QueueDetail = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
participants: {
|
||||
total: number;
|
||||
remaining: number;
|
||||
users_list: [AnonUser];
|
||||
};
|
||||
};
|
||||
|
||||
export const QueueApi = createApi({
|
||||
reducerPath: "QueueApi",
|
||||
baseQuery: fetchBaseQuery({
|
||||
@ -30,14 +42,14 @@ export const QueueApi = createApi({
|
||||
},
|
||||
}),
|
||||
endpoints: (builder) => ({
|
||||
getQueues: builder.query({
|
||||
getQueues: builder.query<[Queue], undefined>({
|
||||
query: () => "/",
|
||||
}),
|
||||
getQueueDetail: builder.query({
|
||||
getQueueDetail: builder.query<QueueDetail, string | undefined>({
|
||||
query: (queueId: string | undefined) => `/${queueId}`,
|
||||
}),
|
||||
joinQueue: builder.mutation({
|
||||
query: (queueId: string) => `/${queueId}/join`,
|
||||
query: (queueId: string) => ({ url: `/${queueId}/join`, method: "POST" }),
|
||||
}),
|
||||
createQueue: builder.mutation({
|
||||
query: (data: CreateQueueRequest) => ({
|
||||
@ -52,5 +64,6 @@ export const QueueApi = createApi({
|
||||
export const {
|
||||
useGetQueuesQuery,
|
||||
useGetQueueDetailQuery,
|
||||
useJoinQueueMutation,
|
||||
useCreateQueueMutation,
|
||||
} = QueueApi;
|
||||
|
||||
Reference in New Issue
Block a user