This commit is contained in:
wuaho 2021-05-06 13:04:58 +08:00
parent c06629c9a2
commit b345c22932
20 changed files with 281 additions and 12 deletions

View File

@ -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')

View File

@ -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'])

View File

@ -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='删除成功')

View File

@ -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']

View 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='删除成功')

View File

@ -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='删除成功')

View File

@ -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

View File

@ -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)

View File

@ -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(

View File

@ -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
View 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')

View File

@ -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(

View File

@ -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()

View File

@ -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)

View File

@ -4,3 +4,4 @@ from .project import *
from .folder import *
from .space import *
from .dashboard import *
from .report import *

View File

@ -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()

View File

@ -20,6 +20,10 @@ class FolderCreate(FolderBase):
pid: str
class FolderDelete(DBBase):
pass
class Category(str, Enum):
project = 'kanban'
space = 'space'

View File

@ -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
View 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()

View File

@ -18,6 +18,10 @@ class SpaceCreate(SpaceBase):
project_id: str
class SpaceDelete(DBBase):
pass
# --------------------------------------------------------------
# 数据库模型
class SpaceDB(DBBase):