Prechádzať zdrojové kódy

add time, menbership in User and Videos

tomoya 2 rokov pred
rodič
commit
8f53d5d59f

+ 45 - 0
backend/app/app/api/api_v1/endpoints/videos.py

@@ -0,0 +1,45 @@
+from typing import Any, List
+
+from fastapi import APIRouter, Depends, HTTPException
+from sqlalchemy.orm import Session
+
+import app.crud as crud
+import app.models as models
+import app.schemas as schemas 
+from app.api import deps
+
+router = APIRouter()
+
+@router.get("/", response_model=List[schemas.Video])
+def read_items(
+    db: Session = Depends(deps.get_db),
+    skip: int = 0,
+    limit: int = 100,
+    current_user: models.User = Depends(deps.get_current_active_user),
+) -> Any:
+    """
+    Retrieve items.
+    """
+    if crud.user.is_superuser(current_user):
+        items = crud.item.get_multi(db, skip=skip, limit=limit)
+    else:
+        items = crud.item.get_multi_by_owner(
+            db=db, owner_id=current_user.id, skip=skip, limit=limit
+        )
+    return items
+
+@router.post("/", response_model=schemas.Item)
+def create_item(
+    *,
+    db: Session = Depends(deps.get_db),
+    video_upload: schemas.VideoUpload,
+    current_user: models.User = Depends(deps.get_current_active_user),
+) -> Any:
+    """
+    Create new video.
+    """
+    video_create = schemas.VideoCreate
+    video_create.title = video_upload.title
+    video_create.progress = models.Progress.WAITING
+    video = crud.item.create_with_owner(db=db, obj_in=video_create, owner_id=current_user.id)
+    return video

+ 1 - 0
backend/app/app/crud/__init__.py

@@ -1,5 +1,6 @@
 from .crud_item import item
 from .crud_item import item
 from .crud_user import user
 from .crud_user import user
+from .crud_video import video
 
 
 # For a new basic set of CRUD operations you could just do
 # For a new basic set of CRUD operations you could just do
 
 

+ 34 - 0
backend/app/app/crud/crud_video.py

@@ -0,0 +1,34 @@
+from typing import List
+
+from fastapi.encoders import jsonable_encoder
+from sqlalchemy.orm import Session
+
+from app.crud.base import CRUDBase
+from app.models.video import Video
+from app.schemas.video import VideoCreate, VideoUpdate
+
+
+class CRUDVideo(CRUDBase[Video, VideoCreate, VideoUpdate]):
+    def create_with_owner(
+        self, db: Session, *, obj_in: VideoCreate, owner_id: int
+    ) -> Video:
+        obj_in_data = jsonable_encoder(obj_in)
+        db_obj = self.model(**obj_in_data, owner_id=owner_id)
+        db.add(db_obj)
+        db.commit()
+        db.refresh(db_obj)
+        return db_obj
+
+    def get_multi_by_owner(
+        self, db: Session, *, owner_id: int, skip: int = 0, limit: int = 100
+    ) -> List[Video]:
+        return (
+            db.query(self.model)
+            .filter(Video.owner_id == owner_id)
+            .offset(skip)
+            .limit(limit)
+            .all()
+        )
+
+
+video = CRUDVideo(Video)

+ 1 - 0
backend/app/app/db/base.py

@@ -3,3 +3,4 @@
 from app.db.base_class import Base  # noqa
 from app.db.base_class import Base  # noqa
 from app.models.item import Item  # noqa
 from app.models.item import Item  # noqa
 from app.models.user import User  # noqa
 from app.models.user import User  # noqa
+from app.models.video import Video

+ 3 - 0
backend/app/app/models/__init__.py

@@ -1,2 +1,5 @@
 from .item import Item
 from .item import Item
 from .user import User
 from .user import User
+from .user import Membership
+from .video import Video
+from .video import Progress

+ 18 - 8
backend/app/app/models/user.py

@@ -1,19 +1,29 @@
 from typing import TYPE_CHECKING
 from typing import TYPE_CHECKING
 
 
-from sqlalchemy import Boolean, Column, Integer, String
+from sqlalchemy import Boolean, Column, Integer, String, Enum
 from sqlalchemy.orm import relationship
 from sqlalchemy.orm import relationship
 
 
 from app.db.base_class import Base
 from app.db.base_class import Base
 
 
+import enum
+
+
 if TYPE_CHECKING:
 if TYPE_CHECKING:
     from .item import Item  # noqa: F401
     from .item import Item  # noqa: F401
 
 
 
 
+class Membership(enum.Enum):
+  Chosen = enum.auto()
+  Normal = enum.auto()
+
 class User(Base):
 class User(Base):
