feat: Add event details in roster builder
parent
3d5d9574e3
commit
6f49053dac
|
@ -16,7 +16,8 @@ export type { CreateEventJson } from './models/CreateEventJson';
|
|||
export type { CreateTeamJson } from './models/CreateTeamJson';
|
||||
export type { EditMemberRolesJson } from './models/EditMemberRolesJson';
|
||||
export type { EventSchema } from './models/EventSchema';
|
||||
export type { EventSchemaList } from './models/EventSchemaList';
|
||||
export type { EventWithPlayerSchema } from './models/EventWithPlayerSchema';
|
||||
export type { EventWithPlayerSchemaList } from './models/EventWithPlayerSchemaList';
|
||||
export type { GetEventPlayersResponse } from './models/GetEventPlayersResponse';
|
||||
export type { PlayerEventRolesSchema } from './models/PlayerEventRolesSchema';
|
||||
export type { PlayerRoleSchema } from './models/PlayerRoleSchema';
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { EventSchema } from './EventSchema';
|
||||
export type EventSchemaList = Array<EventSchema>;
|
|
@ -0,0 +1,11 @@
|
|||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { EventSchema } from './EventSchema';
|
||||
import type { PlayerEventRolesSchema } from './PlayerEventRolesSchema';
|
||||
export type EventWithPlayerSchema = {
|
||||
event: EventSchema;
|
||||
playerEvent: (PlayerEventRolesSchema | null);
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { EventWithPlayerSchema } from './EventWithPlayerSchema';
|
||||
export type EventWithPlayerSchemaList = Array<EventWithPlayerSchema>;
|
|
@ -7,7 +7,8 @@ import type { CreateEventJson } from '../models/CreateEventJson';
|
|||
import type { CreateTeamJson } from '../models/CreateTeamJson';
|
||||
import type { EditMemberRolesJson } from '../models/EditMemberRolesJson';
|
||||
import type { EventSchema } from '../models/EventSchema';
|
||||
import type { EventSchemaList } from '../models/EventSchemaList';
|
||||
import type { EventWithPlayerSchema } from '../models/EventWithPlayerSchema';
|
||||
import type { EventWithPlayerSchemaList } from '../models/EventWithPlayerSchemaList';
|
||||
import type { GetEventPlayersResponse } from '../models/GetEventPlayersResponse';
|
||||
import type { PlayerSchema } from '../models/PlayerSchema';
|
||||
import type { PutScheduleForm } from '../models/PutScheduleForm';
|
||||
|
@ -50,12 +51,12 @@ export class DefaultService {
|
|||
/**
|
||||
* get_team_events <GET>
|
||||
* @param teamId
|
||||
* @returns EventSchemaList OK
|
||||
* @returns EventWithPlayerSchemaList OK
|
||||
* @throws ApiError
|
||||
*/
|
||||
public getTeamEvents(
|
||||
teamId: number,
|
||||
): CancelablePromise<EventSchemaList> {
|
||||
): CancelablePromise<EventWithPlayerSchemaList> {
|
||||
return this.httpRequest.request({
|
||||
method: 'GET',
|
||||
url: '/api/events/team/id/{team_id}',
|
||||
|
@ -128,6 +129,46 @@ export class DefaultService {
|
|||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* unattend_event <DELETE>
|
||||
* @param eventId
|
||||
* @returns EventWithPlayerSchema OK
|
||||
* @throws ApiError
|
||||
*/
|
||||
public unattendEvent(
|
||||
eventId: number,
|
||||
): CancelablePromise<EventWithPlayerSchema> {
|
||||
return this.httpRequest.request({
|
||||
method: 'DELETE',
|
||||
url: '/api/events/{event_id}/attendance',
|
||||
path: {
|
||||
'event_id': eventId,
|
||||
},
|
||||
errors: {
|
||||
422: `Unprocessable Content`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* attend_event <PUT>
|
||||
* @param eventId
|
||||
* @returns EventWithPlayerSchema OK
|
||||
* @throws ApiError
|
||||
*/
|
||||
public attendEvent(
|
||||
eventId: number,
|
||||
): CancelablePromise<EventWithPlayerSchema> {
|
||||
return this.httpRequest.request({
|
||||
method: 'PUT',
|
||||
url: '/api/events/{event_id}/attendance',
|
||||
path: {
|
||||
'event_id': eventId,
|
||||
},
|
||||
errors: {
|
||||
422: `Unprocessable Content`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* get_event_players <GET>
|
||||
* @param eventId
|
||||
|
@ -165,52 +206,6 @@ export class DefaultService {
|
|||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* unattend_event <DELETE>
|
||||
* @param eventId
|
||||
* @param teamId
|
||||
* @returns void
|
||||
* @throws ApiError
|
||||
*/
|
||||
public deleteApiEventsEventIdTeamIdTeamIdAttendance(
|
||||
eventId: number,
|
||||
teamId: number,
|
||||
): CancelablePromise<void> {
|
||||
return this.httpRequest.request({
|
||||
method: 'DELETE',
|
||||
url: '/api/events/{event_id}/team/id/{team_id}/attendance',
|
||||
path: {
|
||||
'event_id': eventId,
|
||||
'team_id': teamId,
|
||||
},
|
||||
errors: {
|
||||
422: `Unprocessable Content`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* attend_event <PUT>
|
||||
* @param eventId
|
||||
* @param teamId
|
||||
* @returns void
|
||||
* @throws ApiError
|
||||
*/
|
||||
public putApiEventsEventIdTeamIdTeamIdAttendance(
|
||||
eventId: number,
|
||||
teamId: number,
|
||||
): CancelablePromise<void> {
|
||||
return this.httpRequest.request({
|
||||
method: 'PUT',
|
||||
url: '/api/events/{event_id}/team/id/{team_id}/attendance',
|
||||
path: {
|
||||
'event_id': eventId,
|
||||
'team_id': teamId,
|
||||
},
|
||||
errors: {
|
||||
422: `Unprocessable Content`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* logout <DELETE>
|
||||
* @returns void
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<script setup lang="ts">
|
||||
import { useRosterStore } from "@/stores/roster";
|
||||
import moment from "moment";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const rosterStore = useRosterStore();
|
||||
|
||||
function saveRoster() {
|
||||
rosterStore.saveRoster(Number(route.params.teamId))
|
||||
.then(() => {
|
||||
router.push({
|
||||
name: "team-details",
|
||||
params: {
|
||||
id: route.params.teamId
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="event-scheduler-container">
|
||||
<h1 class="roster-title">
|
||||
Roster for Snus Brotherhood
|
||||
</h1>
|
||||
<div v-if="rosterStore.startTime">
|
||||
<span class="aside date">
|
||||
{{ moment.unix(rosterStore.startTime).format("LL LT") }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group margin">
|
||||
<h3>Event Name</h3>
|
||||
<input v-model="rosterStore.title" />
|
||||
</div>
|
||||
<div class="form-group margin">
|
||||
<h3>Description (optional)</h3>
|
||||
<input v-model="rosterStore.description" />
|
||||
</div>
|
||||
<div class="form-group margin">
|
||||
<div class="action-buttons">
|
||||
<button class="accent" @click="saveRoster">Save roster</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
em.aside.date {
|
||||
font-size: 11pt;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,14 @@
|
|||
import type { PlayerRoleSchema } from "@/client";
|
||||
import { ref } from "vue";
|
||||
|
||||
export function useEventForm() {
|
||||
const title = ref("");
|
||||
const description = ref("");
|
||||
const players = ref<PlayerRoleSchema[]>([]);
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
players,
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import { type EventSchema, type CreateEventJson, type PlayerRoleSchema } from "@
|
|||
import { useTeamDetails } from "@/composables/team-details";
|
||||
import moment from "moment";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useEventForm } from "@/composables/event-form";
|
||||
|
||||
export const useRosterStore = defineStore("roster", () => {
|
||||
const clientStore = useClientStore();
|
||||
|
@ -169,6 +170,8 @@ export const useRosterStore = defineStore("roster", () => {
|
|||
|
||||
const startTime = ref<number>();
|
||||
|
||||
const { title, description } = useEventForm();
|
||||
|
||||
function saveRoster(teamId: number) {
|
||||
if (startTime.value == undefined) {
|
||||
throw new Error("No start time set");
|
||||
|
@ -176,8 +179,8 @@ export const useRosterStore = defineStore("roster", () => {
|
|||
|
||||
if (!currentEvent.value) {
|
||||
const body: CreateEventJson = {
|
||||
name: "Test",
|
||||
description: "test description",
|
||||
name: title.value,
|
||||
description: description.value,
|
||||
startTime: startTime.value.toString(),
|
||||
playerRoles: Object.values(selectedPlayers).map((player) => ({
|
||||
player: {
|
||||
|
@ -191,12 +194,10 @@ export const useRosterStore = defineStore("roster", () => {
|
|||
})),
|
||||
};
|
||||
|
||||
clientStore.client.default.createEvent(teamId, body)
|
||||
.then(() => {
|
||||
|
||||
});
|
||||
return clientStore.client.default.createEvent(teamId, body);
|
||||
} else {
|
||||
// TODO: update event
|
||||
throw "Not implemented";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,5 +218,7 @@ export const useRosterStore = defineStore("roster", () => {
|
|||
fetchPlayersFromEvent,
|
||||
startTime,
|
||||
saveRoster,
|
||||
title,
|
||||
description,
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,45 +1,62 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { useClientStore } from "../client";
|
||||
import type { EventSchema, EventSchemaList } from "@/client";
|
||||
import type { EventWithPlayerSchema } from "@/client";
|
||||
import { useEventsStore } from "../events";
|
||||
import { computed } from "vue";
|
||||
import { computed, reactive } from "vue";
|
||||
|
||||
export const useTeamsEventsStore = defineStore("teamsEvents", () => {
|
||||
const clientStore = useClientStore();
|
||||
const client = clientStore.client;
|
||||
const eventsStore = useEventsStore();
|
||||
//const eventsStore = useEventsStore();
|
||||
|
||||
const teamEvents = computed(() => {
|
||||
console.log("Recomputing teamEvents");
|
||||
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[] });
|
||||
});
|
||||
// // 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(
|
||||
fetchTeamEvents.name,
|
||||
() => client.default.getTeamEvents(teamId),
|
||||
(result: EventSchemaList) => {
|
||||
result.forEach((event) => {
|
||||
// insert into event store
|
||||
//eventsStore.events[event.id] = event;
|
||||
eventsStore.events.push(event);
|
||||
});
|
||||
(result: EventWithPlayerSchema[]) => {
|
||||
teamEvents[teamId] = result;
|
||||
return result;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function attendEvent(eventId: number) {
|
||||
client.default.attendEvent(eventId)
|
||||
.then((response) => {
|
||||
let index = teamEvents[response.event.teamId]
|
||||
.findIndex((event) => event.event.id == response.event.id);
|
||||
teamEvents[response.event.teamId][index] = response;
|
||||
});
|
||||
}
|
||||
|
||||
function unattendEvent(eventId: number) {
|
||||
client.default.unattendEvent(eventId)
|
||||
.then((response) => {
|
||||
let index = teamEvents[response.event.teamId]
|
||||
.findIndex((event) => event.event.id == response.event.id);
|
||||
teamEvents[response.event.teamId][index].playerEvent = null;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
teamEvents,
|
||||
fetchTeamEvents,
|
||||
attendEvent,
|
||||
unattendEvent,
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import PlayerCard from "../components/PlayerCard.vue";
|
||||
import RoleSlot from "../components/RoleSlot.vue";
|
||||
import PlayerTeamRole from "../player.ts";
|
||||
import { computed, reactive, onMounted } from "vue";
|
||||
import { useRosterStore } from "../stores/roster";
|
||||
import { useRoute } from "vue-router";
|
||||
import moment from "moment";
|
||||
import { useEventsStore } from "@/stores/events";
|
||||
import EventSchedulerForm from "@/components/EventSchedulerForm.vue";
|
||||
|
||||
const rosterStore = useRosterStore();
|
||||
const eventsStore = useEventsStore();
|
||||
|
@ -23,10 +22,6 @@ const hasAlternates = computed(() => {
|
|||
|
||||
const eventId = computed<number | undefined>(() => Number(route.params.eventId));
|
||||
|
||||
function saveRoster() {
|
||||
rosterStore.saveRoster(Number(route.params.teamId));
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (eventId.value) {
|
||||
const event = await eventsStore.fetchEvent(eventId.value);
|
||||
|
@ -42,26 +37,19 @@ onMounted(async () => {
|
|||
<template>
|
||||
<main>
|
||||
<div class="top">
|
||||
<h1 class="roster-title">
|
||||
Roster for Snus Brotherhood
|
||||
<em class="aside date" v-if="rosterStore.startTime">
|
||||
@
|
||||
{{ moment.unix(rosterStore.startTime).format("L LT") }}
|
||||
</em>
|
||||
</h1>
|
||||
<div class="button-group">
|
||||
<button>Cancel</button>
|
||||
<button class="accent" @click="saveRoster">Save Roster</button>
|
||||
</div>
|
||||
<a>
|
||||
<i class="bi bi-arrow-left" />
|
||||
Back
|
||||
</a>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="form-group margin column">
|
||||
<PlayerCard v-for="role in rosterStore.neededRoles"
|
||||
:player="rosterStore.selectedPlayers[role]"
|
||||
:role-title="role"
|
||||
is-roster />
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="form-group margin column" v-if="rosterStore.selectedRole">
|
||||
<PlayerCard v-for="player in rosterStore.mainRoles"
|
||||
:player="player"
|
||||
:role-title="player.role" />
|
||||
|
@ -75,6 +63,15 @@ onMounted(async () => {
|
|||
<PlayerCard v-if="rosterStore.selectedRole"
|
||||
is-ringer
|
||||
:role-title="rosterStore.selectedRole" />
|
||||
<div class="action-buttons">
|
||||
<button class="accent">
|
||||
<i class="bi bi-check" />
|
||||
Done
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column" v-else>
|
||||
<EventSchedulerForm />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
@ -120,9 +117,4 @@ onMounted(async () => {
|
|||
display: flex;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
em.aside.date {
|
||||
font-size: 14px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from flask import Blueprint, abort, make_response
|
||||
from spectree import Response
|
||||
from sqlalchemy import Row
|
||||
from sqlalchemy.sql import tuple_
|
||||
from models.player import Player
|
||||
from models.player_event import PlayerEvent, PlayerEventRolesSchema
|
||||
from models.player_event import EventWithPlayerSchema, PlayerEvent, PlayerEventRolesSchema
|
||||
from models.player_team_availability import PlayerTeamAvailability
|
||||
from models.player_team_role import PlayerRoleSchema, PlayerTeamRole
|
||||
from models.team import Team
|
||||
|
@ -43,23 +45,30 @@ def get_event(event_id: int):
|
|||
@api_events.get("/team/id/<int:team_id>")
|
||||
@spec.validate(
|
||||
resp=Response(
|
||||
HTTP_200=list[EventSchema],
|
||||
HTTP_200=list[EventWithPlayerSchema],
|
||||
),
|
||||
operation_id="get_team_events",
|
||||
)
|
||||
def get_team_events(team_id: int):
|
||||
events = db.session.query(
|
||||
Event
|
||||
).filter(
|
||||
@requires_authentication
|
||||
@requires_team_membership()
|
||||
def get_team_events(player_team: PlayerTeam, team_id: int, **_):
|
||||
rows = db.session.query(
|
||||
Event, PlayerEvent
|
||||
).outerjoin(
|
||||
PlayerEvent,
|
||||
(PlayerEvent.event_id == Event.id) & (PlayerEvent.player_id == player_team.player_id)
|
||||
).where(
|
||||
Event.team_id == team_id
|
||||
).order_by(
|
||||
Event.start_time
|
||||
).all()
|
||||
|
||||
def map_to_schema(event: Event):
|
||||
return EventSchema.from_model(event).dict(by_alias=True)
|
||||
def map_to_schema(row: Row[tuple[Event, PlayerEvent]]):
|
||||
return EventWithPlayerSchema.from_event_player_event(
|
||||
*row.tuple()
|
||||
).dict(by_alias=True)
|
||||
|
||||
return list(map(map_to_schema, events))
|
||||
return list(map(map_to_schema, rows))
|
||||
|
||||
@api_events.get("/user/id/<int:user_id>")
|
||||
def get_user_events(user_id: int):
|
||||
|
@ -129,28 +138,33 @@ def create_event(player_team: PlayerTeam, team_id: int, json: CreateEventJson, *
|
|||
@api_events.put("/<int:event_id>/attendance")
|
||||
@spec.validate(
|
||||
resp=Response(
|
||||
HTTP_204=None,
|
||||
)
|
||||
HTTP_200=EventWithPlayerSchema,
|
||||
),
|
||||
operation_id="attend_event",
|
||||
)
|
||||
@requires_authentication
|
||||
@requires_team_membership()
|
||||
def attend_event(player_team: PlayerTeam, event_id: int, **_):
|
||||
def attend_event(player: Player, event_id: int, **_):
|
||||
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_event = db.session.query(
|
||||
PlayerEvent
|
||||
).where(
|
||||
PlayerEvent.event_id == event_id
|
||||
).where(
|
||||
PlayerEvent.player_id == player_team.player_id
|
||||
PlayerEvent.player_id == player.steam_id
|
||||
).join(
|
||||
Event
|
||||
).where(
|
||||
Event.team_id == player_team.team_id
|
||||
).one_or_none()
|
||||
|
||||
if not player_event:
|
||||
player_event = PlayerEvent()
|
||||
player_event.event_id = event_id
|
||||
player_event.player_id = player_team.player_id
|
||||
player_event.player_id = player.steam_id
|
||||
db.session.add(player_event)
|
||||
|
||||
player_event.has_confirmed = True
|
||||
|
@ -159,27 +173,28 @@ def attend_event(player_team: PlayerTeam, event_id: int, **_):
|
|||
|
||||
player_event.event.update_discord_message()
|
||||
|
||||
return make_response({ }, 204)
|
||||
return EventWithPlayerSchema.from_event_player_event(
|
||||
player_event.event,
|
||||
player_event,
|
||||
).dict(by_alias=True)
|
||||
|
||||
@api_events.delete("/<int:event_id>/attendance")
|
||||
@spec.validate(
|
||||
resp=Response(
|
||||
HTTP_204=None,
|
||||
)
|
||||
HTTP_200=EventWithPlayerSchema,
|
||||
),
|
||||
operation_id="unattend_event",
|
||||
)
|
||||
@requires_authentication
|
||||
@requires_team_membership()
|
||||
def unattend_event(player_team: PlayerTeam, event_id: int, **_):
|
||||
def unattend_event(player: Player, event_id: int, **_):
|
||||
result = db.session.query(
|
||||
PlayerEvent, Event
|
||||
).where(
|
||||
PlayerEvent.event_id == event_id
|
||||
).where(
|
||||
PlayerEvent.player_id == player_team.player_id
|
||||
PlayerEvent.player_id == player.steam_id
|
||||
).join(
|
||||
Event
|
||||
).where(
|
||||
Event.team_id == player_team.team_id
|
||||
Event.id == event_id
|
||||
).one_or_none()
|
||||
|
||||
if not result:
|
||||
|
@ -192,7 +207,10 @@ def unattend_event(player_team: PlayerTeam, event_id: int, **_):
|
|||
|
||||
event.update_discord_message()
|
||||
|
||||
return make_response({ }, 204)
|
||||
return EventWithPlayerSchema.from_event_player_event(
|
||||
event,
|
||||
None,
|
||||
).dict(by_alias=True)
|
||||
|
||||
class GetEventPlayersResponse(BaseModel):
|
||||
players: list[PlayerEventRolesSchema]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from datetime import datetime
|
||||
import threading
|
||||
from sqlalchemy.orm import mapped_column, relationship
|
||||
from sqlalchemy.orm.attributes import Mapped
|
||||
from sqlalchemy.orm.properties import ForeignKey
|
||||
|
@ -63,7 +64,7 @@ class Event(app_db.BaseModel):
|
|||
f"<t:{start_timestamp}:f>",
|
||||
"\n".join(players_info),
|
||||
"",
|
||||
"[Confirm availability here]" +
|
||||
"[Confirm attendance here]" +
|
||||
f"(https://availabili.tf/team/id/{self.team.id}/events/{self.id})",
|
||||
])
|
||||
|
||||
|
@ -81,16 +82,23 @@ class Event(app_db.BaseModel):
|
|||
return DiscordWebhook(
|
||||
integration.webhook_url,
|
||||
id=str(self.discord_message_id),
|
||||
username=integration.webhook_bot_name,
|
||||
avatar_url=integration.webhook_bot_profile_picture,
|
||||
)
|
||||
else:
|
||||
return DiscordWebhook(integration.webhook_url)
|
||||
return DiscordWebhook(
|
||||
integration.webhook_url,
|
||||
username=integration.webhook_bot_name,
|
||||
avatar_url=integration.webhook_bot_profile_picture,
|
||||
)
|
||||
|
||||
def update_discord_message(self):
|
||||
webhook = self.get_or_create_webhook()
|
||||
if webhook:
|
||||
webhook.content = self.get_discord_content()
|
||||
if webhook.id:
|
||||
webhook.edit()
|
||||
# fire and forget
|
||||
threading.Thread(target=webhook.edit).start()
|
||||
else:
|
||||
webhook.execute()
|
||||
if webhook_id := webhook.id:
|
||||
|
|
|
@ -26,6 +26,24 @@ class PlayerEvent(app_db.BaseModel):
|
|||
)
|
||||
role: Mapped["PlayerTeamRole"] = relationship("PlayerTeamRole")
|
||||
|
||||
class EventWithPlayerSchema(spec.BaseModel):
|
||||
event: "EventSchema"
|
||||
player_event: Optional["PlayerEventRolesSchema"]
|
||||
|
||||
@classmethod
|
||||
def from_event_player_event(cls, event: "Event", player_event: Optional["PlayerEvent"]):
|
||||
res = cls(
|
||||
event=EventSchema.from_model(event),
|
||||
player_event=None,
|
||||
)
|
||||
|
||||
if player_event:
|
||||
res.player_event = PlayerEventRolesSchema.from_event_player_team(
|
||||
player_event, player_event.player_team
|
||||
)
|
||||
|
||||
return res
|
||||
|
||||
class PlayerEventRolesSchema(spec.BaseModel):
|
||||
player: "PlayerSchema"
|
||||
role: Optional["RoleSchema"]
|
||||
|
@ -44,7 +62,7 @@ class PlayerEventRolesSchema(spec.BaseModel):
|
|||
)
|
||||
|
||||
|
||||
from models.event import Event
|
||||
from models.event import Event, EventSchema
|
||||
from models.player import Player, PlayerSchema
|
||||
from models.player_team_role import PlayerTeamRole, RoleSchema
|
||||
from models.player_team import PlayerTeam
|
||||
|
|
Loading…
Reference in New Issue