SarahXia0405 commited on
Commit
a581a5b
·
verified ·
1 Parent(s): 7361291

Create store.py

Browse files
Files changed (1) hide show
  1. api/store.py +145 -0
api/store.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # api/store.py
2
+ from __future__ import annotations
3
+ import json
4
+ import os
5
+ from typing import Dict, Any, List, Optional
6
+ from pathlib import Path
7
+
8
+ from api.models import CourseDirectoryItem, Workspace, PersonContact, WorkspaceCourseRef, WorkspaceMember
9
+
10
+ DATA_DIR = Path(os.getenv("CLARE_DATA_DIR", "./data"))
11
+ COURSE_FILE = DATA_DIR / "course_directory.json"
12
+ WORKSPACE_FILE = DATA_DIR / "workspaces.json"
13
+
14
+
15
+ def _ensure_dir():
16
+ DATA_DIR.mkdir(parents=True, exist_ok=True)
17
+
18
+
19
+ def _read_json(path: Path) -> Optional[Any]:
20
+ if not path.exists():
21
+ return None
22
+ with path.open("r", encoding="utf-8") as f:
23
+ return json.load(f)
24
+
25
+
26
+ def _write_json(path: Path, obj: Any) -> None:
27
+ _ensure_dir()
28
+ with path.open("w", encoding="utf-8") as f:
29
+ json.dump(obj, f, ensure_ascii=False, indent=2)
30
+
31
+
32
+ def seed_if_missing() -> None:
33
+ """
34
+ Provide sane defaults so HF can run out-of-the-box.
35
+ Replace these with your real course list/workspaces later.
36
+ """
37
+ _ensure_dir()
38
+
39
+ if not COURSE_FILE.exists():
40
+ courses = [
41
+ CourseDirectoryItem(
42
+ id="course_ai_001",
43
+ name="Introduction to AI",
44
+ instructor=PersonContact(name="Dr. Smith", email="smith@uni.edu"),
45
+ teachingAssistant=PersonContact(name="Alice", email="alice@uni.edu"),
46
+ ).model_dump()
47
+ ]
48
+ _write_json(COURSE_FILE, {"items": courses})
49
+
50
+ if not WORKSPACE_FILE.exists():
51
+ workspaces = [
52
+ Workspace(
53
+ id="ws_group_ai_g3",
54
+ type="group",
55
+ category="course",
56
+ name="Group Alpha",
57
+ groupNo=3,
58
+ courseId="course_ai_001",
59
+ courseInfo=WorkspaceCourseRef(id="course_ai_001", name="Introduction to AI"),
60
+ members=[
61
+ WorkspaceMember(id="u1", name="Sarah", email="sarah@uni.edu", role="owner"),
62
+ WorkspaceMember(id="u2", name="Bob", email="bob@uni.edu", role="member"),
63
+ ],
64
+ ).model_dump()
65
+ ]
66
+ _write_json(WORKSPACE_FILE, {"items": workspaces})
67
+
68
+
69
+ def load_courses() -> List[CourseDirectoryItem]:
70
+ seed_if_missing()
71
+ raw = _read_json(COURSE_FILE) or {}
72
+ items = raw.get("items", [])
73
+ out: List[CourseDirectoryItem] = []
74
+ for x in items:
75
+ out.append(CourseDirectoryItem(**x))
76
+ return out
77
+
78
+
79
+ def save_courses(courses: List[CourseDirectoryItem]) -> None:
80
+ _write_json(COURSE_FILE, {"items": [c.model_dump() for c in courses]})
81
+
82
+
83
+ def load_workspaces() -> List[Workspace]:
84
+ seed_if_missing()
85
+ raw = _read_json(WORKSPACE_FILE) or {}
86
+ items = raw.get("items", [])
87
+ out: List[Workspace] = []
88
+ for x in items:
89
+ out.append(Workspace(**x))
90
+ return out
91
+
92
+
93
+ def save_workspaces(workspaces: List[Workspace]) -> None:
94
+ _write_json(WORKSPACE_FILE, {"items": [w.model_dump() for w in workspaces]})
95
+
96
+
97
+ def enrich_workspace_course_info(workspaces: List[Workspace], courses: List[CourseDirectoryItem]) -> List[Workspace]:
98
+ """
99
+ Ensure workspace.courseInfo has instructor/TA to satisfy CourseInfoSection fallback.
100
+ Frontend prefers availableCourses, but this makes fallback robust.
101
+ """
102
+ by_id = {c.id.strip().lower(): c for c in courses}
103
+ by_name = {c.name.strip().lower(): c for c in courses}
104
+
105
+ enriched: List[Workspace] = []
106
+ for w in workspaces:
107
+ ws_course = w.courseInfo
108
+ hit: Optional[CourseDirectoryItem] = None
109
+
110
+ if w.courseId:
111
+ hit = by_id.get(w.courseId.strip().lower())
112
+ if not hit and ws_course and ws_course.id:
113
+ hit = by_id.get(ws_course.id.strip().lower())
114
+ if not hit and ws_course and ws_course.name:
115
+ hit = by_name.get(ws_course.name.strip().lower())
116
+
117
+ if hit:
118
+ w.courseId = w.courseId or hit.id
119
+ w.courseInfo = WorkspaceCourseRef(
120
+ id=hit.id,
121
+ name=hit.name,
122
+ instructor=hit.instructor,
123
+ teachingAssistant=hit.teachingAssistant,
124
+ )
125
+ else:
126
+ # keep whatever exists; CourseInfoSection will show fallback if nothing matches
127
+ w.courseInfo = ws_course
128
+
129
+ enriched.append(w)
130
+
131
+ return enriched
132
+
133
+
134
+ def rename_workspace(workspace_id: str, new_name: str) -> Workspace:
135
+ workspaces = load_workspaces()
136
+ found = None
137
+ for w in workspaces:
138
+ if w.id == workspace_id:
139
+ w.name = new_name
140
+ found = w
141
+ break
142
+ if not found:
143
+ raise KeyError(f"workspace not found: {workspace_id}")
144
+ save_workspaces(workspaces)
145
+ return found