Skip to content

Commit

Permalink
refactor: migrate event and project components to SDK
Browse files Browse the repository at this point in the history
fix: validate strings in events and projects
refactor: only accept project event as list of 1 string matching record regex
  • Loading branch information
slashtechno committed Dec 28, 2024
1 parent 3583007 commit 30be183
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 42 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[svelte]": {
"editor.defaultFormatter": "svelte.svelte-vscode"
},
}
8 changes: 5 additions & 3 deletions backend/showcase/db/event.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, StringConstraints
from typing import Annotated, List, Optional
from pydantic.json_schema import SkipJsonSchema


# https://docs.pydantic.dev/1.10/usage/schema/#field-customization
class EventCreationPayload(BaseModel):
name: str
description: Optional[str] = None
name: Annotated[str, StringConstraints(
min_length=1
)]
description: Optional[Annotated[str, StringConstraints(max_length=500)]]

# Owner is inferred from the current user (token)
# https://github.com/fastapi/fastapi/discussions/7585#discussioncomment-7573510
Expand Down
10 changes: 5 additions & 5 deletions backend/showcase/db/project.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
from pydantic import BaseModel, HttpUrl, Field, StringConstraints
from pydantic.json_schema import SkipJsonSchema
from typing import Annotated, List, Optional
from annotated_types import Len

# https://docs.pydantic.dev/1.10/usage/schema/#field-customization
class ProjectCreationPayload(BaseModel):
name: str
name: Annotated[str, StringConstraints(
min_length=1
)]
readme: HttpUrl
repo: HttpUrl
image_url: HttpUrl
description: Optional[str] = None

owner: Annotated[SkipJsonSchema[List[str]], Field()] = None
# https://docs.pydantic.dev/latest/api/types/#pydantic.types.constr--__tabbed_1_2
event: List[str] | Annotated[str, StringConstraints(
pattern=r'^rec\w*$'
)]
# join_code: SkipJsonSchema[str] = None
event: Annotated[List[Annotated[str, StringConstraints(pattern=r"^rec\w*$")]], Len(min_length=1, max_length=1)] = None

def model_dump(self, *args, **kwargs):
data = super().model_dump(*args, **kwargs)
Expand Down
92 changes: 85 additions & 7 deletions frontend/package-lock.json

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

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
"prettier": "3.4.2",
"prettier-plugin-svelte": "^3.3.2",
"svelte": "^5.0.0",
"svelte-check": "^4.1.1",
"tailwindcss": "^3.4.9",
"vite": "^5.0.3"
},
"dependencies": {
"@hey-api/client-fetch": "^0.5.7",
"pocketbase": "^0.21.5",
"svelte-sonner": "^0.3.28"
}
}
3 changes: 2 additions & 1 deletion frontend/src/lib/apiErrorCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export function handleError(error: HTTPValidationError | ErrorWithDetail | Error
console.error("Error", error);
if (error && typeof error === "object" && "detail" in error) {
if (Array.isArray(error?.detail)) {
const invalidFields = error.detail.map((e) => e.msg);
// const invalidFields = error.detail.map((e) => e.msg);
const invalidFields = error.detail.map((e) => `${e.loc.join(".")}: ${e.msg}`);
toast(invalidFields.join(" | "));
} else if (typeof error?.detail === "string") {
toast(error.detail);
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/lib/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@ export type CheckAuthResponse = {

export type ComplexEvent = {
name: string;
description?: string | null;
description: string | null;
join_code: string;
id: string;
attendees?: Array<string>;
};

export type Event = {
name: string;
description?: string | null;
description: string | null;
id: string;
};

export type EventCreationPayload = {
name: string;
description?: string | null;
description: string | null;
};

export type HTTPValidationError = {
Expand All @@ -39,7 +39,7 @@ export type Project = {
repo: string;
image_url: string;
description?: string | null;
event: Array<string> | string;
event: Array<string>;
id: string;
points: number;
};
Expand All @@ -50,7 +50,7 @@ export type ProjectCreationPayload = {
repo: string;
image_url: string;
description?: string | null;
event: Array<string> | string;
event: Array<string>;
};

/**
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/lib/components/AttendEvent.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<script lang="ts">
import { api } from "$lib/api/client.svelte";
import {client} from "$lib/client/sdk.gen";
import {EventsService} from "$lib/client/sdk.gen";
import { toast } from 'svelte-sonner';
let joinCode = $state('');
// Function to create a new event
async function attendEvent() {
try {
await api.attendEvent(joinCode);
await EventsService.attendEventEventsAttendPost({
query: { join_code: joinCode },
throwOnError: true,
});
toast('Joined event successfully');
// Reset join code to empty string
joinCode = '';
Expand Down
9 changes: 4 additions & 5 deletions frontend/src/lib/components/CreateEvent.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { api } from "$lib/api/client.svelte";
import { handleError } from "$lib/apiErrorCheck";
import { EventsService } from "$lib/client";
import { toast } from 'svelte-sonner';
// TODO: Use the object instead of individual variables
let eventName = $state('');
Expand All @@ -8,13 +9,11 @@
// Function to create a new event
async function createEvent() {
try {
// TODO: Add description and other fields
const event = { name: eventName, description: eventDescription };
await api.createEvent(event);
await EventsService.createEventEventsPost({ body: event, throwOnError: true });
toast('Event created successfully');
} catch (err) {
console.error(err);
toast(JSON.stringify(err));
handleError(err);
}
}
</script>
Expand Down
31 changes: 20 additions & 11 deletions frontend/src/lib/components/CreateProject.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
<script lang="ts">
import { api } from "$lib/api/client.svelte";
import {EventsService, ProjectsService} from "$lib/client/sdk.gen";
import type { ProjectCreationPayload, Event} from "$lib/client";
import { toast } from 'svelte-sonner';
import type { Event, ProjectCreationPayload } from "$lib/api/types";
import { user } from "$lib/user.svelte";
import { get } from 'svelte/store';
import { handleError } from "$lib/apiErrorCheck";
let project: ProjectCreationPayload = $state({
name: "",
readme: "https://example.com",
repo: "",
image_url: "",
description: "",
// TODO: Allow these fields to be changed
event: [""],
})
let events: Event[] = $state([]);
Expand All @@ -26,22 +25,32 @@
async function fetchEvents() {
try {
toast('Fetching events; please wait');
const userEvents = await api.getAttendingEvents();
const {data: userEvents} = await EventsService.getAttendingEventsEventsGet({throwOnError: true});
events = userEvents.attending_events;
fetchedEvents = true;
} catch (err) {
console.error(err);
toast(JSON.stringify(err));
handleError(err);
}
}
async function createProject() {
try {
await api.createProject(project);
await ProjectsService.createProjectProjectsPost({
body: project,
throwOnError: true,
});
toast('Project created successfully');
// Reset the fields
project = {
name: "",
readme: "https://example.com",
repo: "",
image_url: "",
description: "",
event: [""],
};
} catch (err) {
console.error(err);
toast(JSON.stringify(err));
handleError(err);
}
}
</script>
Expand Down
1 change: 0 additions & 1 deletion frontend/src/routes/events/[id]/rank/+page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { api } from "$lib/api/client.svelte";
import { error } from "@sveltejs/kit";
import type { PageLoad } from "./$types";
import { client, EventsService } from "$lib/client/sdk.gen";
Expand Down

0 comments on commit 30be183

Please sign in to comment.