Add updating events
parent
6f49053dac
commit
7043877a9f
|
@ -33,6 +33,7 @@ export type { TeamInviteSchemaList } from './models/TeamInviteSchemaList';
|
||||||
export type { TeamLogsTfIntegrationSchema } from './models/TeamLogsTfIntegrationSchema';
|
export type { TeamLogsTfIntegrationSchema } from './models/TeamLogsTfIntegrationSchema';
|
||||||
export { TeamRole } from './models/TeamRole';
|
export { TeamRole } from './models/TeamRole';
|
||||||
export type { TeamSchema } from './models/TeamSchema';
|
export type { TeamSchema } from './models/TeamSchema';
|
||||||
|
export type { UpdateEventJson } from './models/UpdateEventJson';
|
||||||
export type { ValidationError } from './models/ValidationError';
|
export type { ValidationError } from './models/ValidationError';
|
||||||
export type { ValidationErrorElement } from './models/ValidationErrorElement';
|
export type { ValidationErrorElement } from './models/ValidationErrorElement';
|
||||||
export type { ViewAvailablePlayersQuery } from './models/ViewAvailablePlayersQuery';
|
export type { ViewAvailablePlayersQuery } from './models/ViewAvailablePlayersQuery';
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import type { PlayerRoleSchema } from './PlayerRoleSchema';
|
import type { PlayerRoleSchema } from './PlayerRoleSchema';
|
||||||
export type CreateEventJson = {
|
export type CreateEventJson = {
|
||||||
description: string;
|
description: (string | null);
|
||||||
name: string;
|
name: string;
|
||||||
playerRoles: Array<PlayerRoleSchema>;
|
playerRoles: Array<PlayerRoleSchema>;
|
||||||
startTime: string;
|
startTime: string;
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type { PlayerRoleSchema } from './PlayerRoleSchema';
|
||||||
|
export type UpdateEventJson = {
|
||||||
|
description: (string | null);
|
||||||
|
name: string;
|
||||||
|
playerRoles: Array<PlayerRoleSchema>;
|
||||||
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@ import type { SetUsernameJson } from '../models/SetUsernameJson';
|
||||||
import type { TeamIntegrationSchema } from '../models/TeamIntegrationSchema';
|
import type { TeamIntegrationSchema } from '../models/TeamIntegrationSchema';
|
||||||
import type { TeamInviteSchema } from '../models/TeamInviteSchema';
|
import type { TeamInviteSchema } from '../models/TeamInviteSchema';
|
||||||
import type { TeamInviteSchemaList } from '../models/TeamInviteSchemaList';
|
import type { TeamInviteSchemaList } from '../models/TeamInviteSchemaList';
|
||||||
|
import type { UpdateEventJson } from '../models/UpdateEventJson';
|
||||||
import type { ViewAvailablePlayersResponse } from '../models/ViewAvailablePlayersResponse';
|
import type { ViewAvailablePlayersResponse } from '../models/ViewAvailablePlayersResponse';
|
||||||
import type { ViewScheduleResponse } from '../models/ViewScheduleResponse';
|
import type { ViewScheduleResponse } from '../models/ViewScheduleResponse';
|
||||||
import type { ViewTeamMembersResponseList } from '../models/ViewTeamMembersResponseList';
|
import type { ViewTeamMembersResponseList } from '../models/ViewTeamMembersResponseList';
|
||||||
|
@ -129,6 +130,30 @@ export class DefaultService {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* update_event <PATCH>
|
||||||
|
* @param eventId
|
||||||
|
* @param requestBody
|
||||||
|
* @returns EventSchema OK
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public updateEvent(
|
||||||
|
eventId: number,
|
||||||
|
requestBody?: UpdateEventJson,
|
||||||
|
): CancelablePromise<EventSchema> {
|
||||||
|
return this.httpRequest.request({
|
||||||
|
method: 'PATCH',
|
||||||
|
url: '/api/events/{event_id}',
|
||||||
|
path: {
|
||||||
|
'event_id': eventId,
|
||||||
|
},
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Unprocessable Content`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* unattend_event <DELETE>
|
* unattend_event <DELETE>
|
||||||
* @param eventId
|
* @param eventId
|
||||||
|
@ -189,23 +214,6 @@ export class DefaultService {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* set_event_players <PATCH>
|
|
||||||
* @param eventId
|
|
||||||
* @returns void
|
|
||||||
* @throws ApiError
|
|
||||||
*/
|
|
||||||
public patchApiEventsEventIdPlayers(
|
|
||||||
eventId: number,
|
|
||||||
): CancelablePromise<void> {
|
|
||||||
return this.httpRequest.request({
|
|
||||||
method: 'PATCH',
|
|
||||||
url: '/api/events/{event_id}/players',
|
|
||||||
path: {
|
|
||||||
'event_id': eventId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* logout <DELETE>
|
* logout <DELETE>
|
||||||
* @returns void
|
* @returns void
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { useTeamsStore } from "@/stores/teams";
|
||||||
import { useTeamsEventsStore } from "@/stores/teams/events";
|
import { useTeamsEventsStore } from "@/stores/teams/events";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
import { RouterLink } from "vue-router";
|
||||||
|
|
||||||
const teamsStore = useTeamsStore();
|
const teamsStore = useTeamsStore();
|
||||||
const rosterStore = useRosterStore();
|
const rosterStore = useRosterStore();
|
||||||
|
@ -72,6 +73,15 @@ function attendOrUnattend() {
|
||||||
<em v-else class="subtext">No description provided.</em>
|
<em v-else class="subtext">No description provided.</em>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
|
<RouterLink class="button" :to="{
|
||||||
|
name: 'roster-builder-event',
|
||||||
|
params: { eventId: event.event.id }
|
||||||
|
}">
|
||||||
|
<button>
|
||||||
|
<i class="bi bi-pencil" />
|
||||||
|
Edit
|
||||||
|
</button>
|
||||||
|
</RouterLink>
|
||||||
<button
|
<button
|
||||||
@click="attendOrUnattend()"
|
@click="attendOrUnattend()"
|
||||||
v-if="event.playerEvent"
|
v-if="event.playerEvent"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useEventForm } from "@/composables/event-form";
|
||||||
import { useRosterStore } from "@/stores/roster";
|
import { useRosterStore } from "@/stores/roster";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
@ -8,16 +9,22 @@ const router = useRouter();
|
||||||
|
|
||||||
const rosterStore = useRosterStore();
|
const rosterStore = useRosterStore();
|
||||||
|
|
||||||
|
const { eventId } = useEventForm();
|
||||||
|
|
||||||
function saveRoster() {
|
function saveRoster() {
|
||||||
rosterStore.saveRoster(Number(route.params.teamId))
|
if (eventId.value) {
|
||||||
.then(() => {
|
rosterStore.updateRoster(eventId.value);
|
||||||
router.push({
|
} else {
|
||||||
name: "team-details",
|
rosterStore.saveRoster(Number(route.params.teamId))
|
||||||
params: {
|
.then(() => {
|
||||||
id: route.params.teamId
|
router.push({
|
||||||
}
|
name: "team-details",
|
||||||
|
params: {
|
||||||
|
id: route.params.teamId
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
import type { PlayerRoleSchema } from "@/client";
|
import type { PlayerRoleSchema } from "@/client";
|
||||||
import { ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
export function useEventForm() {
|
export function useEventForm() {
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
const title = ref("");
|
const title = ref("");
|
||||||
const description = ref("");
|
const description = ref<string | null>("");
|
||||||
const players = ref<PlayerRoleSchema[]>([]);
|
const players = ref<PlayerRoleSchema[]>([]);
|
||||||
|
const eventId = computed<number | undefined>(() => Number(route.params.eventId));
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
players,
|
players,
|
||||||
|
eventId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { type Player, type PlayerTeamRoleFlat } from "@/player";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { computed, reactive, ref, type Reactive, type Ref } from "vue";
|
import { computed, reactive, ref, type Reactive, type Ref } from "vue";
|
||||||
import { useClientStore } from "./client";
|
import { useClientStore } from "./client";
|
||||||
import { type EventSchema, type CreateEventJson, type PlayerRoleSchema } from "@/client";
|
import { type EventSchema, type CreateEventJson, type PlayerRoleSchema, type UpdateEventJson } from "@/client";
|
||||||
import { useTeamDetails } from "@/composables/team-details";
|
import { useTeamDetails } from "@/composables/team-details";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
@ -14,6 +14,8 @@ export const useRosterStore = defineStore("roster", () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
// TODO: move roster state to a composable
|
||||||
|
|
||||||
const neededRoles: Reactive<Array<String>> = reactive([
|
const neededRoles: Reactive<Array<String>> = reactive([
|
||||||
"PocketScout",
|
"PocketScout",
|
||||||
"FlankScout",
|
"FlankScout",
|
||||||
|
@ -78,12 +80,12 @@ export const useRosterStore = defineStore("roster", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const roleNames = reactive<{ [key: string]: string }>({
|
const roleNames = reactive<{ [key: string]: string }>({
|
||||||
"Scout": "Scout (HL)",
|
"Scout": "Scout",
|
||||||
"PocketScout": "Pocket Scout (6s)",
|
"PocketScout": "Pocket Scout",
|
||||||
"FlankScout": "Flank Scout (6s)",
|
"FlankScout": "Flank Scout",
|
||||||
"Soldier": "Soldier (HL)",
|
"Soldier": "Soldier",
|
||||||
"PocketSoldier": "Pocket Soldier (6s)",
|
"PocketSoldier": "Pocket Soldier",
|
||||||
"Roamer": "Roamer (6s)",
|
"Roamer": "Roamer",
|
||||||
"Pyro": "Pyro",
|
"Pyro": "Pyro",
|
||||||
"Demoman": "Demoman",
|
"Demoman": "Demoman",
|
||||||
"HeavyWeapons": "Heavy",
|
"HeavyWeapons": "Heavy",
|
||||||
|
@ -177,28 +179,42 @@ export const useRosterStore = defineStore("roster", () => {
|
||||||
throw new Error("No start time set");
|
throw new Error("No start time set");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentEvent.value) {
|
const body: CreateEventJson = {
|
||||||
const body: CreateEventJson = {
|
name: title.value,
|
||||||
name: title.value,
|
description: description.value,
|
||||||
description: description.value,
|
startTime: startTime.value.toString(),
|
||||||
startTime: startTime.value.toString(),
|
playerRoles: Object.values(selectedPlayers).map((player) => ({
|
||||||
playerRoles: Object.values(selectedPlayers).map((player) => ({
|
player: {
|
||||||
player: {
|
steamId: player.steamId,
|
||||||
steamId: player.steamId,
|
username: player.name,
|
||||||
username: player.name,
|
},
|
||||||
},
|
role: {
|
||||||
role: {
|
role: player.role,
|
||||||
role: player.role,
|
isMain: player.isMain,
|
||||||
isMain: player.isMain,
|
},
|
||||||
},
|
})),
|
||||||
})),
|
};
|
||||||
};
|
|
||||||
|
|
||||||
return clientStore.client.default.createEvent(teamId, body);
|
return client.default.createEvent(teamId, body);
|
||||||
} else {
|
}
|
||||||
// TODO: update event
|
|
||||||
throw "Not implemented";
|
function updateRoster(eventId: number) {
|
||||||
}
|
const body: UpdateEventJson = {
|
||||||
|
name: title.value,
|
||||||
|
description: description.value,
|
||||||
|
playerRoles: Object.values(selectedPlayers).map((player) => ({
|
||||||
|
player: {
|
||||||
|
steamId: player.steamId,
|
||||||
|
username: player.name,
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
role: player.role,
|
||||||
|
isMain: player.isMain,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
return client.default.updateEvent(eventId, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -218,6 +234,7 @@ export const useRosterStore = defineStore("roster", () => {
|
||||||
fetchPlayersFromEvent,
|
fetchPlayersFromEvent,
|
||||||
startTime,
|
startTime,
|
||||||
saveRoster,
|
saveRoster,
|
||||||
|
updateRoster,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { useRoute } from "vue-router";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useEventsStore } from "@/stores/events";
|
import { useEventsStore } from "@/stores/events";
|
||||||
import EventSchedulerForm from "@/components/EventSchedulerForm.vue";
|
import EventSchedulerForm from "@/components/EventSchedulerForm.vue";
|
||||||
|
import { useEventForm } from "@/composables/event-form";
|
||||||
|
|
||||||
const rosterStore = useRosterStore();
|
const rosterStore = useRosterStore();
|
||||||
const eventsStore = useEventsStore();
|
const eventsStore = useEventsStore();
|
||||||
|
@ -20,12 +21,19 @@ const hasAlternates = computed(() => {
|
||||||
return rosterStore.alternateRoles.length > 0;
|
return rosterStore.alternateRoles.length > 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
const eventId = computed<number | undefined>(() => Number(route.params.eventId));
|
const { eventId } = useEventForm();
|
||||||
|
|
||||||
|
function closeSelection() {
|
||||||
|
rosterStore.selectedRole = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (eventId.value) {
|
if (eventId.value) {
|
||||||
const event = await eventsStore.fetchEvent(eventId.value);
|
const event = await eventsStore.fetchEvent(eventId.value);
|
||||||
rosterStore.startTime = moment(event.startTime).unix();
|
rosterStore.startTime = moment(event.startTime).unix();
|
||||||
|
rosterStore.title = event.name;
|
||||||
|
rosterStore.description = event.description;
|
||||||
|
Object.assign(rosterStore.selectedPlayers, { });
|
||||||
rosterStore.fetchPlayersFromEvent(eventId.value);
|
rosterStore.fetchPlayersFromEvent(eventId.value);
|
||||||
} else {
|
} else {
|
||||||
rosterStore.startTime = Number(route.params.startTime);
|
rosterStore.startTime = Number(route.params.startTime);
|
||||||
|
@ -64,7 +72,7 @@ onMounted(async () => {
|
||||||
is-ringer
|
is-ringer
|
||||||
:role-title="rosterStore.selectedRole" />
|
:role-title="rosterStore.selectedRole" />
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
<button class="accent">
|
<button class="accent" @click="closeSelection">
|
||||||
<i class="bi bi-check" />
|
<i class="bi bi-check" />
|
||||||
Done
|
Done
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -76,10 +76,15 @@ def get_user_events(user_id: int):
|
||||||
|
|
||||||
class CreateEventJson(BaseModel):
|
class CreateEventJson(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
description: str
|
description: Optional[str]
|
||||||
start_time: datetime
|
start_time: datetime
|
||||||
player_roles: list[PlayerRoleSchema]
|
player_roles: list[PlayerRoleSchema]
|
||||||
|
|
||||||
|
class UpdateEventJson(BaseModel):
|
||||||
|
name: str
|
||||||
|
description: Optional[str]
|
||||||
|
player_roles: list[PlayerRoleSchema]
|
||||||
|
|
||||||
@api_events.post("/team/id/<int:team_id>")
|
@api_events.post("/team/id/<int:team_id>")
|
||||||
@spec.validate(
|
@spec.validate(
|
||||||
resp=Response(
|
resp=Response(
|
||||||
|
@ -93,7 +98,8 @@ def create_event(player_team: PlayerTeam, team_id: int, json: CreateEventJson, *
|
||||||
event = Event()
|
event = Event()
|
||||||
event.team_id = player_team.team_id
|
event.team_id = player_team.team_id
|
||||||
event.name = json.name
|
event.name = json.name
|
||||||
event.description = json.description
|
if json.description:
|
||||||
|
event.description = json.description
|
||||||
event.start_time = json.start_time
|
event.start_time = json.start_time
|
||||||
|
|
||||||
db.session.add(event)
|
db.session.add(event)
|
||||||
|
@ -252,13 +258,33 @@ def get_event_players(player: Player, event_id: int, **_):
|
||||||
players=player_event_roles
|
players=player_event_roles
|
||||||
).dict(by_alias=True), 200
|
).dict(by_alias=True), 200
|
||||||
|
|
||||||
@api_events.patch("/<int:event_id>/players")
|
@api_events.patch("/<int:event_id>")
|
||||||
|
@spec.validate(
|
||||||
|
resp=Response(
|
||||||
|
HTTP_200=EventSchema,
|
||||||
|
),
|
||||||
|
operation_id="update_event",
|
||||||
|
)
|
||||||
@requires_authentication
|
@requires_authentication
|
||||||
@requires_team_membership()
|
def update_event(player: Player, event_id: int, json: UpdateEventJson, **_):
|
||||||
def set_event_players(player_team: PlayerTeam, event_id: int, **_):
|
event = db.session.query(Event).where(Event.id == event_id).one_or_none()
|
||||||
assert_team_authority(player_team, None)
|
if not event:
|
||||||
|
abort(404)
|
||||||
|
assert_team_membership(player, event.team)
|
||||||
|
|
||||||
# merge players into event
|
for player_event in event.players:
|
||||||
db.session.query(Event).filter(Event.id == event_id).update({"players": []})
|
player_team = player_event.player_team
|
||||||
|
roles = player_team.player_roles
|
||||||
|
# assign new roles if in json, set to None if not
|
||||||
|
new_role = next((x.role for x in json.player_roles if x.player.steam_id == str(player_event.player_id)), None)
|
||||||
|
#import sys
|
||||||
|
#print(player_event.player_id, file=sys.stderr)
|
||||||
|
# if valid role (new_role exists in roles), update player_event.role
|
||||||
|
if new_role and (role_entity := next((x for x in roles if x.role.name == new_role.role), None)):
|
||||||
|
player_event.player_team_role_id = role_entity.id
|
||||||
|
else:
|
||||||
|
player_event.role = None
|
||||||
|
|
||||||
raise NotImplementedError()
|
event.update_discord_message()
|
||||||
|
|
||||||
|
return EventSchema.from_model(event).dict(by_alias=True), 200
|
||||||
|
|
|
@ -12,7 +12,7 @@ class PlayerEvent(app_db.BaseModel):
|
||||||
|
|
||||||
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), primary_key=True)
|
event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), primary_key=True)
|
||||||
player_id: Mapped[int] = mapped_column(ForeignKey("players.steam_id"), primary_key=True)
|
player_id: Mapped[int] = mapped_column(ForeignKey("players.steam_id"), primary_key=True)
|
||||||
player_team_role_id: Mapped[int] = mapped_column(ForeignKey("players_teams_roles.id"), nullable=True)
|
player_team_role_id: Mapped[int | None] = mapped_column(ForeignKey("players_teams_roles.id"), nullable=True)
|
||||||
has_confirmed: Mapped[bool] = mapped_column(Boolean, default=False)
|
has_confirmed: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||||
|
|
||||||
event: Mapped["Event"] = relationship("Event", back_populates="players")
|
event: Mapped["Event"] = relationship("Event", back_populates="players")
|
||||||
|
@ -21,10 +21,10 @@ class PlayerEvent(app_db.BaseModel):
|
||||||
"PlayerTeam",
|
"PlayerTeam",
|
||||||
secondary="players",
|
secondary="players",
|
||||||
primaryjoin="PlayerEvent.player_id == Player.steam_id",
|
primaryjoin="PlayerEvent.player_id == Player.steam_id",
|
||||||
secondaryjoin="PlayerTeam.player_id == Player.steam_id",
|
secondaryjoin="(PlayerTeam.player_id == Player.steam_id) & (PlayerTeam.team_id == Event.team_id)",
|
||||||
viewonly=True,
|
viewonly=True,
|
||||||
)
|
)
|
||||||
role: Mapped["PlayerTeamRole"] = relationship("PlayerTeamRole")
|
role: Mapped["PlayerTeamRole | None"] = relationship("PlayerTeamRole")
|
||||||
|
|
||||||
class EventWithPlayerSchema(spec.BaseModel):
|
class EventWithPlayerSchema(spec.BaseModel):
|
||||||
event: "EventSchema"
|
event: "EventSchema"
|
||||||
|
|
Loading…
Reference in New Issue