-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
428 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,52 @@ | ||
from fastapi import HTTPException, Depends | ||
from itertools import count | ||
from typing import Annotated | ||
from fastapi import File, Form, HTTPException, Depends, UploadFile | ||
from pydantic import ValidationError | ||
from sqlalchemy.orm import Session | ||
from starlette import status | ||
from src.schemas.backup import Backup_v1, make_backup | ||
from src import schemas, crud, database_utils | ||
from src.database_utils import get_db | ||
from fastapi import APIRouter | ||
|
||
router = APIRouter( | ||
prefix="/database", | ||
prefix="/db", | ||
tags=['database'] | ||
) | ||
|
||
|
||
@router.get("/backup/") | ||
async def backup_database(session: Session = Depends(get_db)) -> schemas.Page[schemas.Job]: | ||
|
||
""" Return the whole Job table, can be restored using /database/restore/ endpoint""" | ||
@router.get("/backup") | ||
async def backup(session: Session = Depends(get_db)) -> schemas.Backup_v1: | ||
|
||
# Extract the list of ALL jobs | ||
page = crud.jobCrud.get_all(session) | ||
return schemas.Page[schemas.Job]( | ||
item=list(map(lambda job: schemas.Job.model_validate(job), page.item)), | ||
item_total_count=page.item_total_count | ||
) | ||
jobs = list(map(lambda job: schemas.Job.model_validate(job), page.item)) | ||
|
||
# Return a backup with the list | ||
return make_backup(jobs) | ||
|
||
|
||
@router.post("/restore/") | ||
async def restore_database(jobs: schemas.Page[schemas.Job], session: Session = Depends(get_db)) -> str: | ||
@router.post("/restore/v1") | ||
async def restore( | ||
file: Annotated[UploadFile, File()], | ||
session: Session = Depends(get_db) | ||
) -> str: | ||
|
||
""" Restore the entire database from a large Job list. Existing data will be erased. """ | ||
|
||
if database_utils.restore(jobs, session) is False: | ||
""" Restore the entire database from a large Job list. Existing data will be erased. """ | ||
|
||
backup: schemas.Backup_v1 | ||
|
||
try: | ||
file_str = file.file.read() | ||
backup = schemas.Backup_v1.model_validate_json(file_str) | ||
except ValidationError as err: | ||
raise HTTPException( | ||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | ||
detail='Unable to restore the database') | ||
return "Database restored" | ||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, | ||
detail=err.json()) | ||
|
||
if database_utils.erase_and_restore(backup.jobs, session) is False: | ||
raise HTTPException( | ||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | ||
detail='Unable to restore the database') | ||
return f"Database restored from {file.filename}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
from .event import Event, EventCreate, EventUpdate, EventType | ||
from .job import Job, JobCreate, JobUpdate | ||
from .page import Page | ||
from .backup import Backup_v1, make_backup | ||
|
||
JobPage = Page[Job] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from datetime import datetime | ||
from typing import Literal | ||
from pydantic import BaseModel, Field | ||
from .job import Job | ||
|
||
|
||
class Backup_v1(BaseModel): | ||
version: Literal["1"] = Field() | ||
date: datetime = Field() | ||
jobs: list[Job] = Field() | ||
|
||
def make_backup(jobs: list[Job]) -> Backup_v1: | ||
return Backup_v1(jobs=jobs, date=datetime.now(), version="1") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
# !!! DO NOT COMMIT ANY PERSONNAL DATA HERE !!! | ||
#---------- use .env.local instead ------------ | ||
NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8000 | ||
#---------- use .env.local instead ------------ | ||
# !!! DO NOT COMMIT ANY PERSONNAL DATA HERE !!! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
"use client" | ||
import { Job } from "@/app/typings/api" | ||
import { Alert, Table } from "@mui/material" | ||
import TableBody from "@mui/material/TableBody" | ||
import TableCell from "@mui/material/TableCell" | ||
import TableContainer from "@mui/material/TableContainer" | ||
import TableHead from "@mui/material/TableHead" | ||
import TableRow from "@mui/material/TableRow" | ||
import moment from "moment" | ||
|
||
export type Props = { | ||
jobs: Job[] | ||
} | ||
export default function Report(props: Props) { | ||
const { jobs } = props; | ||
|
||
if ( jobs.length === 0) | ||
return ( | ||
<TableRow> | ||
<TableCell rowSpan={8}> | ||
<Alert severity="info"> | ||
No data found for the selected period | ||
</Alert> | ||
</TableCell> | ||
</TableRow> | ||
) | ||
|
||
return ( | ||
<TableContainer> | ||
<Table size="small"> | ||
<TableHead> | ||
<TableRow> | ||
<TableCell>Date</TableCell> | ||
<TableCell>Type</TableCell> | ||
<TableCell>Name</TableCell> | ||
<TableCell>Person Contacted</TableCell> | ||
|
||
<TableCell>Contact Type</TableCell> | ||
<TableCell>Contact Info</TableCell> | ||
<TableCell>Type of Work</TableCell> | ||
<TableCell>Results</TableCell> | ||
</TableRow> | ||
</TableHead> | ||
|
||
<TableBody> | ||
{jobs.flatMap((job) => ( | ||
job.events.map((event) => ( | ||
<TableRow key={`${job.id}-${event.id}`}> | ||
<TableCell>{moment(event.date).format("MM/DD/YYYY")}</TableCell> | ||
<TableCell>Employer</TableCell> | ||
<TableCell>{job.company}</TableCell> | ||
<TableCell>{event.contact_person}</TableCell> | ||
<TableCell>{event.contact_type}</TableCell> | ||
<TableCell>{event.contact_info}</TableCell> | ||
<TableCell>{job.role}</TableCell> | ||
<TableCell>{event.result}</TableCell> | ||
</TableRow> | ||
)))) | ||
} | ||
</TableBody> | ||
</Table> | ||
</TableContainer> | ||
) | ||
} |
Oops, something went wrong.