Spaces:
Running
Running
GitHub Action commited on
Commit ·
ec7fd73
1
Parent(s): d761759
deploy from github actions
Browse files- app/main.py +1 -1
- app/models/user.py +10 -0
- app/routers/admin.py +131 -1
app/main.py
CHANGED
|
@@ -3,7 +3,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
|
| 3 |
from fastapi.staticfiles import StaticFiles
|
| 4 |
from app.database import engine, Base
|
| 5 |
from app.routers import auth, songs, lyrics, iglesia, aprendizaje, midi, alabanza, workers, admin, migration
|
| 6 |
-
from app.models.user import User, AdminUser, AdminNotification
|
| 7 |
from app.models.process import Task, Worker
|
| 8 |
from app.models.lyrics import Lyric, Repertorio, Group, UserGroup, Invitation
|
| 9 |
from app.models.iglesia import Iglesia, IglesiaMember, IglesiaRol, Calendario, Servicio, Asistencia, Finanza, Momento, RelacionFamiliar, Inventario, Miembro, DismissedVisita
|
|
|
|
| 3 |
from fastapi.staticfiles import StaticFiles
|
| 4 |
from app.database import engine, Base
|
| 5 |
from app.routers import auth, songs, lyrics, iglesia, aprendizaje, midi, alabanza, workers, admin, migration
|
| 6 |
+
from app.models.user import User, AdminUser, AdminNotification, LandingGalleryItem
|
| 7 |
from app.models.process import Task, Worker
|
| 8 |
from app.models.lyrics import Lyric, Repertorio, Group, UserGroup, Invitation
|
| 9 |
from app.models.iglesia import Iglesia, IglesiaMember, IglesiaRol, Calendario, Servicio, Asistencia, Finanza, Momento, RelacionFamiliar, Inventario, Miembro, DismissedVisita
|
app/models/user.py
CHANGED
|
@@ -114,3 +114,13 @@ class LandingTutorial(Base):
|
|
| 114 |
desc = Column(String, nullable=True)
|
| 115 |
steps = Column(JSON, default=[]) # list of strings
|
| 116 |
order = Column(Integer, default=0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
desc = Column(String, nullable=True)
|
| 115 |
steps = Column(JSON, default=[]) # list of strings
|
| 116 |
order = Column(Integer, default=0)
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
class LandingGalleryItem(Base):
|
| 120 |
+
__tablename__ = "landing_gallery"
|
| 121 |
+
|
| 122 |
+
id = Column(Integer, primary_key=True, index=True)
|
| 123 |
+
image_url = Column(String, nullable=False)
|
| 124 |
+
caption = Column(String, nullable=True)
|
| 125 |
+
order = Column(Integer, default=0)
|
| 126 |
+
|
app/routers/admin.py
CHANGED
|
@@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends, HTTPException, status
|
|
| 2 |
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
| 3 |
from sqlalchemy.orm import Session
|
| 4 |
from app.database import get_db
|
| 5 |
-
from app.models.user import User, CreditTransaction, AdminUser, AdminNotification, LandingFeature, LandingPlatform, LandingTutorial
|
| 6 |
from app.models.iglesia import Iglesia
|
| 7 |
from app.models.lyrics import Group
|
| 8 |
from app.routers.auth import SECRET_KEY, ALGORITHM, verify_password, create_access_token, ACCESS_TOKEN_EXPIRE_MINUTES, get_password_hash
|
|
@@ -1007,3 +1007,133 @@ def delete_tutorial(
|
|
| 1007 |
db.delete(tutorial)
|
| 1008 |
db.commit()
|
| 1009 |
return {"message": "Tutorial de landing page eliminado exitosamente"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
| 3 |
from sqlalchemy.orm import Session
|
| 4 |
from app.database import get_db
|
| 5 |
+
from app.models.user import User, CreditTransaction, AdminUser, AdminNotification, LandingFeature, LandingPlatform, LandingTutorial, LandingGalleryItem
|
| 6 |
from app.models.iglesia import Iglesia
|
| 7 |
from app.models.lyrics import Group
|
| 8 |
from app.routers.auth import SECRET_KEY, ALGORITHM, verify_password, create_access_token, ACCESS_TOKEN_EXPIRE_MINUTES, get_password_hash
|
|
|
|
| 1007 |
db.delete(tutorial)
|
| 1008 |
db.commit()
|
| 1009 |
return {"message": "Tutorial de landing page eliminado exitosamente"}
|
| 1010 |
+
|
| 1011 |
+
|
| 1012 |
+
class LandingGalleryItemCreate(BaseModel):
|
| 1013 |
+
image_url: str
|
| 1014 |
+
caption: Optional[str] = None
|
| 1015 |
+
order: int = 0
|
| 1016 |
+
|
| 1017 |
+
|
| 1018 |
+
class LandingGalleryItemUpdate(BaseModel):
|
| 1019 |
+
image_url: Optional[str] = None
|
| 1020 |
+
caption: Optional[str] = None
|
| 1021 |
+
order: Optional[int] = None
|
| 1022 |
+
|
| 1023 |
+
|
| 1024 |
+
DEFAULT_GALLERY = [
|
| 1025 |
+
{
|
| 1026 |
+
"image_url": "/hero_banner.png",
|
| 1027 |
+
"caption": "Plan de Estudios & Desafíos",
|
| 1028 |
+
"order": 0
|
| 1029 |
+
},
|
| 1030 |
+
{
|
| 1031 |
+
"image_url": "/app_mockup.png",
|
| 1032 |
+
"caption": "Liga de la Iglesia, Perfil & Finanzas",
|
| 1033 |
+
"order": 1
|
| 1034 |
+
}
|
| 1035 |
+
]
|
| 1036 |
+
|
| 1037 |
+
|
| 1038 |
+
def _seed_gallery_if_empty(db: Session):
|
| 1039 |
+
"""Auto-seeds the landing_gallery table with defaults if empty."""
|
| 1040 |
+
count = db.query(LandingGalleryItem).count()
|
| 1041 |
+
if count == 0:
|
| 1042 |
+
for item in DEFAULT_GALLERY:
|
| 1043 |
+
db.add(LandingGalleryItem(**item))
|
| 1044 |
+
db.commit()
|
| 1045 |
+
|
| 1046 |
+
|
| 1047 |
+
@router.get("/gallery")
|
| 1048 |
+
def list_gallery(db: Session = Depends(get_db), current_admin: AdminUser = Depends(get_current_admin)):
|
| 1049 |
+
_seed_gallery_if_empty(db)
|
| 1050 |
+
items = db.query(LandingGalleryItem).order_by(LandingGalleryItem.order).all()
|
| 1051 |
+
return [
|
| 1052 |
+
{
|
| 1053 |
+
"id": i.id,
|
| 1054 |
+
"image_url": i.image_url,
|
| 1055 |
+
"caption": i.caption,
|
| 1056 |
+
"order": i.order,
|
| 1057 |
+
}
|
| 1058 |
+
for i in items
|
| 1059 |
+
]
|
| 1060 |
+
|
| 1061 |
+
|
| 1062 |
+
@router.get("/gallery/public")
|
| 1063 |
+
def list_gallery_public(db: Session = Depends(get_db)):
|
| 1064 |
+
"""Public endpoint for the landing page gallery."""
|
| 1065 |
+
_seed_gallery_if_empty(db)
|
| 1066 |
+
items = db.query(LandingGalleryItem).order_by(LandingGalleryItem.order).all()
|
| 1067 |
+
return [
|
| 1068 |
+
{
|
| 1069 |
+
"id": i.id,
|
| 1070 |
+
"image_url": i.image_url,
|
| 1071 |
+
"caption": i.caption,
|
| 1072 |
+
"order": i.order,
|
| 1073 |
+
}
|
| 1074 |
+
for i in items
|
| 1075 |
+
]
|
| 1076 |
+
|
| 1077 |
+
|
| 1078 |
+
@router.post("/gallery")
|
| 1079 |
+
def create_gallery_item(
|
| 1080 |
+
data: LandingGalleryItemCreate,
|
| 1081 |
+
db: Session = Depends(get_db),
|
| 1082 |
+
current_admin: AdminUser = Depends(get_current_admin),
|
| 1083 |
+
):
|
| 1084 |
+
item = LandingGalleryItem(
|
| 1085 |
+
image_url=data.image_url,
|
| 1086 |
+
caption=data.caption,
|
| 1087 |
+
order=data.order,
|
| 1088 |
+
)
|
| 1089 |
+
db.add(item)
|
| 1090 |
+
db.commit()
|
| 1091 |
+
db.refresh(item)
|
| 1092 |
+
return {
|
| 1093 |
+
"id": item.id,
|
| 1094 |
+
"image_url": item.image_url,
|
| 1095 |
+
"caption": item.caption,
|
| 1096 |
+
"order": item.order,
|
| 1097 |
+
}
|
| 1098 |
+
|
| 1099 |
+
|
| 1100 |
+
@router.put("/gallery/{item_id}")
|
| 1101 |
+
def update_gallery_item(
|
| 1102 |
+
item_id: int,
|
| 1103 |
+
data: LandingGalleryItemUpdate,
|
| 1104 |
+
db: Session = Depends(get_db),
|
| 1105 |
+
current_admin: AdminUser = Depends(get_current_admin),
|
| 1106 |
+
):
|
| 1107 |
+
item = db.query(LandingGalleryItem).filter(LandingGalleryItem.id == item_id).first()
|
| 1108 |
+
if not item:
|
| 1109 |
+
raise HTTPException(status_code=404, detail="Item de galería no encontrado")
|
| 1110 |
+
|
| 1111 |
+
if data.image_url is not None:
|
| 1112 |
+
item.image_url = data.image_url
|
| 1113 |
+
if data.caption is not None:
|
| 1114 |
+
item.caption = data.caption
|
| 1115 |
+
if data.order is not None:
|
| 1116 |
+
item.order = data.order
|
| 1117 |
+
|
| 1118 |
+
db.commit()
|
| 1119 |
+
db.refresh(item)
|
| 1120 |
+
return {
|
| 1121 |
+
"id": item.id,
|
| 1122 |
+
"image_url": item.image_url,
|
| 1123 |
+
"caption": item.caption,
|
| 1124 |
+
"order": item.order,
|
| 1125 |
+
}
|
| 1126 |
+
|
| 1127 |
+
|
| 1128 |
+
@router.delete("/gallery/{item_id}")
|
| 1129 |
+
def delete_gallery_item(
|
| 1130 |
+
item_id: int,
|
| 1131 |
+
db: Session = Depends(get_db),
|
| 1132 |
+
current_admin: AdminUser = Depends(get_current_admin),
|
| 1133 |
+
):
|
| 1134 |
+
item = db.query(LandingGalleryItem).filter(LandingGalleryItem.id == item_id).first()
|
| 1135 |
+
if not item:
|
| 1136 |
+
raise HTTPException(status_code=404, detail="Item de galería no encontrado")
|
| 1137 |
+
db.delete(item)
|
| 1138 |
+
db.commit()
|
| 1139 |
+
return {"message": "Item de galería eliminado exitosamente"}
|