From bb82f20a47a17d09a9205fa891f07d40ba8ed8bf Mon Sep 17 00:00:00 2001 From: HumanoidSandvichDispenser Date: Sat, 30 Nov 2024 19:01:23 -0800 Subject: [PATCH] feat: Add delete event functionality - Add delete_event endpoint in backend-flask - Add cascade delete-orphan to Event model relationship --- .../src/client/services/DefaultService.ts | 20 +++++++++++++ availabili.tf/src/stores/teams/events.ts | 29 ++++++------------- backend-flask/events.py | 27 ++++++++++++++++- backend-flask/models/event.py | 6 +++- 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/availabili.tf/src/client/services/DefaultService.ts b/availabili.tf/src/client/services/DefaultService.ts index 2963ff8..9acdd5a 100644 --- a/availabili.tf/src/client/services/DefaultService.ts +++ b/availabili.tf/src/client/services/DefaultService.ts @@ -110,6 +110,26 @@ export class DefaultService { }, }); } + /** + * delete_event + * @param eventId + * @returns void + * @throws ApiError + */ + public deleteEvent( + eventId: number, + ): CancelablePromise { + return this.httpRequest.request({ + method: 'DELETE', + url: '/api/events/{event_id}', + path: { + 'event_id': eventId, + }, + errors: { + 422: `Unprocessable Content`, + }, + }); + } /** * get_event * @param eventId diff --git a/availabili.tf/src/stores/teams/events.ts b/availabili.tf/src/stores/teams/events.ts index 7815e01..c6b8eed 100644 --- a/availabili.tf/src/stores/teams/events.ts +++ b/availabili.tf/src/stores/teams/events.ts @@ -7,22 +7,8 @@ import { computed, reactive } from "vue"; export const useTeamsEventsStore = defineStore("teamsEvents", () => { const clientStore = useClientStore(); const client = clientStore.client; - //const eventsStore = useEventsStore(); const teamEvents = reactive<{ [teamId: number]: EventWithPlayerSchema[] }>({ }); - //const teamEvents = computed(() => { - // console.log("Recomputing teamEvents"); - - // // map events to objects with teamId as key, and array of events as value - // return eventsStore.events - // .reduce((acc, event) => { - // if (!acc[event.teamId]) { - // acc[event.teamId] = []; - // } - // acc[event.teamId].push(event); - // return acc; - // }, { } as { [teamId: number]: EventSchema[] }); - //}); function fetchTeamEvents(teamId: number) { return clientStore.call( @@ -35,8 +21,8 @@ export const useTeamsEventsStore = defineStore("teamsEvents", () => { ); } - function attendEvent(eventId: number) { - client.default.attendEvent(eventId) + async function attendEvent(eventId: number) { + return client.default.attendEvent(eventId) .then((response) => { let index = teamEvents[response.event.teamId] .findIndex((event) => event.event.id == response.event.id); @@ -44,8 +30,8 @@ export const useTeamsEventsStore = defineStore("teamsEvents", () => { }); } - function unattendEvent(eventId: number) { - client.default.unattendEvent(eventId) + async function unattendEvent(eventId: number) { + return client.default.unattendEvent(eventId) .then((response) => { let index = teamEvents[response.event.teamId] .findIndex((event) => event.event.id == response.event.id); @@ -53,8 +39,11 @@ export const useTeamsEventsStore = defineStore("teamsEvents", () => { }); } - function deleteEvent(eventId: number) { - // TODO: implement + async function deleteEvent(eventId: number) { + return client.default.deleteEvent(eventId) + .then(() => { + + }); } return { diff --git a/backend-flask/events.py b/backend-flask/events.py index ce53ec9..3921adf 100644 --- a/backend-flask/events.py +++ b/backend-flask/events.py @@ -102,6 +102,8 @@ def create_event(player_team: PlayerTeam, team_id: int, json: CreateEventJson, * event.description = json.description event.start_time = json.start_time + assert_team_authority(player_team) + db.session.add(event) db.session.flush() db.session.refresh(event) @@ -270,7 +272,9 @@ def update_event(player: Player, event_id: int, json: UpdateEventJson, **_): event = db.session.query(Event).where(Event.id == event_id).one_or_none() if not event: abort(404) - assert_team_membership(player, event.team) + + player_team = assert_team_membership(player, event.team) + assert_team_authority(player_team) for player_event in event.players: player_team = player_event.player_team @@ -288,3 +292,24 @@ def update_event(player: Player, event_id: int, json: UpdateEventJson, **_): event.update_discord_message() return EventSchema.from_model(event).dict(by_alias=True), 200 + +@api_events.delete("/") +@spec.validate( + resp=Response( + HTTP_204=None, + ), + operation_id="delete_event", +) +@requires_authentication +def delete_event(player: Player, event_id: int, **_): + event = db.session.query(Event).where(Event.id == event_id).one_or_none() + if not event: + abort(404) + + player_team = assert_team_membership(player, event.team) + assert_team_authority(player_team) + + db.session.delete(event) + db.session.commit() + + return make_response({ }, 204) diff --git a/backend-flask/models/event.py b/backend-flask/models/event.py index 067a4ab..9806540 100644 --- a/backend-flask/models/event.py +++ b/backend-flask/models/event.py @@ -28,7 +28,11 @@ class Event(app_db.BaseModel): discord_message_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True) team: Mapped["Team"] = relationship("Team", back_populates="events") - players: Mapped[list["PlayerEvent"]] = relationship("PlayerEvent", back_populates="event") + players: Mapped[list["PlayerEvent"]] = relationship( + "PlayerEvent", + back_populates="event", + cascade="all, delete-orphan" + ) __table_args__ = ( UniqueConstraint("team_id", "name", "start_time"),