Skip to content

Commit

Permalink
feat: Added functions for reopening projects and fetching closed proj…
Browse files Browse the repository at this point in the history
…ects (#152)

* feat: Added project related functions
* feat: Add route for setting project status
* build: add build folder to avoid ownership problems
* fix: Add error handling for invalid status
* feat: Add enum for status filter
* feat: Add custom exceptions for bad status

Co-authored-by: Alex Garel <alex@garel.org>
  • Loading branch information
aadarsh-ram and alexgarel authored Jan 4, 2023
1 parent b74f220 commit a714cf4
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 20 deletions.
55 changes: 48 additions & 7 deletions backend/editor/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
import os

# Required imports
# ----------------------------------------------------------------------------#
# ------------------------------------------------------------------------------------#
from datetime import datetime
from enum import Enum
from typing import Optional

# FastAPI
from fastapi import BackgroundTasks, FastAPI, HTTPException, Request, Response, status
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.responses import FileResponse, JSONResponse

# DB helper imports
from . import graph_db
Expand All @@ -23,7 +27,7 @@
# Data model imports
from .models import Footer, Header

# ----------------------------------------------------------------------------#
# -----------------------------------------------------------------------------------#

# Setup logs
logging.basicConfig(
Expand Down Expand Up @@ -97,6 +101,31 @@ def file_cleanup(filepath):
raise HTTPException(status_code=500, detail="Taxonomy file not found for deletion")


class StatusFilter(str, Enum):
"""
Enum for project status filter
"""

OPEN = "OPEN"
CLOSED = "CLOSED"


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
reformatted_errors = []
for pydantic_error in exc.errors():
# Add custom message for status filter
if pydantic_error["loc"] == ("query", "status"):
pydantic_error[
"msg"
] = "Status filter must be one of: OPEN, CLOSED or should be omitted"
reformatted_errors.append(pydantic_error)
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content=jsonable_encoder({"detail": "Invalid request", "errors": reformatted_errors}),
)


# Get methods


Expand All @@ -115,13 +144,25 @@ async def pong(response: Response):


@app.get("/projects")
async def list_all_projects(response: Response):
async def list_all_projects(response: Response, status: Optional[StatusFilter] = None):
"""
List all open projects created in the Taxonomy Editor
List projects created in the Taxonomy Editor with a status filter
"""
# Listing all projects doesn't require a taoxnomy name or branch name
# Listing all projects doesn't require a taxonomy name or branch name
taxonony = TaxonomyGraph("", "")
result = list(taxonony.list_existing_projects())
result = list(taxonony.list_projects(status))
return result


@app.get("{taxonomy_name}/{branch}/set-project-status")
async def set_project_status(
response: Response, branch: str, taxonomy_name: str, status: Optional[StatusFilter] = None
):
"""
Set the status of a Taxonomy Editor project
"""
taxonony = TaxonomyGraph(branch, taxonomy_name)
result = taxonony.set_project_status(status)
return result


Expand Down
27 changes: 16 additions & 11 deletions backend/editor/entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def github_export(self):
# Create a new transaction context
with TransactionCtx():
result = self.export_to_github(filepath)
self.close_project()
self.set_project_status(status="CLOSED")
return result

def export_to_github(self, filename):
Expand Down Expand Up @@ -229,28 +229,33 @@ def create_project(self, description):
}
get_current_transaction().run(query, params)

def close_project(self):
def set_project_status(self, status):
"""
Helper function to close a Taxonomy Editor project and updates project status as "CLOSED"
Helper function to update a Taxonomy Editor project status
"""
query = """
MATCH (n:PROJECT)
WHERE n.id = $project_name
SET n.status = $status
"""
params = {"project_name": self.project_name, "status": "CLOSED"}
params = {"project_name": self.project_name, "status": status}
get_current_transaction().run(query, params)

def list_existing_projects(self):
def list_projects(self, status=None):
"""
Helper function for listing all existing projects created in Taxonomy Editor
"""
query = """
MATCH (n:PROJECT)
WHERE n.status = "OPEN" RETURN n
ORDER BY n.created_at
"""
result = get_current_transaction().run(query)
query = ["""MATCH (n:PROJECT)\n"""]
params = {}
if status is not None:
# List only projects matching status
query.append("""WHERE n.status = $status\n""")
params["status"] = status

query.append("""RETURN n\n""")
query.append("""ORDER BY n.created_at\n""") # Sort by creation date

result = get_current_transaction().run("".join(query), params)
return result

def add_node_to_end(self, label, entry):
Expand Down
3 changes: 2 additions & 1 deletion taxonomy-editor-frontend/build/.empty
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
# keep this file to have the folder in git to avoid permissions problem (if docker-compose creates the build directory, it will be owned by root
# keep this folder to avoid having docker-compose create it with root owner

2 changes: 1 addition & 1 deletion taxonomy-editor-frontend/src/pages/gotoproject/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { toSnakeCase, toTitleCase } from "../../components/interConvertNames";

const GotoProject = () => {
/* eslint no-unused-vars: ["error", { varsIgnorePattern: "^__" }] */
const { data: incomingData, isPending, isError, __isSuccess, errorMessage } = useFetch(`${API_URL}projects`);
const { data: incomingData, isPending, isError, __isSuccess, errorMessage } = useFetch(`${API_URL}projects?status=OPEN`);
const [projectData, setProjectData] = useState([]);
const navigate = useNavigate();

Expand Down

0 comments on commit a714cf4

Please sign in to comment.