Skip to content
This repository has been archived by the owner on May 31, 2024. It is now read-only.

Add a simple static web UI #52

Merged
merged 11 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ jobs:
- name: Hit registry endpoints
run: |
sleep 5
curl http://localhost:8080/filetypes | jq
curl http://localhost:8080/extractors| jq
curl http://localhost:8080/redoc
curl http://localhost:8080/api/filetypes | jq
curl http://localhost:8080/api/extractors | jq
curl http://localhost:8080/api/redoc
curl http://localhost:8080/filetypes
curl http://localhost:8080/extractors
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
exclude: ^(marda_registry/data/|marda_registry/models/)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ run invoke validate-entries
cmd uvicorn marda_registry.app:app --host 0.0.0.0 --port ${PORT}

healthcheck --interval=5m --timeout=3s --start-period=10s \
cmd curl --fail http://localhost:${PORT} || exit 1
cmd curl --fail http://localhost:${PORT}/api || exit 1
111 changes: 92 additions & 19 deletions marda_registry/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@
import json
import pathlib
from functools import lru_cache
from typing import List

import mongomock as pymongo
import uvicorn
from fastapi import FastAPI, HTTPException
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel

from .models import Extractor, FileType
from .utils import load_registry_collection

__api_version__ = "0.2.0"
__api_version__ = "0.3.0"


app = FastAPI(
Expand All @@ -25,13 +28,49 @@

db: pymongo.Database = pymongo.MongoClient().registry

templates = Jinja2Templates(directory=pathlib.Path(__file__).parent / "templates")

@app.get("/filetypes")
app.mount(
"/static",
StaticFiles(directory=pathlib.Path(__file__).parent / "static"),
name="static",
)


class JSONAPIResponse(BaseModel):
data: list[FileType] | list[Extractor] | FileType | Extractor
meta: dict | None = None


class FileTypeEntryResponse(JSONAPIResponse):
data: list[FileType]


class ExtractorEntryResponse(JSONAPIResponse):
data: list[Extractor]


class SingleFileTypeEntryResponse(JSONAPIResponse):
data: FileType


class SingleExtractorEntryResponse(JSONAPIResponse):
data: Extractor


@api.get("/filetypes", response_model=FileTypeEntryResponse)
def get_filetypes():
return list(db.filetypes.find(projection={"_id": 0}))
return {"data": list(db.filetypes.find(projection={"_id": 0})), "meta": _get_info()}


@app.get("/filetypes/{id}", response_model=FileType)
@app.get("/filetypes", response_class=HTMLResponse)
def get_filetypes_html(request: Request):
return templates.TemplateResponse(
"filetypes.html", {"request": request, "data": get_filetypes()["data"]}
)


@api.get("/filetypes/{id}", response_model=SingleFileTypeEntryResponse)
def get_filetype(id: str):
result = db.filetypes.find_one({"id": id.lower()}, projection={"_id": 0})

Expand All @@ -42,39 +81,73 @@ def get_filetype(id: str):
raise HTTPException(status_code=404, detail="File type not found")

result["registered_extractors"] = {_["id"] for _ in registered_extractors}
return result
return {"data": result, "meta": _get_info()}


@app.get("/filetypes/{id}", response_class=HTMLResponse)
def get_filetype_html(request: Request, id: str):
try:
ft = get_filetype(id)["data"]
except HTTPException:
ft = None
return templates.TemplateResponse("filetype.html", {"request": request, "ft": ft})


@app.get("/search-filetypes", response_model=List[FileType])
@api.get("/search-filetypes", response_model=FileTypeEntryResponse)
def search_file_types(query: str):
results = list(db.filetypes.find({"$text": query}, projection={"_id": 0}))
return results
return {"data": results, "meta": _get_info()}


@app.get("/extractors")
@api.get("/extractors", response_model=ExtractorEntryResponse)
def get_extractors():
return list(db.extractors.find({}, projection={"_id": 0}))
return {
"data": list(db.extractors.find({}, projection={"_id": 0})),
"meta": _get_info(),
}


@app.get("/extractors/{id}", response_model=Extractor)
@app.get("/extractors")
def get_extractors_html(request: Request):
return templates.TemplateResponse(
"extractors.html", {"request": request, "data": get_extractors()["data"]}
)


@api.get("/extractors/{id}", response_model=SingleExtractorEntryResponse)
def get_extractor(id: str):
result = db.extractors.find_one({"id": id.lower()}, projection={"_id": 0})
if not result:
raise HTTPException(status_code=404, detail="File type not found")
return result
return {"data": result, "meta": _get_info()}


@app.get("/extractors/{id}")
def get_extractor_html(request: Request, id: str):
try:
ex = get_extractor(id)["data"]
except HTTPException:
ex = None
return templates.TemplateResponse("extractor.html", {"request": request, "ex": ex})

@app.get("/search-extractors", response_model=List[Extractor])

@api.get("/search-extractors", response_model=ExtractorEntryResponse)
def search_extractors(query: str):
results = list(db.extractors.find({"$text": query}, projection={"_id": 0}))
return results
return {"data": results, "meta": _get_info()}


@app.get("/")
@api.get("/")
def get_info():
return _get_info()


@app.get("/", response_class=HTMLResponse)
def get_index_html(request: Request):
"""Simply return the file types list as the "homepage" for now."""
return templates.TemplateResponse("index.html", {"request": request})


@lru_cache(maxsize=1)
def _get_info():
with open(pathlib.Path(__file__).parent / "data" / "meta.json") as f:
Expand All @@ -91,9 +164,9 @@ async def load_data():
_get_info()


api.mount(f"/{__api_version__}", app)
api.mount("/", app)
app.mount(f"/api/v{__api_version__}", api)
app.mount("/api/", api)


if __name__ == "__main__":
uvicorn.run("__main__:api")
uvicorn.run("__main__:app")
15 changes: 15 additions & 0 deletions marda_registry/static/background.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading