Files

205 lines
6.4 KiB
Python

from dataclasses import dataclass, field
import jsonfile
from fields import FieldSpec, get_path
@dataclass
class Collection:
id: str
title: str
file: str
fields: list[FieldSpec]
columns: list[tuple[str, str]] = field(default_factory=list)
single: bool = False
@property
def title_field(self) -> FieldSpec:
return self.fields[0]
PROJECT_BASICS = [
FieldSpec("name", "Name", required=True),
FieldSpec("description", "Description", "longtext"),
FieldSpec("featured", "Featured", "flag"),
FieldSpec("tags", "Tags", "tags"),
]
PROJECT_COLUMNS = [("Name", "name"), ("Featured", "featured"), ("Tags", "tags")]
PROFILE = Collection(
"profile",
"Profile",
"profile.json",
[
FieldSpec("name", "Full name", required=True),
FieldSpec("displayName", "Display name"),
FieldSpec("title", "Title"),
FieldSpec("tagline", "Tagline", "longtext"),
FieldSpec("bio", "Bio", "longtext"),
FieldSpec("email", "Email"),
FieldSpec("photo", "Portfolio photo", "image"),
FieldSpec("avatar", "Avatar", "image"),
FieldSpec("education.school", "School"),
FieldSpec("education.degree", "Degree"),
FieldSpec("education.graduation", "Graduation"),
FieldSpec("interests", "Interests", "tags"),
FieldSpec("skills", "Skills", "skill_map"),
FieldSpec("socials", "Socials", "socials"),
FieldSpec("donateUrl", "Donate url"),
FieldSpec("giteaUrl", "Gitea url"),
],
single=True,
)
EXPERIENCE = Collection(
"experience",
"Experience",
"experience.json",
[
FieldSpec("role", "Role", required=True),
FieldSpec("organization", "Organization"),
FieldSpec("school", "School"),
FieldSpec("period", "Period"),
FieldSpec("employmentType", "Employment type"),
FieldSpec("highlights", "Highlights", "lines"),
FieldSpec("tech", "Tech", "tags"),
FieldSpec("awards", "Awards", "lines"),
FieldSpec("links", "Links", "link_list"),
],
[("Role", "role"), ("Organization", "organization"), ("Period", "period")],
)
LEADERSHIP = Collection(
"leadership",
"Leadership",
"leadership.json",
[
FieldSpec("role", "Role", required=True),
FieldSpec("organization", "Organization"),
FieldSpec("url", "Url"),
],
[("Role", "role"), ("Organization", "organization")],
)
PROJECT_COLLECTIONS = [
Collection(
"opensource",
"Open Source",
"projects/opensource.json",
[*PROJECT_BASICS, FieldSpec("version", "Version"), FieldSpec("period", "Period"), FieldSpec("image", "Image", "image"), FieldSpec("links", "Links", "link_map")],
PROJECT_COLUMNS,
),
Collection(
"packages",
"Packages",
"projects/packages.json",
[*PROJECT_BASICS, FieldSpec("deprecated", "Deprecated", "flag"), FieldSpec("links", "Links", "link_map")],
PROJECT_COLUMNS,
),
Collection(
"hackathons",
"Hackathons",
"projects/hackathons.json",
[
*PROJECT_BASICS,
FieldSpec("image", "Image", "image"),
FieldSpec("event.name", "Event"),
FieldSpec("event.university", "University"),
FieldSpec("event.location", "Location"),
FieldSpec("event.year", "Year"),
FieldSpec("awards", "Awards", "awards"),
FieldSpec("links", "Links", "link_map"),
],
[("Name", "name"), ("Event", "event.name"), ("Featured", "featured")],
),
Collection(
"research",
"Research groups",
"projects/research.json",
[
FieldSpec("name", "Name", required=True),
FieldSpec("shortName", "Short name"),
FieldSpec("institution", "Institution"),
FieldSpec("role", "Role"),
FieldSpec("period", "Period"),
FieldSpec("description", "Description", "longtext"),
FieldSpec("lab.name", "Lab name"),
FieldSpec("lab.url", "Lab url"),
FieldSpec("focus", "Focus", "tags"),
FieldSpec("links", "Links", "link_list"),
],
[("Name", "name"), ("Role", "role"), ("Period", "period")],
),
Collection(
"organizations",
"Organizations",
"projects/organizations.json",
[
*PROJECT_BASICS,
FieldSpec("organization", "Roles"),
FieldSpec("awards", "Awards", "awards"),
FieldSpec("gallery", "Gallery", "images"),
FieldSpec("links", "Links", "link_map"),
FieldSpec("socials", "Socials", "socials"),
],
PROJECT_COLUMNS,
),
]
def find_collection(collection_id: str) -> Collection:
for collection in [PROFILE, EXPERIENCE, LEADERSHIP, *PROJECT_COLLECTIONS]:
if collection.id == collection_id:
return collection
raise ValueError(f"Unknown collection {collection_id}")
def load_records(collection: Collection):
return jsonfile.load(collection.file)
def save_records(collection: Collection, records) -> None:
jsonfile.save(collection.file, records)
def record_title(collection: Collection, record: dict) -> str:
return str(get_path(record, collection.title_field.path) or "untitled")
def check_required(collection: Collection, record: dict) -> None:
for spec in collection.fields:
if spec.required and not get_path(record, spec.path):
raise ValueError(f"{spec.label} is required")
def save_record(collection: Collection, index: int | None, record: dict) -> int:
check_required(collection, record)
if collection.single:
save_records(collection, record)
return 0
records = load_records(collection)
if index is None:
records.append(record)
index = len(records) - 1
else:
records[index] = record
save_records(collection, records)
return index
def remove_record(collection: Collection, index: int) -> dict:
records = load_records(collection)
removed = records.pop(index)
save_records(collection, records)
return removed
def move_record(collection: Collection, index: int, step: int) -> int:
records = load_records(collection)
target = index + step
if not 0 <= target < len(records):
return index
records[index], records[target] = records[target], records[index]
save_records(collection, records)
return target