-    id = Column(Integer, primary_key=True, index=True)
-    full_name = Column(String, index=True)
-    email = Column(String, unique=True, index=True, nullable=False)
-    hashed_password = Column(String, nullable=False)
-    is_active = Column(Boolean(), default=True)
-    is_superuser = Column(Boolean(), default=False)
-    items = relationship("Item", back_populates="owner")
+  id = Column(Integer, primary_key=True, index=True)
+  full_name = Column(String, index=True)
+  email = Column(String, unique=True, index=True, nullable=False)
+  hashed_password = Column(String, nullable=False)
+  membership = Column(Enum(Membership), nullable=False, default=Membership.Normal)
+  time = Column(Integer, default=0)
+  is_active = Column(Boolean(), default=True)
+  is_superuser = Column(Boolean(), default=False)
+  items = relationship("Item", back_populates="owner")
+  videos = relationship("Video", back_populates="owner")

+ 23 - 0
backend/app/app/models/video.py

@@ -0,0 +1,23 @@
+from typing import TYPE_CHECKING
+
+from sqlalchemy import Column, ForeignKey, Integer, String, Enum
+from sqlalchemy.orm import relationship
+
+from app.db.base_class import Base
+
+import enum
+
+if TYPE_CHECKING:
+    from .user import User  # noqa: F401
+
+class Progress(enum.Enum):
+  WAITING = enum.auto()
+  PROCESSING = enum.auto()
+  COMPLETE = enum.auto()
+
+class Video(Base):
+  id = Column(Integer, primary_key=True, index=True)
+  title = Column(String, index=True)
+  progress = Column(Enum(Progress))
+  owner_id = Column(Integer, ForeignKey("user.id"))
+  owner = relationship("User", back_populates="videos")

+ 1 - 0
backend/app/app/schemas/__init__.py

@@ -2,3 +2,4 @@ from .item import Item, ItemCreate, ItemInDB, ItemUpdate
 from .msg import Msg
 from .msg import Msg
 from .token import Token, TokenPayload
 from .token import Token, TokenPayload
 from .user import User, UserCreate, UserInDB, UserUpdate
 from .user import User, UserCreate, UserInDB, UserUpdate
+from .video import Video, VideoCreate, VideoInDB, VideoUpdate

+ 42 - 0
backend/app/app/schemas/video.py

@@ -0,0 +1,42 @@
+from typing import Optional
+
+from pydantic import BaseModel
+
+from fastapi import UploadFile, File
+
+# Shared properties
+class VideoBase(BaseModel):
+    title: Optional[str] = None
+
+# Properties to receive on item upload
+class VideoUpload(VideoBase):
+    title: str
+    zip_file: UploadFile=File()
+
+# Properties to receive on item creation
+class VideoCreate(VideoBase):
+    title: str
+
+# Properties to receive on item update
+class VideoUpdate(VideoBase):
+    pass
+
+# Properties shared by models stored in DB
+class VideoInDBBase(VideoBase):
+    id: int
+    title: str
+    progress: str
+    owner_id: int
+
+    class Config:
+        orm_mode = True
+
+
+# Properties to return to client
+class Video(VideoInDBBase):
+    pass
+
+
+# Properties properties stored in DB
+class VideoInDB(VideoInDBBase):
+    pass

+ 1 - 53
frontend/src/views/Login.vue

@@ -85,7 +85,7 @@ onMounted(() => {});
 
 
           <p class="text-center">
           <p class="text-center">
             還沒有帳號?
             還沒有帳號?
-            <router-link to="/signup">註冊</router-link><router-link
+            <router-link to="/signup">註冊</router-link> / <router-link
               to="/recover-password"
               to="/recover-password"
               >忘記密碼</router-link
               >忘記密碼</router-link
             >
             >
@@ -104,56 +104,4 @@ onMounted(() => {});
     </v-row>
     </v-row>
   </v-container>
   </v-container>
 
 
-  <!-- <v-container fluid class="d-flex fill-height">
-    <v-row align="center" justify="center">
-      <v-col :cols="width">
-        <v-card class="elevation-12">
-          <v-toolbar dark color="primary">
-            <v-toolbar-title>{{ appName }}</v-toolbar-title>
-            <v-spacer></v-spacer>
-            <v-btn to="/signup">SignUp</v-btn>
-          </v-toolbar>
-          <v-card-text>
-            <v-form @keyup.enter="submit">
-              <v-text-field
-                @keyup.enter="submit"
-                v-model="email"
-                prepend-icon="person"
-                name="email"
-                label="Email"
-                type="text"
-              ></v-text-field>
-              <v-text-field
-                @keyup.enter="submit"
-                v-model="password"
-                prepend-icon="key"
-                name="password"
-                label="Password"
-                id="password"
-                type="password"
-              ></v-text-field>
-            </v-form>
-            <div v-if="loginError">
-              <v-alert
-                :value="loginError"
-                transition="fade-transition"
-                type="error"
-              >
-                Incorrect email or password
-              </v-alert>
-            </div>
-            <div class="d-flex align-end flex-column">
-              <router-link to="/recover-password"
-                >Forgot your password?</router-link
-              >
-            </div>
-          </v-card-text>
-          <v-card-actions>
-            <v-spacer></v-spacer>
-            <v-btn @click.prevent="submit">Login</v-btn>
-          </v-card-actions>
-        </v-card>
-      </v-col>
-    </v-row>
-  </v-container> -->
 </template>
 </template>