bug: (timestamp) git

This commit is contained in:
null 2026-05-20 01:44:31 -05:00
parent ad5ca38a86
commit 5d7403984d
3 changed files with 32 additions and 12 deletions

View File

@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
from uuid import UUID from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, status from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import cast, String
from sqlmodel import select, func from sqlmodel import select, func
from app.api.deps import get_board_for_user_write, require_org_member from app.api.deps import get_board_for_user_write, require_org_member
@ -54,10 +55,23 @@ async def list_issues(
if state: if state:
statement = statement.where(ForgejoIssue.state == state) statement = statement.where(ForgejoIssue.state == state)
if label:
# Filter by label name — search within the JSON labels array cast to text
statement = statement.where(
cast(ForgejoIssue.labels, String).ilike(f"%{label}%")
)
if assignee:
# Filter by assignee login — search within the JSON assignees array cast to text
statement = statement.where(
cast(ForgejoIssue.assignees, String).ilike(f"%{assignee}%")
)
if search: if search:
statement = statement.where( statement = statement.where(
(ForgejoIssue.title.ilike(f"%{search}%")) | (ForgejoIssue.title.ilike(f"%{search}%")) |
(ForgejoIssue.body_preview.ilike(f"%{search}%")) (ForgejoIssue.body_preview.ilike(f"%{search}%")) |
(ForgejoIssue.body.ilike(f"%{search}%"))
) )
# Count total # Count total
@ -70,10 +84,19 @@ async def list_issues(
pass pass
if state: if state:
total_statement = total_statement.where(ForgejoIssue.state == state) total_statement = total_statement.where(ForgejoIssue.state == state)
if label:
total_statement = total_statement.where(
cast(ForgejoIssue.labels, String).ilike(f"%{label}%")
)
if assignee:
total_statement = total_statement.where(
cast(ForgejoIssue.assignees, String).ilike(f"%{assignee}%")
)
if search: if search:
total_statement = total_statement.where( total_statement = total_statement.where(
(ForgejoIssue.title.ilike(f"%{search}%")) | (ForgejoIssue.title.ilike(f"%{search}%")) |
(ForgejoIssue.body_preview.ilike(f"%{search}%")) (ForgejoIssue.body_preview.ilike(f"%{search}%")) |
(ForgejoIssue.body.ilike(f"%{search}%"))
) )
total_result = await session.exec(total_statement) total_result = await session.exec(total_statement)
total = total_result.one() total = total_result.one()

View File

@ -198,7 +198,6 @@ class ForgejoAPIClient:
List of repository dicts with name, full_name, owner, default_branch, etc. List of repository dicts with name, full_name, owner, default_branch, etc.
""" """
client = await self._get_client() client = await self._get_client()
params = {"limit": limit, "page": page, "token": ""}
response = await client.get("/api/v1/repos/search", params={"limit": limit, "page": page}) response = await client.get("/api/v1/repos/search", params={"limit": limit, "page": page})
response.raise_for_status() response.raise_for_status()
data = response.json() data = response.json()

View File

@ -112,9 +112,9 @@ class IssueSyncService:
body_full = raw_body if raw_body else None body_full = raw_body if raw_body else None
body_preview = raw_body[:1000] if raw_body else None body_preview = raw_body[:1000] if raw_body else None
# Parse dates # Parse dates — required fields fall back to utcnow(), optional closed_at stays None
created_at = self._parse_iso_date(issue_data.get("created_at")) created_at = self._parse_iso_date(issue_data.get("created_at")) or utcnow()
updated_at = self._parse_iso_date(issue_data.get("updated_at")) updated_at = self._parse_iso_date(issue_data.get("updated_at")) or utcnow()
closed_at = self._parse_iso_date(issue_data.get("closed_at")) closed_at = self._parse_iso_date(issue_data.get("closed_at"))
# Check if issue exists # Check if issue exists
@ -234,15 +234,13 @@ class IssueSyncService:
results = await self.session.exec(statement) results = await self.session.exec(statement)
return results.first() return results.first()
def _parse_iso_date(self, date_str: str | None) -> datetime: def _parse_iso_date(self, date_str: str | None) -> datetime | None:
"""Parse ISO format date string to datetime.""" """Parse ISO format date string to datetime. Returns None for absent/empty values."""
if not date_str: if not date_str:
return utcnow() return None
try: try:
# Handle Z suffix
cleaned = date_str.replace("Z", "+00:00") cleaned = date_str.replace("Z", "+00:00")
parsed = datetime.fromisoformat(cleaned) parsed = datetime.fromisoformat(cleaned)
# Strip timezone info for naive UTC storage
return parsed.replace(tzinfo=None) return parsed.replace(tzinfo=None)
except (ValueError, AttributeError): except (ValueError, AttributeError):
return utcnow() return None