diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index ef365cd..320327a 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -2,7 +2,6 @@ package database import ( "embed" - "os" "path/filepath" "ttime/internal/types" @@ -19,7 +18,7 @@ type Database interface { PromoteToAdmin(username string) error GetUserId(username string) (int, error) AddProject(name string, description string, username string) error - Migrate(dirname string) error + Migrate() error GetProjectId(projectname string) (int, error) AddWeeklyReport(projectName string, userName string, week int, developmentTime int, meetingTime int, adminTime int, ownWorkTime int, studyTime int, testingTime int) error AddUserToProject(username string, projectname string, role string) error @@ -259,13 +258,18 @@ func (d *Db) GetAllUsersApplication() ([]string, error) { // Reads a directory of migration files and applies them to the database. // This will eventually be used on an embedded directory -func (d *Db) Migrate(dirname string) error { +func (d *Db) Migrate() error { // Read the embedded scripts directory files, err := scripts.ReadDir("migrations") if err != nil { return err } + if len(files) == 0 { + println("No migration files found") + return nil + } + tr := d.MustBegin() // Iterate over each SQL file and execute it @@ -275,8 +279,7 @@ func (d *Db) Migrate(dirname string) error { } // This is perhaps not the most elegant way to do this - sqlFile := filepath.Join("migrations", file.Name()) - sqlBytes, err := os.ReadFile(sqlFile) + sqlBytes, err := scripts.ReadFile("migrations/" + file.Name()) if err != nil { return err } diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 5438d66..9124c45 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -8,7 +8,7 @@ import ( func setupState() (Database, error) { db := DbConnect(":memory:") - err := db.Migrate("../../migrations") + err := db.Migrate() if err != nil { return nil, err } diff --git a/backend/main.go b/backend/main.go index 9ba2556..7f0f81e 100644 --- a/backend/main.go +++ b/backend/main.go @@ -43,6 +43,11 @@ func main() { // Connect to the database db := database.DbConnect(conf.DbPath) + // Migrate the database + if err = db.Migrate(); err != nil { + fmt.Println("Error migrating database: ", err) + } + // Get our global state gs := handlers.NewGlobalState(db) // Create the server diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 248ad37..c1f237c 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -1,5 +1,10 @@ -import { NewProject, Project } from "../Types/Project"; -import { NewUser, User } from "../Types/Users"; +import { + NewWeeklyReport, + NewUser, + User, + Project, + NewProject, +} from "../Types/goTypes"; // This type of pattern should be hard to misuse interface APIResponse { @@ -20,8 +25,20 @@ interface API { project: NewProject, token: string, ): Promise>; + /** Submit a weekly report */ + submitWeeklyReport( + project: NewWeeklyReport, + token: string, + ): Promise>; /** Renew the token */ renewToken(token: string): Promise>; + /** Gets all the projects of a user*/ + getUserProjects( + username: string, + token: string, + ): Promise>; + /** Login */ + login(NewUser: NewUser): Promise>; } // Export an instance of the API @@ -117,4 +134,87 @@ export const api: API = { return { success: false, message: "Failed to renew token" }; } }, + + async getUserProjects(token: string): Promise> { + try { + const response = await fetch("/api/getUserProjects", { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + }); + + if (!response.ok) { + return Promise.resolve({ + success: false, + message: "Failed to get user projects", + }); + } else { + const data = (await response.json()) as Project[]; + return Promise.resolve({ success: true, data }); + } + } catch (e) { + return Promise.resolve({ + success: false, + message: "Failed to get user projects", + }); + } + }, + + async submitWeeklyReport( + project: NewWeeklyReport, + token: string, + ): Promise> { + try { + return fetch("/api/submitWeeklyReport", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + body: JSON.stringify(project), + }) + .then((response) => { + if (!response.ok) { + return { + success: false, + message: "Failed to submit weekly report", + }; + } else { + return response.json(); + } + }) + .then((data: Project) => { + return { success: true, data }; + }); + } catch (e) { + return Promise.resolve({ + success: false, + message: "Failed to submit weekly report", + }); + } + }, + + async login(NewUser: NewUser): Promise> { + try { + const response = await fetch("/api/login", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(NewUser), + }); + + if (!response.ok) { + return { success: false, message: "Failed to login" }; + } else { + const data = (await response.json()) as { token: string }; // Fix: Change the type of 'data' + const token = data.token; + return { success: true, data: token }; + } + } catch (e) { + return { success: false, message: "Failed to login" }; + } + }, }; diff --git a/frontend/src/Components/Register.tsx b/frontend/src/Components/Register.tsx index e4a3ba0..0c0fcd0 100644 --- a/frontend/src/Components/Register.tsx +++ b/frontend/src/Components/Register.tsx @@ -4,6 +4,32 @@ import { api } from "../API/API"; import Logo from "../assets/Logo.svg"; import Button from "./Button"; +function InputField(props: { + label: string; + type: string; + value: string; + onChange: (e: React.ChangeEvent) => void; +}): JSX.Element { + return ( +
+ + +
+ ); +} + export default function Register(): JSX.Element { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); @@ -14,7 +40,7 @@ export default function Register(): JSX.Element { }; return ( -
+
Register New User -
- - { - setUsername(e.target.value); - }} - /> -
-
- - { - setPassword(e.target.value); - }} - /> -
+ { + setUsername(e.target.value); + }} + /> + { + setPassword(e.target.value); + }} + />
+
); } - -export default NewTimeReport; diff --git a/frontend/src/Pages/AdminPages/AdminAddUser.tsx b/frontend/src/Pages/AdminPages/AdminAddUser.tsx index 5e8c01f..c0f9492 100644 --- a/frontend/src/Pages/AdminPages/AdminAddUser.tsx +++ b/frontend/src/Pages/AdminPages/AdminAddUser.tsx @@ -1,18 +1,16 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; +import Register from "../../Components/Register"; function AdminAddUser(): JSX.Element { - const content = <>; + const content = ( + <> + + + ); const buttons = ( <> -