Skip to content

Commit

Permalink
add metadata endpoint, context and hook (#4)
Browse files Browse the repository at this point in the history
* add metadata endpoint, context and hook

* clean up junk test code
  • Loading branch information
jacobfilik authored Mar 6, 2024
1 parent 1d4e9fa commit 464cc7d
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 84 deletions.
7 changes: 7 additions & 0 deletions xas-standards-api/src/xas_standards_api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
add_new_standard,
get_data,
get_file,
get_metadata,
get_standard,
select_all,
select_or_create_person,
Expand All @@ -25,6 +26,7 @@
Edge,
Element,
LicenceType,
MetadataResponse,
Review,
XASStandard,
XASStandardAdminResponse,
Expand Down Expand Up @@ -60,6 +62,11 @@ def get_session():
add_pagination(app)


@app.get("/api/metadata")
def read_metadata(session: Session = Depends(get_session)) -> MetadataResponse:
return get_metadata(session)


@app.get("/api/licences")
def read_licences(session: Session = Depends(get_session)) -> List[LicenceType]:
return list(LicenceType)
Expand Down
13 changes: 13 additions & 0 deletions xas-standards-api/src/xas_standards_api/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

from .schemas import (
Beamline,
Edge,
Element,
LicenceType,
Person,
PersonInput,
XASStandard,
Expand All @@ -30,6 +33,16 @@ def select_all(session, sql_model):
return results.unique().all()


def get_metadata(session):
output = {}
output["elements"] = select_all(session, Element)
output["edges"] = select_all(session, Edge)
output["beamlines"] = select_all(session, Beamline)
output["licences"] = list(LicenceType)

return output


def get_standard(session, id) -> XASStandard:
standard = session.get(XASStandard, id)
if standard:
Expand Down
7 changes: 7 additions & 0 deletions xas-standards-api/src/xas_standards_api/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ class BeamlineResponse(SQLModel):
facility: FacilityResponse


class MetadataResponse(SQLModel):
beamlines: List[BeamlineResponse]
elements: List[Element]
edges: List[Edge]
licences: List[str]


class XASStandardDataInput(SQLModel):
original_filename: str
transmission: bool
Expand Down
21 changes: 18 additions & 3 deletions xas-standards-client/src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import { it, describe } from "vitest";
import { render } from "@testing-library/react";
import { it, describe, vi, expect } from "vitest";
import { render, screen } from "@testing-library/react";

import App from "./App";
import { BrowserRouter } from "react-router-dom";
import axios from "axios";

vi.mock("axios");

describe("App", () => {
it("renders welcome page", () => {
vi.mocked(axios.get).mockImplementation((url) => {
switch (url) {
case "/api/beamlines":
return Promise.resolve({});
default:
return Promise.resolve({});
}
});

it("renders welcome page", async () => {
render(<App />, { wrapper: BrowserRouter });
expect(
await screen.findByText(/XAS Standards Database /i)
).toBeInTheDocument();
});
});
16 changes: 10 additions & 6 deletions xas-standards-client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ import StandardViewer from "./components/StandardViewer.tsx";
import StandardSubmission from "./components/StandardSubmission.tsx";
import WelcomePage from "./components/WelcomePage.tsx";

import { MetadataProvider } from "./contexts/MetadataContext.tsx";

function App() {
return (
<div className="mainwindow">
<Header />
<Routes>
<Route path="/" element={<WelcomePage />} />
<Route path="/view" element={<StandardViewer />} />
<Route path="/submit" element={<StandardSubmission />} />
{/* <Route path="/review" element={<ReviewPage />} /> */}
</Routes>
<MetadataProvider>
<Routes>
<Route path="/" element={<WelcomePage />} />
<Route path="/view" element={<StandardViewer />} />
<Route path="/submit" element={<StandardSubmission />} />
{/* <Route path="/review" element={<ReviewPage />} /> */}
</Routes>
</MetadataProvider>
</div>
);
}
Expand Down
2 changes: 0 additions & 2 deletions xas-standards-client/src/components/InstrumentForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { s } from "vitest/dist/reporters-1evA5lom.js";

function InstrumentForm(props) {
const beamlines = props.beamlines;
const beamlineHeader = props.beamlineHeader;
Expand Down
36 changes: 5 additions & 31 deletions xas-standards-client/src/components/StandardSubmission.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useState, useEffect } from "react";
import { useState, useContext } from "react";

import { MetadataContext } from "../contexts/MetadataContext";

import axios from "axios";
import { AxiosResponse, AxiosError } from "axios";
Expand All @@ -12,17 +14,13 @@ import InstrumentForm from "./InstrumentForm";
import CitationForm from "./CitationForm";
import AdditionalInformationForm from "./AdditionalInfoForm";

import { Edge, Element } from "../models";

import { useNavigate } from "react-router-dom";

const standards_url = "/api/standards";
const beamlines_url = "/api/beamlines";
const elements_url = "/api/elements";
const edges_url = "/api/edges";
const licences_url = "/api/licences";

function StandardSubmission() {
const { elements, edges, beamlines, licences } = useContext(MetadataContext);

const [file, setFile] = useState<File>();
const [file2, setFile2] = useState<FileList>();

Expand All @@ -39,32 +37,8 @@ function StandardSubmission() {
const [citation, setCitation] = useState("");
const [comments, setComments] = useState("");

const [beamlines, setBeamlines] = useState([]);
const [elements, setElements] = useState<Element[]>([]);
const [edges, setEdges] = useState<Edge[]>([]);
const [licences, setLicences] = useState([]);

const navigate = useNavigate();

useEffect(() => {
axios.get(beamlines_url).then((res) => {
setBeamlines(res.data);
});

axios.get(elements_url).then((res) => {
setElements(res.data);
});

axios.get(edges_url).then((res) => {
setEdges(res.data);
});

axios.get(licences_url).then((res) => {
setLicences(res.data);
setLicence(res.data[0]);
});
}, []);

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();

Expand Down
14 changes: 4 additions & 10 deletions xas-standards-client/src/components/StandardViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { useState, useEffect } from "react";
import { useState, useContext } from "react";

import XASChart from "./StandardsChart.tsx";
import axios from "axios";
import StandardsTable from "./StandardsTable.tsx";
import { Element } from "../models.ts";

import { XASStandard, XASData } from "../models.ts";
import { MetadataContext } from "../contexts/MetadataContext.tsx";

const data_url = "/api/data";
const elements_url = "/api/elements";

function StandardViewer() {
const [standards, setStandardsList] = useState<XASStandard[]>([]);

const [xasdata, setXASData] = useState<XASData | null>(null);
const [elements, setElements] = useState<Element[]>([]);
const [showTrans, setShowTrans] = useState(false);
const [showFluor, setShowFluor] = useState(false);
const [showRef, setShowRef] = useState(false);
const [contains, setContains] = useState([false, false, false]);

const { elements } = useContext(MetadataContext);

function getData(setXASData: React.Dispatch<XASData>) {
return (id: number) => {
axios.get(data_url + "/" + id).then((response) => {
Expand All @@ -40,12 +40,6 @@ function StandardViewer() {

const onClick = getData(setXASData);

useEffect(() => {
axios.get(elements_url).then((res) => {
setElements(res.data);
});
}, []);

return (
<div className="mainbody">
<StandardsTable
Expand Down
23 changes: 23 additions & 0 deletions xas-standards-client/src/contexts/MetadataContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { createContext } from "react";
import { AppMetadata } from "../models";
import useMetadata from "../hooks/useMetadata";

const MetadataContext = createContext<AppMetadata>({
elements: [],
edges: [],
beamlines: [],
licences: [],
});

function MetadataProvider(props: { children: React.ReactNode }) {
const { children } = props;
const appMetadata = useMetadata();

return (
<MetadataContext.Provider value={appMetadata}>
{children}
</MetadataContext.Provider>
);
}

export { MetadataContext, MetadataProvider };
26 changes: 26 additions & 0 deletions xas-standards-client/src/hooks/useMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useEffect, useState } from "react";
import axios from "axios";

const metadata_url = "/api/metadata";

import { AppMetadata } from "../models";

function useMetadata(): AppMetadata {
const [appMetadata, setAppMetdata] = useState<AppMetadata>({
beamlines: [],
elements: [],
edges: [],
licences: [],
});

useEffect(() => {
axios.get(metadata_url).then((res) => {
// console.log("BEAMLINE! " + res.data.name);
setAppMetdata(res.data);
});
}, []);

return appMetadata;
}

export default useMetadata;
36 changes: 5 additions & 31 deletions xas-standards-client/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,35 +43,9 @@ export interface XASStandardInput {
licence: string;
}



const emptyElement: Element = {
symbol: "",
z: -1
export interface AppMetadata {
beamlines: Beamline[];
elements: Element[];
edges: Edge[];
licences: string[];
}

const emptyEdge: Edge = {
name: "",
id: -1
}

const emptyBeamline: Beamline = {
name: "";
facility: "";
}
}


const empty: XASStandard = {
id: -1,

edge: Edge;
sample_name: string;
sample_prep: string;
sample_comp: string;
doi: string;
citation: string;
facility: string;
collection_date: string;
beamline: Beamline;
}
2 changes: 1 addition & 1 deletion xas-standards-client/src/xdifile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import XDIFile from "./xdifile";

describe("Parse info from xdi file", () =>
new Promise((done) => {
fs.readFile("test.xdi", "utf8", (err, data) => {
fs.readFile("test.xdi", "utf8", (err: any, data: string) => {
if (err) throw err;
const xdi = XDIFile.parseFile(data);

Expand Down

0 comments on commit 464cc7d

Please sign in to comment.