feat: band NC folder config, fix watcher event filter, add light/dark theme

- Add PATCH /bands/{id} endpoint for admins to update nc_folder_path
- Add band NC scan folder UI panel with inline edit
- Fix watcher: use activity type field (not human-readable subject) for upload detection
- Reorder watcher filters: audio extension check first, then band path, then type
- Add dark/light theme toggle using GitHub Primer-inspired CSS custom properties
- All inline styles migrated to CSS variables for theme-awareness

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Steffen Schuhmann
2026-03-29 00:29:58 +01:00
parent 5536bf4394
commit fbac62a0ea
13 changed files with 419 additions and 211 deletions

View File

@@ -6,7 +6,8 @@ from sqlalchemy.ext.asyncio import AsyncSession
from rehearsalhub.db.engine import get_session
from rehearsalhub.db.models import Member
from rehearsalhub.dependencies import get_current_member
from rehearsalhub.schemas.band import BandCreate, BandRead, BandReadWithMembers
from rehearsalhub.schemas.band import BandCreate, BandRead, BandReadWithMembers, BandUpdate
from rehearsalhub.repositories.band import BandRepository
from rehearsalhub.services.band import BandService
router = APIRouter(prefix="/bands", tags=["bands"])
@@ -17,7 +18,6 @@ async def list_bands(
session: AsyncSession = Depends(get_session),
current_member: Member = Depends(get_current_member),
):
from rehearsalhub.repositories.band import BandRepository
repo = BandRepository(session)
bands = await repo.list_for_member(current_member.id)
return [BandRead.model_validate(b) for b in bands]
@@ -53,3 +53,29 @@ async def get_band(
if band is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Band not found")
return BandReadWithMembers.model_validate(band)
@router.patch("/{band_id}", response_model=BandRead)
async def update_band(
band_id: uuid.UUID,
data: BandUpdate,
session: AsyncSession = Depends(get_session),
current_member: Member = Depends(get_current_member),
):
repo = BandRepository(session)
role = await repo.get_member_role(band_id, current_member.id)
if role != "admin":
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Admin only")
band = await repo.get_by_id(band_id)
if band is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Band not found")
updates: dict = {}
if data.nc_folder_path is not None:
path = data.nc_folder_path.strip()
updates["nc_folder_path"] = (path.rstrip("/") + "/") if path else None
if updates:
band = await repo.update(band, **updates)
return BandRead.model_validate(band)

View File

@@ -21,6 +21,10 @@ class BandCreate(BaseModel):
nc_base_path: str | None = None # e.g. "Bands/MyBand/" — defaults to "bands/{slug}/"
class BandUpdate(BaseModel):
nc_folder_path: str | None = None # update the Nextcloud base folder for scans
class BandRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID