Skip to content

Commit

Permalink
Merge pull request #5 from kamyabnazari/kn-adding-dashboard-page
Browse files Browse the repository at this point in the history
Kn adding dashboard page
  • Loading branch information
kamyabnazari authored May 26, 2023
2 parents 755f685 + 3a918b4 commit 07ffe65
Show file tree
Hide file tree
Showing 32 changed files with 463 additions and 149 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pip install -r requirements.txt
To run the plugin, enter the following command:

```bash
uvicorn main:app --reload
python main.py
```

Expand Down
2 changes: 1 addition & 1 deletion backend/Dockerfile.backend
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
FROM python:3.8-slim-buster
WORKDIR /app
ADD . /app
RUN pip install --no-cache-dir fastapi uvicorn
RUN pip install -r requirements.txt --no-cache-dir
EXPOSE 5003
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "5003"]
Binary file modified backend/logo.png
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 36 additions & 24 deletions backend/main.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,56 @@
import os

# Importing fastAPI
from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List
import uvicorn

class Todo(BaseModel):
todo: str
# Importing langchain
from langchain import LLMChain
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate, ChatPromptTemplate

from dotenv import load_dotenv

load_dotenv()

apikey = os.getenv("OPENAI_API_KEY")
# use the gpt-3.5-turbo LLM
openai_model = ChatOpenAI(openai_api_key=apikey, model_name = 'gpt-3.5-turbo')

chat_prompt = ChatPromptTemplate.from_template("tell me a joke about {subject}")
chat_prompt_value = chat_prompt.format_prompt(subject="soccer")

llm_chain = LLMChain(
prompt = chat_prompt,
llm = openai_model
)

app = FastAPI()

app.add_middleware(
CORSMiddleware,
allow_origins=["https://chat.openai.com"],
allow_origins=["https://chat.openai.com", "http://localhost:8080", "http://localhost:5173"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

_TODOS = {}

@app.get("/")
async def read_root():
return {"message": "Hello!"}

@app.post("/todos/{username}", response_model=Todo)
async def add_todo(username: str, todo: Todo):
_TODOS.setdefault(username, []).append(todo.todo)
return todo

@app.get("/todos/{username}", response_model=List[str])
async def get_todos(username: str):
return _TODOS.get(username, [])

@app.delete("/todos/{username}")
async def delete_todo(username: str, todo: Todo):
if username in _TODOS and todo.todo in _TODOS[username]:
_TODOS[username].remove(todo.todo)
return JSONResponse(content='OK', status_code=200)
raise HTTPException(status_code=404, detail="Todo not found")
return {"message": "This is the backend for ADM Project!"}

@app.get("/api")
async def read_api_root():
return {"message": "Welcome to the ADM Backend!"}

@app.get("/api/joke")
async def read_():
# joke question
question = "Tell me a joke"
response = llm_chain.run(question)
return {"message": response}

@app.get("/logo.png")
async def logo():
Expand Down
7 changes: 6 additions & 1 deletion backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
quart
quart-cors
quart-cors
langchain
fastapi
uvicorn
openai
python-dotenv
11 changes: 10 additions & 1 deletion frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"type": "module",
"dependencies": {
"daisyui": "^2.51.6",
"pocketbase": "^0.15.0"
"pocketbase": "^0.15.0",
"zod": "^3.21.4"
}
}
8 changes: 4 additions & 4 deletions frontend/src/lib/components/footer.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<footer class="footer footer-center text-base-content bg-base-300 sticky bottom-0 rounded p-10">
<footer class="footer footer-center text-base-content bg-base-100 bottom-0 p-10">
<div class="grid grid-flow-col gap-4">
<a href="/" class="link link-hover">Documentation</a>
<a href="/" class="link link-hover">About us</a>
<a href="/" class="link link-hover">Contact</a>
<a href="/documentation" class="link link-hover">Documentation</a>
<a href="/about-us" class="link link-hover">About us</a>
<a href="/contact" class="link link-hover">Contact</a>
</div>
<div>
<p>Copyright © 2023</p>
Expand Down
123 changes: 78 additions & 45 deletions frontend/src/lib/components/header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,93 @@
import IconMenu from '~icons/solar/hamburger-menu-outline';
import IconMoon from '~icons/solar/moon-outline';
import IconSun from '~icons/solar/sun-2-outline';
import { onMount, onDestroy } from 'svelte';
import { get, writable } from 'svelte/store';
const theme = writable('lofi');
const toggleTheme = () => {
theme.update((currentTheme) => {
const newTheme = currentTheme === 'black' ? 'lofi' : 'black';
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
return newTheme;
});
};
onMount(() => {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
theme.set(savedTheme);
}
});
onDestroy(() => {
theme.set('black'); // Reset the theme to default on component destruction
});
$: isChecked = $theme === 'black'; // Computed property for checkbox state
function handleCheckboxChange() {
isChecked;
toggleTheme();
}
</script>

<div class="navbar text-base-content bg-base-300 sticky left-0 top-0">
<div class="navbar text-base-content bg-base-100 sticky left-0 top-0 p-4 shadow-sm">
<div class="flex-none">
<label for="application-drawer" class="btn btn-square btn-ghost drawer-button">
<IconMenu style="font-size: 1.5em" /></label
>
<label for="application-drawer" class="btn btn-square btn-ghost drawer-button lg:hidden">
<IconMenu style="font-size: 1.5em" />
</label>
</div>
<div class="flex-1">
<a class="btn-ghost btn text-xl normal-case" href="/">ADM</a>
</div>
<div class="flex-none">
{#if $currentUser}
<div class="dropdown dropdown-end">
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<!-- svelte-ignore a11y-label-has-associated-control -->
<label tabindex="0" class="btn btn-ghost btn-circle avatar">
<div class="w-8 rounded-full">
<img src="/example-avatar-image.jpeg" alt="Example Avatar" />
</div>
</label>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<ul
tabindex="0"
class="menu menu-compact dropdown-content bg-base-100 rounded-box mt-3 w-52 p-2 shadow"
>
<li><a href="/">{$currentUser.email}</a></li>
<li>
<a href="/" class="justify-between"> Profile </a>
</li>
<li><a href="/">Settings</a></li>
<li>
<form
method="POST"
action="/logout"
use:enhance={() => {
return async ({ result }) => {
pb.authStore.clear();
await applyAction(result);
};
}}
>
<button>Log out</button>
</form>
</li>
</ul>
</div>
{:else}
<a href="/login"><button class="btn btn-ghost">Login</button></a>
{/if}
{#await $currentUser then user}
{#if user}
<div class="dropdown dropdown-end">
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<!-- svelte-ignore a11y-label-has-associated-control -->
<label tabindex="0" class="btn btn-ghost btn-square avatar">
<div class="ring-primary ring-offset-base-100 w-8 rounded-md ring-2 ring-offset-2">
<img src="/example-avatar-image.jpeg" alt="Example Avatar" />
</div>
</label>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<ul
tabindex="0"
class="menu menu-compact dropdown-content bg-base-100 rounded-box mt-3 w-52 p-2 shadow"
>
<li><a href="/profile">Profile</a></li>
<li><a href="/settings">Settings</a></li>
<li>
<form
method="POST"
action="/logout"
use:enhance={() => {
return async ({ result }) => {
pb.authStore.clear();
await applyAction(result);
};
}}
>
<button>Log out</button>
</form>
</li>
</ul>
</div>
{:else}
<a href="/login"><button class="btn btn-ghost">Login</button></a>
<a href="/register"><button class="btn btn-ghost">Register</button></a>
{/if}
{:catch error}
<p>Error loading user data: {error.message}</p>
{/await}
</div>
<label class="swap swap-rotate px-4">
<input type="checkbox" />
<IconSun class="swap-on fill-current" style="font-size: 1.5em" />
<IconMoon class="swap-off fill-current" style="font-size: 1.5em" />
<input type="checkbox" bind:checked={isChecked} on:change={handleCheckboxChange} />
<IconSun class="swap-off fill-current" style="font-size: 1.5em" />
<IconMoon class="swap-on fill-current" style="font-size: 1.5em" />
</label>
</div>
8 changes: 8 additions & 0 deletions frontend/src/lib/schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { z } from 'zod';

export const loginUserSchema = z.object({
email: z
.string({ required_error: 'Email is required' })
.email({ message: 'Email must be a valid email.' }),
password: z.string({ required_error: 'Password is required' })
});
20 changes: 20 additions & 0 deletions frontend/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
export const validateData = async (formData, schema) => {
const body = Object.fromEntries(formData);
try {
const data = schema.parse(body);
return {
formData: data,
errors: null
};
} catch (err) {
console.log(err);
const errors = err.flatten();
return {
formData: body,
errors
};
}
};
*/
21 changes: 19 additions & 2 deletions frontend/src/routes/(auth)/login/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import { redirect } from '@sveltejs/kit';
import type { Actions } from './$types';
import type { Actions, PageServerLoad } from './$types';

export const actions: Actions = {
default: async ({ locals, request }) => {
/*
const { formData, errors } = await validateData(await request.formData(), loginUserSchema);
if (errors) {
return invalid(400, {
data: formData,
errors: errors.fieldErrors
});
}
*/

const data = Object.fromEntries(await request.formData()) as {
email: string;
password: string;
Expand All @@ -15,6 +26,12 @@ export const actions: Actions = {
throw e;
}

throw redirect(303, '/');
throw redirect(303, '/dashboard');
}
};

export const load: PageServerLoad = async ({ locals }) => {
if (locals.user) {
throw redirect(303, '/dashboard');
}
};
Loading

0 comments on commit 07ffe65

Please sign in to comment.