1
This commit is contained in:
parent
c06629c9a2
commit
b345c22932
@ -4,6 +4,7 @@ from .endpoints import project
|
||||
from .endpoints import folder
|
||||
from .endpoints import space
|
||||
from .endpoints import dashboard
|
||||
from .endpoints import report
|
||||
|
||||
api_router = APIRouter()
|
||||
|
||||
@ -12,3 +13,4 @@ api_router.include_router(project.router, tags=["项目接口"], prefix='/projec
|
||||
api_router.include_router(folder.router, tags=["文件夹接口"], prefix='/folder')
|
||||
api_router.include_router(space.router, tags=["空间接口"], prefix='/space')
|
||||
api_router.include_router(dashboard.router, tags=["看板接口"], prefix='/dashboard')
|
||||
api_router.include_router(report.router, tags=["报表接口"], prefix='/report')
|
||||
|
@ -22,3 +22,63 @@ async def create(
|
||||
# todo 建默认文件夹
|
||||
|
||||
return schemas.Msg(code=0, msg='ok', detail='创建成功')
|
||||
|
||||
|
||||
@router.post("/delete")
|
||||
async def delete(
|
||||
data_in: schemas.DashboardDelete,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
# 删除Dashboard 自己创建的
|
||||
del_dashboard = await crud.dashboard.delete(db, _id=data_in.id, user_id=current_user.id)
|
||||
|
||||
if del_dashboard.deleted_count == 0:
|
||||
return schemas.Msg(code=-1, msg='error', detail='删除失败')
|
||||
return schemas.Msg(code=0, msg='ok', detail='删除成功')
|
||||
|
||||
|
||||
@router.post("/move")
|
||||
async def delete(
|
||||
data_in: schemas.DashboardMove,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
"""
|
||||
移动看板
|
||||
"""
|
||||
res = await crud.dashboard.update_one(db, id=data_in.source_id, cat=data_in.cat, pid=data_in.dest_id)
|
||||
if res.deleted_count == 0:
|
||||
return schemas.Msg(code=-1, msg='error', detail='删除失败')
|
||||
return schemas.Msg(code=0, msg='ok', detail='删除成功')
|
||||
|
||||
|
||||
@router.post("/add_report")
|
||||
async def add_report(data_in: schemas.AddReport,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
):
|
||||
res = await crud.dashboard.update_one(db, id=data_in.id, **{'$push': {'reports': {'$each': data_in.report_ids}}})
|
||||
return schemas.Msg(code=0, msg='ok', detail='ok')
|
||||
|
||||
|
||||
@router.post("/del_report")
|
||||
async def add_report(data_in: schemas.DelReport,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
):
|
||||
"""删除报表"""
|
||||
for item in data_in.report_ids:
|
||||
await crud.dashboard.update_one(db, id=data_in.id, **{'$pull': {'reports': item}})
|
||||
return schemas.Msg(code=0, msg='ok', detail='ok')
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def add_report(_id: str,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
):
|
||||
"""获取一个看板"""
|
||||
res = await crud.dashboard.get(db, id=_id)
|
||||
res['reports'] = await crud.report.find_many(db, **{'$in': {'_id': res.get('reports')}})
|
||||
return schemas.Msg(code=0, msg='ok', detail=res['reports'])
|
||||
|
@ -15,6 +15,7 @@ async def create(
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
"""创建文件夹"""
|
||||
try:
|
||||
await crud.folder.create(db, data_in, user_id=current_user.id)
|
||||
except pymongo.errors.DuplicateKeyError:
|
||||
@ -22,3 +23,19 @@ async def create(
|
||||
# todo 建默认文件夹
|
||||
|
||||
return schemas.Msg(code=0, msg='ok', detail='创建成功')
|
||||
|
||||
|
||||
@router.post("/delete")
|
||||
async def delete(
|
||||
data_in: schemas.FolderDelete,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
"""删除文件夹"""
|
||||
# 删除文件夹 自己创建的
|
||||
del_folder = await crud.folder.delete(db, _id=data_in.id, user_id=current_user.id)
|
||||
# 删除文件夹下的 dashboard
|
||||
del_dashboard = await crud.dashboard.delete(db, pid=data_in.id)
|
||||
if del_folder.deleted_count == 0:
|
||||
return schemas.Msg(code=-1, msg='error', detail='删除失败')
|
||||
return schemas.Msg(code=0, msg='ok', detail='删除成功')
|
||||
|
@ -16,6 +16,7 @@ async def create(
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
"""创建项目"""
|
||||
try:
|
||||
await crud.project.create(db, data_in, user_id=current_user.id)
|
||||
except pymongo.errors.DuplicateKeyError:
|
||||
@ -30,6 +31,7 @@ async def read_project(
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
):
|
||||
"""查看自己拥有的项目"""
|
||||
res = await crud.project.read_project(db, user_id=current_user.id)
|
||||
return res
|
||||
|
||||
@ -40,6 +42,7 @@ async def read_kanban(
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
):
|
||||
"""获取自己的看板"""
|
||||
res = {'kanban': [], 'space': []}
|
||||
# 我的看板
|
||||
kanban = await crud.folder.read_folder(db, project_id=data_in.id, user_id=current_user.id, cat='kanban')
|
||||
@ -80,14 +83,14 @@ async def read_kanban(
|
||||
'dashboards': [],
|
||||
})
|
||||
|
||||
for d in await crud.dashboard.find_many(db, pid=f['_id']):
|
||||
for d in await crud.dashboard.find_many(db, pid=f['_id']):
|
||||
res['space'][-1]['folders'][-1]['dashboards'].append({
|
||||
'name': d['name'],
|
||||
'_id': d['_id']
|
||||
})
|
||||
|
||||
# 空间 看板
|
||||
for d in await crud.dashboard.find_many(db, pid=item['_id']):
|
||||
for d in await crud.dashboard.find_many(db, pid=item['_id']):
|
||||
res['space'][-1]['dashboards'].append({
|
||||
'name': d['name'],
|
||||
'_id': d['_id']
|
||||
|
52
api/api_v1/endpoints/report.py
Normal file
52
api/api_v1/endpoints/report.py
Normal file
@ -0,0 +1,52 @@
|
||||
from typing import Any
|
||||
|
||||
import pymongo
|
||||
from fastapi import APIRouter, Depends
|
||||
from motor.motor_asyncio import AsyncIOMotorDatabase
|
||||
import crud, schemas
|
||||
|
||||
from db import get_database
|
||||
from api import deps
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/create")
|
||||
async def create(
|
||||
data_in: schemas.ReportCreate,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
"""新建报表"""
|
||||
try:
|
||||
await crud.report.create(db, data_in, user_id=current_user.id)
|
||||
except pymongo.errors.DuplicateKeyError:
|
||||
return schemas.Msg(code=-1, msg='error', detail='报表已存在')
|
||||
|
||||
return schemas.Msg(code=0, msg='ok', detail='创建成功')
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def read_report(
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> Any:
|
||||
"""获取已建报表"""
|
||||
|
||||
res = await crud.report.read_report(db, user_id=current_user.id)
|
||||
return res
|
||||
|
||||
|
||||
@router.post("/delete")
|
||||
async def delete(
|
||||
data_in: schemas.ReportDelete,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
"""删除报表"""
|
||||
# 删除Report 自己创建的
|
||||
del_report = await crud.report.delete(db, _id=data_in.id, user_id=current_user.id)
|
||||
|
||||
if del_report.deleted_count == 0:
|
||||
return schemas.Msg(code=-1, msg='error', detail='删除失败')
|
||||
return schemas.Msg(code=0, msg='ok', detail='删除成功')
|
@ -15,6 +15,7 @@ async def create(
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
"""创建空间"""
|
||||
try:
|
||||
await crud.space.create(db, data_in, user_id=current_user.id)
|
||||
except pymongo.errors.DuplicateKeyError:
|
||||
@ -22,3 +23,27 @@ async def create(
|
||||
# todo 建默认文件夹
|
||||
|
||||
return schemas.Msg(code=0, msg='ok', detail='创建成功')
|
||||
|
||||
|
||||
@router.post("/delete")
|
||||
async def delete(
|
||||
data_in: schemas.SpaceDelete,
|
||||
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||
) -> schemas.Msg:
|
||||
"""删除空间"""
|
||||
# 删除空间 自己创建的
|
||||
del_space = await crud.space.delete(db, _id=data_in.id, user_id=current_user.id)
|
||||
# 删除文件夹
|
||||
del_folder = await crud.folder.find_many(db, pid=data_in.id)
|
||||
del_folder_ids = [f['_id'] for f in del_folder]
|
||||
await crud.folder.delete(db, pid=data_in.id)
|
||||
# 删除文件夹下的 dashboard
|
||||
await crud.dashboard.delete(db, **{'$in': {'_id': del_folder_ids}})
|
||||
|
||||
# 删除空间下的 dashboard
|
||||
await crud.dashboard.delete(db, pid=data_in.id)
|
||||
|
||||
if del_space.deleted_count == 0:
|
||||
return schemas.Msg(code=-1, msg='error', detail='删除失败')
|
||||
return schemas.Msg(code=0, msg='ok', detail='删除成功')
|
||||
|
@ -3,3 +3,4 @@ from .crud_project import project
|
||||
from .crud_folder import folder
|
||||
from .crud_space import space
|
||||
from .crud_dashboard import dashboard
|
||||
from .crud_report import report
|
||||
|
16
crud/base.py
16
crud/base.py
@ -1,3 +1,5 @@
|
||||
from typing import Union
|
||||
|
||||
from bson import ObjectId
|
||||
|
||||
|
||||
@ -5,15 +7,21 @@ class CRUDBase:
|
||||
def __init__(self, coll_name):
|
||||
self.coll_name = coll_name
|
||||
|
||||
async def get(self, coll, id: ObjectId):
|
||||
return await coll.find_one({'_id': id})
|
||||
async def get(self, db, id: Union[ObjectId, str]):
|
||||
return (await db[self.coll_name].find_one({'_id': ObjectId(id)})) or dict()
|
||||
|
||||
async def read_have(self, coll, user_id: str, **kwargs):
|
||||
async def read_have(self, db, user_id: str, **kwargs):
|
||||
where = {'members': user_id}
|
||||
where.update(kwargs)
|
||||
cursor = coll.find(where)
|
||||
cursor = db[self.coll_name].find(where)
|
||||
return await cursor.to_list(length=999)
|
||||
|
||||
async def find_many(self, db, **kwargs):
|
||||
cursor = db[self.coll_name].find(kwargs)
|
||||
return await cursor.to_list(length=999)
|
||||
|
||||
async def delete(self, db, **kwargs):
|
||||
return await db[self.coll_name].delete_many(kwargs)
|
||||
|
||||
async def update_one(self, db, id, **kwargs):
|
||||
return await db[self.coll_name].update_one({'_id': id}, kwargs)
|
||||
|
@ -19,7 +19,7 @@ class CRUDFolder(CRUDBase):
|
||||
await db[self.coll_name].insert_one(db_obj.dict(by_alias=True))
|
||||
|
||||
async def read_folder(self, db, user_id, project_id, cat):
|
||||
return await self.read_have(db[self.coll_name], user_id=user_id, project_id=project_id, cat=cat)
|
||||
return await self.read_have(db, user_id=user_id, project_id=project_id, cat=cat)
|
||||
|
||||
async def create_index(self, db: AsyncIOMotorDatabase):
|
||||
await db[self.coll_name].create_index(
|
||||
|
@ -16,7 +16,7 @@ class CRUDProject(CRUDBase):
|
||||
await db[self.coll_name].insert_one(db_obj.dict(by_alias=True))
|
||||
|
||||
async def read_project(self, db: AsyncIOMotorDatabase, user_id: str):
|
||||
return await self.read_have(db[self.coll_name], user_id=user_id)
|
||||
return await self.read_have(db, user_id=user_id)
|
||||
|
||||
async def create_index(self, db: AsyncIOMotorDatabase):
|
||||
await db[self.coll_name].create_index('name', unique=True)
|
||||
|
30
crud/crud_report.py
Normal file
30
crud/crud_report.py
Normal file
@ -0,0 +1,30 @@
|
||||
import pymongo
|
||||
from motor.motor_asyncio import AsyncIOMotorDatabase
|
||||
|
||||
from crud.base import CRUDBase
|
||||
from schemas import *
|
||||
|
||||
__all__ = 'report',
|
||||
|
||||
|
||||
class CRUDReport(CRUDBase):
|
||||
|
||||
async def create(self, db: AsyncIOMotorDatabase, obj_in: ReportCreate, user_id: str):
|
||||
db_obj = ReportDB(
|
||||
**obj_in.dict(), user_id=user_id,
|
||||
_id=uuid.uuid1().hex
|
||||
|
||||
)
|
||||
await db[self.coll_name].insert_one(db_obj.dict(by_alias=True))
|
||||
|
||||
async def create_index(self, db: AsyncIOMotorDatabase):
|
||||
await db[self.coll_name].create_index(
|
||||
[('project_id', pymongo.DESCENDING), ('name', pymongo.DESCENDING), ('user_id', pymongo.DESCENDING)],
|
||||
unique=True)
|
||||
|
||||
async def read_report(self, db, user_id):
|
||||
res = await self.read_have(db, user_id)
|
||||
return res
|
||||
|
||||
|
||||
report = CRUDReport('report')
|
@ -19,7 +19,7 @@ class CRUDSpace(CRUDBase):
|
||||
await db[self.coll_name].insert_one(db_obj.dict(by_alias=True))
|
||||
|
||||
async def read_space(self, db, user_id, project_id):
|
||||
return await self.read_have(db[self.coll_name], user_id=user_id, project_id=project_id)
|
||||
return await self.read_have(db, user_id=user_id, project_id=project_id)
|
||||
|
||||
async def create_index(self, db: AsyncIOMotorDatabase):
|
||||
await db[self.coll_name].create_index(
|
||||
|
@ -38,6 +38,9 @@ async def space_index():
|
||||
async def dashboard_index():
|
||||
await crud.dashboard.create_index(db)
|
||||
|
||||
async def report_index():
|
||||
await crud.report.create_index(db)
|
||||
|
||||
|
||||
async def main():
|
||||
await create_superuser()
|
||||
@ -45,6 +48,7 @@ async def main():
|
||||
await folder_index()
|
||||
await space_index()
|
||||
await dashboard_index()
|
||||
await report_index()
|
||||
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
2
main.py
2
main.py
@ -24,4 +24,4 @@ from api.api_v1.api import api_router
|
||||
app.include_router(api_router, prefix=settings.API_V1_STR)
|
||||
|
||||
if __name__ == '__main__':
|
||||
uvicorn.run(app='main:app', host="127.0.0.1", port=8889, reload=True, debug=True)
|
||||
uvicorn.run(app='main:app', host="0.0.0.0", port=8889, reload=True, debug=True)
|
||||
|
@ -4,3 +4,4 @@ from .project import *
|
||||
from .folder import *
|
||||
from .space import *
|
||||
from .dashboard import *
|
||||
from .report import *
|
@ -19,9 +19,30 @@ class DashboardCreate(DashboardBase):
|
||||
# cat: str
|
||||
pid: str
|
||||
|
||||
|
||||
class DashboardDelete(DBBase):
|
||||
pass
|
||||
|
||||
|
||||
class Category(str, Enum):
|
||||
project = 'kanban'
|
||||
space = 'space'
|
||||
|
||||
|
||||
class DashboardMove(BaseModel):
|
||||
source_id: str
|
||||
dest_id: str
|
||||
cat: Category
|
||||
|
||||
|
||||
class AddReport(DBBase):
|
||||
report_ids: List[str]
|
||||
|
||||
|
||||
class DelReport(DBBase):
|
||||
report_ids: List[str]
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# 数据库模型
|
||||
class DashboardDB(DBBase):
|
||||
@ -29,5 +50,6 @@ class DashboardDB(DBBase):
|
||||
user_id: str
|
||||
project_id: str
|
||||
# cat: Category
|
||||
reports: List[str] = []
|
||||
pid: str
|
||||
create_date: datetime = datetime.now()
|
||||
|
@ -20,6 +20,10 @@ class FolderCreate(FolderBase):
|
||||
pid: str
|
||||
|
||||
|
||||
class FolderDelete(DBBase):
|
||||
pass
|
||||
|
||||
|
||||
class Category(str, Enum):
|
||||
project = 'kanban'
|
||||
space = 'space'
|
||||
|
@ -2,7 +2,7 @@ import uuid
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from schemas import DBBase
|
||||
|
||||
@ -13,7 +13,7 @@ class ProjectBase(BaseModel):
|
||||
|
||||
# 解析请求json 创建项目
|
||||
class ProjectCreate(ProjectBase):
|
||||
name: str
|
||||
name: str = Field(..., title='项目名')
|
||||
|
||||
|
||||
# 查询某个项目看板
|
||||
|
36
schemas/report.py
Normal file
36
schemas/report.py
Normal file
@ -0,0 +1,36 @@
|
||||
import json
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import List
|
||||
|
||||
from pydantic import BaseModel, validator, Json
|
||||
|
||||
from schemas import DBBase
|
||||
|
||||
|
||||
class ReportBase(BaseModel):
|
||||
name: str = None
|
||||
query: str = None
|
||||
project_id: str = None
|
||||
|
||||
|
||||
class ReportCreate(ReportBase):
|
||||
name: str
|
||||
project_id: str
|
||||
query: Json
|
||||
|
||||
|
||||
class ReportDelete(DBBase):
|
||||
pass
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# 数据库模型
|
||||
class ReportDB(DBBase):
|
||||
name: str
|
||||
user_id: str
|
||||
project_id: str
|
||||
# cat: Category
|
||||
pid: str
|
||||
create_date: datetime = datetime.now()
|
@ -18,6 +18,10 @@ class SpaceCreate(SpaceBase):
|
||||
project_id: str
|
||||
|
||||
|
||||
class SpaceDelete(DBBase):
|
||||
pass
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# 数据库模型
|
||||
class SpaceDB(DBBase):
|
||||
|
Loading…
Reference in New Issue
Block a user