diff --git a/backend/init.sql b/backend/init.sql index 5d505c5e..5c56627d 100644 --- a/backend/init.sql +++ b/backend/init.sql @@ -25,7 +25,7 @@ CREATE TABLE species ( CREATE TABLE proteins ( id serial PRIMARY KEY, name text NOT NULL UNIQUE, -- user specified name of the protein (TODO: consider having a string limit) - description text, + description text, length integer, -- length of amino acid sequence mass numeric, -- mass in amu/daltons content bytea, -- stored markdown for the protein article (TODO: consider having a limit to how big this can be) @@ -46,12 +46,24 @@ CREATE TABLE users ( admin boolean NOT NULL ); + +/* +* Tutorials Table +*/ +CREATE TABLE tutorials ( + id serial PRIMARY KEY, + header text NOT NULL, + title text, + description text +); + + /* * Inserts example species into species table */ -INSERT INTO species(name) VALUES ('ganaspis hookeri'); -INSERT INTO species(name) VALUES ('leptopilina boulardi'); -INSERT INTO species(name) VALUES ('leptopilina heterotoma'); +INSERT INTO species(name) VALUES ('ganaspis hookeri'); +INSERT INTO species(name) VALUES ('leptopilina boulardi'); +INSERT INTO species(name) VALUES ('leptopilina heterotoma'); INSERT INTO species(name) VALUES ('unknown'); /* @@ -59,4 +71,11 @@ INSERT INTO species(name) VALUES ('unknown'); * Email: test * Password: test */ -INSERT INTO users(username, email, pword, admin) VALUES ('test', 'test', '$2b$12$PFoNf7YM0KNIPP8WGsJjveIOhiJjitsMtfwRcCjdcyTuqjdk/q//u', '1'); \ No newline at end of file +INSERT INTO users(username, email, pword, admin) VALUES ('test', 'test', '$2b$12$PFoNf7YM0KNIPP8WGsJjveIOhiJjitsMtfwRcCjdcyTuqjdk/q//u', '1'); + + +INSERT INTO tutorials(header, title, description) VALUES('Tutorial Page', 'General Information', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce gravida tristique est, a sollicitudin nulla varius ac. Duis sed lacus arcu. Mauris eget condimentum justo. Vestibulum iaculis cursus accumsan. Mauris eget diam consequat, viverra dui malesuada, maximus nisl. Etiam laoreet venenatis odio ut tempus. Praesent risus est, eleifend id purus non, varius rutrum nisi. Fusce sagittis lorem nec tristique efficitur. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pretium, sapien et volutpat tempus, elit urna congue massa, id consequat leo dolor in ligula. Sed vestibulum tristique eros eu aliquet.'); +INSERT INTO tutorials(header, title, description) VALUES('Tutorial 1', 'Biology', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'); +INSERT INTO tutorials(header, title, description) VALUES('Tutorial 2', 'How to Use the Site', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'); +INSERT INTO tutorials(header, title, description) VALUES('Tutorial 3', 'Other Reading', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'); + diff --git a/backend/src/api/search.py b/backend/src/api/search.py index b35488d7..36dd5dbe 100644 --- a/backend/src/api/search.py +++ b/backend/src/api/search.py @@ -111,6 +111,7 @@ def search_proteins(body: SearchProteinsBody): ], ) if entries_result is not None: + print(entries_result) return SearchProteinsResults( protein_entries=[ ProteinEntry( diff --git a/backend/src/api/tutorials.py b/backend/src/api/tutorials.py index 446a22ad..a5956612 100644 --- a/backend/src/api/tutorials.py +++ b/backend/src/api/tutorials.py @@ -1,18 +1,39 @@ from fastapi import APIRouter from ..api_types import CamelModel +from ..db import Database +import logging as log router = APIRouter() -class Tutorial(CamelModel): +class Link(CamelModel): + url: str title: str -@router.get("/tutorials", response_model=list[Tutorial]) +class Tutorial(CamelModel): + header: str | None = None + title: str | None = None + description: str | None = None + # links: list[Link] | None = None + + +class MultipleTutorials(CamelModel): + tutorials: list[Tutorial] | None = None + + +@router.get("/tutorials", response_model=MultipleTutorials | None) def get_all_tutorials(): - return [ - Tutorial(title="Tutorial 1"), - Tutorial(title="Tutorial 2"), - Tutorial(title="Tutorial 3"), - Tutorial(title="Tutorial 4"), - ] + with Database() as db: + try: + query = """SELECT header, title, description FROM tutorials""" + entries = db.execute_return(query) + if entries: + return MultipleTutorials( + tutorials=[ + Tutorial(header=header, title=title, description=description) + for header, title, description in entries + ] + ) + except Exception as e: + log.error(e) diff --git a/backend/src/setup.py b/backend/src/setup.py index 96083991..7caf927e 100644 --- a/backend/src/setup.py +++ b/backend/src/setup.py @@ -33,4 +33,5 @@ def init_fastapi_app() -> FastAPI: app = FastAPI( title="Venome Backend", generate_unique_id_function=custom_generate_unique_id ) + app = disable_cors(app) return app diff --git a/frontend/src/lib/openapi/index.ts b/frontend/src/lib/openapi/index.ts index 3a19e21e..08618b71 100644 --- a/frontend/src/lib/openapi/index.ts +++ b/frontend/src/lib/openapi/index.ts @@ -11,6 +11,7 @@ export type { EditBody } from './models/EditBody'; export type { HTTPValidationError } from './models/HTTPValidationError'; export type { LoginBody } from './models/LoginBody'; export type { LoginResponse } from './models/LoginResponse'; +export type { MultipleTutorials } from './models/MultipleTutorials'; export type { ProteinEntry } from './models/ProteinEntry'; export type { RangeFilter } from './models/RangeFilter'; export type { SearchProteinsBody } from './models/SearchProteinsBody'; diff --git a/frontend/src/lib/openapi/models/MultipleTutorials.ts b/frontend/src/lib/openapi/models/MultipleTutorials.ts new file mode 100644 index 00000000..27c1e2ef --- /dev/null +++ b/frontend/src/lib/openapi/models/MultipleTutorials.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { Tutorial } from './Tutorial'; +export type MultipleTutorials = { + tutorials?: (Array | null); +}; + diff --git a/frontend/src/lib/openapi/models/Tutorial.ts b/frontend/src/lib/openapi/models/Tutorial.ts index ac0512ad..d35904c6 100644 --- a/frontend/src/lib/openapi/models/Tutorial.ts +++ b/frontend/src/lib/openapi/models/Tutorial.ts @@ -3,6 +3,8 @@ /* tslint:disable */ /* eslint-disable */ export type Tutorial = { - title: string; + header?: (string | null); + title?: (string | null); + description?: (string | null); }; diff --git a/frontend/src/lib/openapi/services/DefaultService.ts b/frontend/src/lib/openapi/services/DefaultService.ts index 2697272c..a891dd8a 100644 --- a/frontend/src/lib/openapi/services/DefaultService.ts +++ b/frontend/src/lib/openapi/services/DefaultService.ts @@ -5,6 +5,7 @@ import type { EditBody } from '../models/EditBody'; import type { LoginBody } from '../models/LoginBody'; import type { LoginResponse } from '../models/LoginResponse'; +import type { MultipleTutorials } from '../models/MultipleTutorials'; import type { ProteinEntry } from '../models/ProteinEntry'; import type { RangeFilter } from '../models/RangeFilter'; import type { SearchProteinsBody } from '../models/SearchProteinsBody'; @@ -250,10 +251,10 @@ export class DefaultService { } /** * Get All Tutorials - * @returns Tutorial Successful Response + * @returns any Successful Response * @throws ApiError */ - public static getAllTutorials(): CancelablePromise> { + public static getAllTutorials(): CancelablePromise<(MultipleTutorials | null)> { return __request(OpenAPI, { method: 'GET', url: '/tutorials', diff --git a/frontend/src/routes/Tutorials.svelte b/frontend/src/routes/Tutorials.svelte index fb27f3b0..b00691f5 100644 --- a/frontend/src/routes/Tutorials.svelte +++ b/frontend/src/routes/Tutorials.svelte @@ -1,21 +1,68 @@ -
- {#each tutorials as tutorial} -
-

{tutorial.title}

-
- {/each} +
+
+ + {#each tutorials as tutorial} +
+ + +

{tutorial.title}

+

{tutorial.description}

+ + + + + + + + + +
+ {/each} +
diff --git a/frontend/vite.config.ts.timestamp-1710099491738-507fb678492d4.mjs b/frontend/vite.config.ts.timestamp-1710099491738-507fb678492d4.mjs new file mode 100644 index 00000000..9896cdbb --- /dev/null +++ b/frontend/vite.config.ts.timestamp-1710099491738-507fb678492d4.mjs @@ -0,0 +1,10 @@ +// vite.config.ts +import { defineConfig } from "file:///app/node_modules/vite/dist/node/index.js"; +import { svelte } from "file:///app/node_modules/@sveltejs/vite-plugin-svelte/src/index.js"; +var vite_config_default = defineConfig({ + plugins: [svelte()] +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvYXBwXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvYXBwL3ZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9hcHAvdml0ZS5jb25maWcudHNcIjtpbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tICd2aXRlJ1xyXG5pbXBvcnQgeyBzdmVsdGUgfSBmcm9tICdAc3ZlbHRlanMvdml0ZS1wbHVnaW4tc3ZlbHRlJ1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbc3ZlbHRlKCldLFxyXG59KVxyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQThMLFNBQVMsb0JBQW9CO0FBQzNOLFNBQVMsY0FBYztBQUd2QixJQUFPLHNCQUFRLGFBQWE7QUFBQSxFQUMxQixTQUFTLENBQUMsT0FBTyxDQUFDO0FBQ3BCLENBQUM7IiwKICAibmFtZXMiOiBbXQp9Cg== diff --git a/frontend/vite.config.ts.timestamp-1710126135921-7f3f0ed4d967a.mjs b/frontend/vite.config.ts.timestamp-1710126135921-7f3f0ed4d967a.mjs new file mode 100644 index 00000000..c60dec35 --- /dev/null +++ b/frontend/vite.config.ts.timestamp-1710126135921-7f3f0ed4d967a.mjs @@ -0,0 +1,10 @@ +// vite.config.ts +import { defineConfig } from "file:///app/node_modules/vite/dist/node/index.js"; +import { svelte } from "file:///app/node_modules/@sveltejs/vite-plugin-svelte/src/index.js"; +var vite_config_default = defineConfig({ + plugins: [svelte()] +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvYXBwXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvYXBwL3ZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9hcHAvdml0ZS5jb25maWcudHNcIjtpbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tICd2aXRlJ1xuaW1wb3J0IHsgc3ZlbHRlIH0gZnJvbSAnQHN2ZWx0ZWpzL3ZpdGUtcGx1Z2luLXN2ZWx0ZSdcblxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG4gIHBsdWdpbnM6IFtzdmVsdGUoKV0sXG59KVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUE4TCxTQUFTLG9CQUFvQjtBQUMzTixTQUFTLGNBQWM7QUFHdkIsSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDMUIsU0FBUyxDQUFDLE9BQU8sQ0FBQztBQUNwQixDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=