tfrere commited on
Commit
63b2074
·
1 Parent(s): 1c3ba6f

add a submission limit checker

Browse files
backend/app/api/endpoints/models.py CHANGED
@@ -1,4 +1,4 @@
1
- from fastapi import APIRouter, HTTPException, Depends
2
  from typing import Dict, Any, List
3
  import logging
4
  from app.services.models import ModelService
@@ -80,6 +80,19 @@ async def submit_model(
80
  logger.error(LogFormatter.error("Submission failed", e))
81
  raise HTTPException(status_code=500, detail=str(e))
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  @router.get("/{model_id}/status")
84
  async def get_model_status(
85
  model_id: str,
 
1
+ from fastapi import APIRouter, HTTPException, Depends, Query
2
  from typing import Dict, Any, List
3
  import logging
4
  from app.services.models import ModelService
 
80
  logger.error(LogFormatter.error("Submission failed", e))
81
  raise HTTPException(status_code=500, detail=str(e))
82
 
83
+ @router.get("/organization/{organization}/submissions")
84
+ async def get_organization_submissions(
85
+ organization: str,
86
+ days: int = Query(default=7, ge=1, le=30),
87
+ model_service: ModelService = Depends(get_model_service)
88
+ ) -> List[Dict[str, Any]]:
89
+ """Get all submissions from an organization in the last n days"""
90
+ try:
91
+ submissions = await model_service.get_organization_submissions(organization, days)
92
+ return submissions
93
+ except Exception as e:
94
+ raise HTTPException(status_code=500, detail=str(e))
95
+
96
  @router.get("/{model_id}/status")
97
  async def get_model_status(
98
  model_id: str,
backend/app/services/models.py CHANGED
@@ -1,4 +1,4 @@
1
- from datetime import datetime, timezone
2
  from typing import Dict, Any, Optional, List
3
  import json
4
  import os
@@ -584,4 +584,41 @@ class ModelService(HuggingFaceService):
584
  return status
585
 
586
  logger.warning(LogFormatter.warning(f"No status found for model: {model_id}"))
587
- return {"status": "not_found"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime, timezone, timedelta
2
  from typing import Dict, Any, Optional, List
3
  import json
4
  import os
 
584
  return status
585
 
586
  logger.warning(LogFormatter.warning(f"No status found for model: {model_id}"))
587
+ return {"status": "not_found"}
588
+
589
+ async def get_organization_submissions(self, organization: str, days: int = 7) -> List[Dict[str, Any]]:
590
+ """Get all submissions from an organization in the last n days"""
591
+ try:
592
+ # Get all models
593
+ all_models = await self.get_models()
594
+ current_time = datetime.now(timezone.utc)
595
+ cutoff_time = current_time - timedelta(days=days)
596
+
597
+ # Filter models by organization and submission time
598
+ org_submissions = []
599
+ for status, models in all_models.items():
600
+ for model in models:
601
+ # Check if model belongs to organization
602
+ if model["name"].startswith(f"{organization}/"):
603
+ # Parse submission time
604
+ submit_time = datetime.fromisoformat(
605
+ model["submission_time"].replace("Z", "+00:00")
606
+ )
607
+ # Check if within time window
608
+ if submit_time > cutoff_time:
609
+ org_submissions.append({
610
+ "name": model["name"],
611
+ "status": status,
612
+ "submission_time": model["submission_time"],
613
+ "precision": model["precision"]
614
+ })
615
+
616
+ return sorted(
617
+ org_submissions,
618
+ key=lambda x: x["submission_time"],
619
+ reverse=True
620
+ )
621
+
622
+ except Exception as e:
623
+ logger.error(LogFormatter.error(f"Failed to get submissions for {organization}", e))
624
+ raise
frontend/src/pages/AddModelPage/AddModelPage.js CHANGED
@@ -5,6 +5,7 @@ import PageHeader from "../../components/shared/PageHeader";
5
  import EvaluationQueues from "./components/EvaluationQueues/EvaluationQueues";
6
  import ModelSubmissionForm from "./components/ModelSubmissionForm/ModelSubmissionForm";
7
  import SubmissionGuide from "./components/SubmissionGuide/SubmissionGuide";
 
8
 
9
  function AddModelPage() {
10
  const { isAuthenticated, loading, user } = useAuth();
@@ -38,7 +39,9 @@ function AddModelPage() {
38
 
39
  <SubmissionGuide />
40
 
41
- <ModelSubmissionForm user={user} isAuthenticated={isAuthenticated} />
 
 
42
 
43
  <EvaluationQueues defaultExpanded={false} />
44
  </Box>
 
5
  import EvaluationQueues from "./components/EvaluationQueues/EvaluationQueues";
6
  import ModelSubmissionForm from "./components/ModelSubmissionForm/ModelSubmissionForm";
7
  import SubmissionGuide from "./components/SubmissionGuide/SubmissionGuide";
8
+ import SubmissionLimitChecker from "./components/SubmissionLimitChecker/SubmissionLimitChecker";
9
 
10
  function AddModelPage() {
11
  const { isAuthenticated, loading, user } = useAuth();
 
39
 
40
  <SubmissionGuide />
41
 
42
+ <SubmissionLimitChecker user={user}>
43
+ <ModelSubmissionForm user={user} isAuthenticated={isAuthenticated} />
44
+ </SubmissionLimitChecker>
45
 
46
  <EvaluationQueues defaultExpanded={false} />
47
  </Box>
frontend/src/pages/AddModelPage/components/SubmissionLimitChecker/SubmissionLimitChecker.js ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from "react";
2
+ import { Alert, Box, CircularProgress } from "@mui/material";
3
+
4
+ const MAX_SUBMISSIONS_PER_WEEK = 10;
5
+
6
+ function SubmissionLimitChecker({ user, children }) {
7
+ const [loading, setLoading] = useState(true);
8
+ const [reachedLimit, setReachedLimit] = useState(false);
9
+ const [error, setError] = useState(false);
10
+
11
+ useEffect(() => {
12
+ const checkSubmissionLimit = async () => {
13
+ if (!user?.username) {
14
+ setLoading(false);
15
+ return;
16
+ }
17
+
18
+ try {
19
+ const response = await fetch(
20
+ `/api/models/organization/${user.username}/submissions?days=7`
21
+ );
22
+ if (!response.ok) {
23
+ throw new Error("Failed to fetch submission data");
24
+ }
25
+
26
+ const submissions = await response.json();
27
+ console.log(`Recent submissions for ${user.username}:`, submissions);
28
+ setReachedLimit(submissions.length >= MAX_SUBMISSIONS_PER_WEEK);
29
+ setError(false);
30
+ } catch (error) {
31
+ console.error("Error checking submission limit:", error);
32
+ setError(true);
33
+ } finally {
34
+ setLoading(false);
35
+ }
36
+ };
37
+
38
+ checkSubmissionLimit();
39
+ }, [user?.username]);
40
+
41
+ if (loading) {
42
+ return (
43
+ <Box sx={{ display: "flex", justifyContent: "center", py: 4 }}>
44
+ <CircularProgress />
45
+ </Box>
46
+ );
47
+ }
48
+
49
+ if (error) {
50
+ return (
51
+ <Alert
52
+ severity="error"
53
+ sx={{
54
+ mb: 3,
55
+ "& .MuiAlert-message": {
56
+ fontSize: "1rem",
57
+ },
58
+ }}
59
+ >
60
+ Unable to verify submission limits. Please try again in a few minutes.
61
+ </Alert>
62
+ );
63
+ }
64
+
65
+ if (reachedLimit) {
66
+ return (
67
+ <Alert
68
+ severity="warning"
69
+ sx={{
70
+ mb: 3,
71
+ "& .MuiAlert-message": {
72
+ fontSize: "1rem",
73
+ },
74
+ }}
75
+ >
76
+ For fairness reasons, you cannot submit more than{" "}
77
+ {MAX_SUBMISSIONS_PER_WEEK} models per week. Please try again later.
78
+ </Alert>
79
+ );
80
+ }
81
+
82
+ return children;
83
+ }
84
+
85
+ export default SubmissionLimitChecker;