completely useless tap logic
This commit is contained in:
@ -26,6 +26,7 @@ class News(Base):
|
|||||||
title = Column(String)
|
title = Column(String)
|
||||||
content = Column(String)
|
content = Column(String)
|
||||||
created = Column(DateTime, default=datetime.datetime.utcnow)
|
created = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
|
taps = Column(Integer, default=0)
|
||||||
|
|
||||||
|
|
||||||
class AnonymousUser(Base):
|
class AnonymousUser(Base):
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Annotated, Union
|
from typing import Annotated, Union
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, status
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
from fastapi.security import OAuth2PasswordRequestForm
|
from fastapi.security import OAuth2PasswordRequestForm
|
||||||
@ -39,3 +40,12 @@ async def create_news(
|
|||||||
db: Annotated[Session, Depends(get_db)],
|
db: Annotated[Session, Depends(get_db)],
|
||||||
) -> schemas.NewsInDb:
|
) -> schemas.NewsInDb:
|
||||||
return services.create_news(news=news, current_user=current_user, db=db)
|
return services.create_news(news=news, current_user=current_user, db=db)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{news_id}/tap")
|
||||||
|
async def create_news(
|
||||||
|
news_id: UUID,
|
||||||
|
db: Annotated[Session, Depends(get_db)],
|
||||||
|
) -> schemas.TapResponse:
|
||||||
|
services.tap_news(news_id=news_id, db=db)
|
||||||
|
return schemas.TapResponse(tap="ok")
|
||||||
|
|||||||
@ -13,6 +13,7 @@ class News(BaseModel):
|
|||||||
title: str
|
title: str
|
||||||
content: str
|
content: str
|
||||||
created: datetime
|
created: datetime
|
||||||
|
taps: int
|
||||||
|
|
||||||
|
|
||||||
class NewsInDb(News):
|
class NewsInDb(News):
|
||||||
@ -20,3 +21,7 @@ class NewsInDb(News):
|
|||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|
||||||
|
|
||||||
|
class TapResponse(BaseModel):
|
||||||
|
tap: str
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from fastapi import Depends, HTTPException
|
from fastapi import Depends, HTTPException, status
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from ...dependencies import get_db
|
from ...dependencies import get_db
|
||||||
from ...db import models
|
from ...db import models
|
||||||
@ -35,3 +36,15 @@ def create_news(
|
|||||||
detail="Could not validate credentials",
|
detail="Could not validate credentials",
|
||||||
headers={"WWW-Authenticate": "Bearer"},
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def tap_news(news_id: UUID, db: Session):
|
||||||
|
n = db.query(models.News).filter(models.News.id == news_id).first()
|
||||||
|
if n:
|
||||||
|
setattr(n, "taps", n.taps + 1)
|
||||||
|
db.commit()
|
||||||
|
return
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="Not found",
|
||||||
|
)
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import "../styles.css";
|
import "../styles.css";
|
||||||
import { Card, Spin } from "antd";
|
import { Button, Card, Spin } from "antd";
|
||||||
import { News, useGetNewsQuery } from "../../slice/NewsApi";
|
import { News, useGetNewsQuery, useTapNewsMutation } from "../../slice/NewsApi";
|
||||||
import { ClockCircleOutlined } from "@ant-design/icons";
|
import { ClockCircleOutlined, FireOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
const formatTime = (s: string) => {
|
const formatTime = (s: string) => {
|
||||||
const d = new Date(s + "Z");
|
const d = new Date(s + "Z");
|
||||||
@ -10,7 +10,8 @@ const formatTime = (s: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NewsListCard = (): JSX.Element => {
|
const NewsListCard = (): JSX.Element => {
|
||||||
const { data, isLoading } = useGetNewsQuery({});
|
const { data, refetch, isLoading } = useGetNewsQuery({});
|
||||||
|
const [tapNews] = useTapNewsMutation();
|
||||||
return (
|
return (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<Spin spinning={isLoading}>
|
<Spin spinning={isLoading}>
|
||||||
@ -25,17 +26,48 @@ const NewsListCard = (): JSX.Element => {
|
|||||||
<p
|
<p
|
||||||
style={{
|
style={{
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
color: "#ffffff",
|
|
||||||
whiteSpace: "break-spaces",
|
whiteSpace: "break-spaces",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{news.content}
|
{news.content}
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<div className="news-footer">
|
<div
|
||||||
|
className="news-footer"
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ClockCircleOutlined />
|
<ClockCircleOutlined />
|
||||||
<br />
|
<br />
|
||||||
<p style={{ marginLeft: "1rem" }}>{formatTime(news.created)}</p>
|
<p style={{ marginLeft: "1rem" }}>
|
||||||
|
{formatTime(news.created)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "100% !important",
|
||||||
|
display: "flex",
|
||||||
|
flexFlow: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
icon={<FireOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
tapNews(news.id);
|
||||||
|
refetch();
|
||||||
|
}}
|
||||||
|
>{` ${news.taps}`}</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -1,15 +1,11 @@
|
|||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
import {
|
import { useGetQueueDetailQuery } from "../../slice/QueueApi";
|
||||||
useGetQueueDetailQuery,
|
|
||||||
useGetQueuesQuery,
|
|
||||||
} from "../../slice/QueueApi";
|
|
||||||
import "../styles.css";
|
import "../styles.css";
|
||||||
import { Button, Spin } from "antd";
|
import { Button, Spin } from "antd";
|
||||||
import {
|
import {
|
||||||
ArrowUpOutlined,
|
ArrowUpOutlined,
|
||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
LoadingOutlined,
|
LoadingOutlined,
|
||||||
PlusCircleOutlined,
|
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import Title from "antd/es/typography/Title";
|
import Title from "antd/es/typography/Title";
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export type News = {
|
|||||||
title: string;
|
title: string;
|
||||||
content: string;
|
content: string;
|
||||||
created: string;
|
created: string;
|
||||||
|
taps: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NewsApi = createApi({
|
export const NewsApi = createApi({
|
||||||
@ -30,6 +31,12 @@ export const NewsApi = createApi({
|
|||||||
getNews: builder.query({
|
getNews: builder.query({
|
||||||
query: () => "/",
|
query: () => "/",
|
||||||
}),
|
}),
|
||||||
|
tapNews: builder.mutation({
|
||||||
|
query: (newsId: string) => ({
|
||||||
|
url: `/${newsId}/tap`,
|
||||||
|
method: "POST",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
createNews: builder.mutation({
|
createNews: builder.mutation({
|
||||||
query: (data: CreateNewsRequest) => ({
|
query: (data: CreateNewsRequest) => ({
|
||||||
url: "/",
|
url: "/",
|
||||||
@ -40,4 +47,5 @@ export const NewsApi = createApi({
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { useGetNewsQuery, useCreateNewsMutation } = NewsApi;
|
export const { useGetNewsQuery, useTapNewsMutation, useCreateNewsMutation } =
|
||||||
|
NewsApi;
|
||||||
|
|||||||
Reference in New Issue
Block a user