Added editing and viewing roles
parent
708aafed9e
commit
5d620c07ed
|
@ -10,6 +10,8 @@
|
|||
"dependencies": {
|
||||
"axios": "^1.7.7",
|
||||
"bootstrap-icons": "^1.11.3",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.46",
|
||||
"pinia": "^2.2.4",
|
||||
"v-tooltip": "^2.1.3",
|
||||
"vue": "^3.5.12",
|
||||
|
@ -5138,6 +5140,27 @@
|
|||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/moment-timezone": {
|
||||
"version": "0.5.46",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz",
|
||||
"integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"moment": "^2.29.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
"type-check": "vue-tsc --build --force",
|
||||
"lint": "eslint . --fix",
|
||||
"format": "prettier --write src/",
|
||||
"openapi-generate": "openapi --input 'http://localhost:5000/apidoc/openapi.json' --output src/client --name AvailabilitfClient"
|
||||
"openapi-generate": "openapi --input 'http://localhost:8000/apidoc/openapi.json' --output src/client --name AvailabilitfClient"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.7",
|
||||
"bootstrap-icons": "^1.11.3",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.46",
|
||||
"pinia": "^2.2.4",
|
||||
"v-tooltip": "^2.1.3",
|
||||
"vue": "^3.5.12",
|
||||
|
|
|
@ -12,6 +12,7 @@ export type { OpenAPIConfig } from './core/OpenAPI';
|
|||
|
||||
export type { AddPlayerJson } from './models/AddPlayerJson';
|
||||
export type { CreateTeamJson } from './models/CreateTeamJson';
|
||||
export type { EditMemberRolesJson } from './models/EditMemberRolesJson';
|
||||
export type { PutScheduleForm } from './models/PutScheduleForm';
|
||||
export type { RoleSchema } from './models/RoleSchema';
|
||||
export { TeamRole } from './models/TeamRole';
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { RoleSchema } from './RoleSchema';
|
||||
export type EditMemberRolesJson = {
|
||||
roles: Array<RoleSchema>;
|
||||
};
|
||||
|
|
@ -4,6 +4,9 @@
|
|||
/* eslint-disable */
|
||||
import type { RoleSchema } from './RoleSchema';
|
||||
export type ViewTeamMembersResponse = {
|
||||
availability: number;
|
||||
createdAt: string;
|
||||
playtime: number;
|
||||
roles: Array<RoleSchema>;
|
||||
steamId: string;
|
||||
username: string;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
/* eslint-disable */
|
||||
import type { AddPlayerJson } from '../models/AddPlayerJson';
|
||||
import type { CreateTeamJson } from '../models/CreateTeamJson';
|
||||
import type { EditMemberRolesJson } from '../models/EditMemberRolesJson';
|
||||
import type { PutScheduleForm } from '../models/PutScheduleForm';
|
||||
import type { ViewScheduleResponse } from '../models/ViewScheduleResponse';
|
||||
import type { ViewTeamMembersResponseList } from '../models/ViewTeamMembersResponseList';
|
||||
|
@ -210,6 +211,35 @@ export class DefaultService {
|
|||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* edit_member_roles <PATCH>
|
||||
* @param teamId
|
||||
* @param targetPlayerId
|
||||
* @param requestBody
|
||||
* @returns void
|
||||
* @throws ApiError
|
||||
*/
|
||||
public editMemberRoles(
|
||||
teamId: string,
|
||||
targetPlayerId: string,
|
||||
requestBody?: EditMemberRolesJson,
|
||||
): CancelablePromise<void> {
|
||||
return this.httpRequest.request({
|
||||
method: 'PATCH',
|
||||
url: '/api/team/id/{team_id}/edit-player/{target_player_id}',
|
||||
path: {
|
||||
'team_id': teamId,
|
||||
'target_player_id': targetPlayerId,
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
errors: {
|
||||
403: `Forbidden`,
|
||||
404: `Not Found`,
|
||||
422: `Unprocessable Entity`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* add_player <PUT>
|
||||
* @param teamId
|
||||
|
|
|
@ -1,14 +1,74 @@
|
|||
<script setup lang="ts">
|
||||
import type { PlayerTeamRole } from "../player";
|
||||
import { computed, type PropType } from "vue";
|
||||
import { computed, type PropType, ref, watch } from "vue";
|
||||
import { useTeamsStore } from "../stores/teams";
|
||||
import { useRosterStore } from "../stores/roster";
|
||||
import { type ViewTeamMembersResponse } from "@/client";
|
||||
import { type ViewTeamMembersResponse, type TeamSchema } from "@/client";
|
||||
import RoleTag from "../components/RoleTag.vue";
|
||||
|
||||
const props = defineProps({
|
||||
player: Object as PropType<ViewTeamMembersResponse>,
|
||||
team: Object as PropType<TeamSchema>,
|
||||
});
|
||||
|
||||
const teamsStore = useTeamsStore();
|
||||
|
||||
const rosterStore = useRosterStore();
|
||||
|
||||
//const roles = computed({
|
||||
// get: () => ({
|
||||
// "PocketScout": "",
|
||||
// "FlankScout": "",
|
||||
// "PocketSoldier": "",
|
||||
// "Roamer": "",
|
||||
// "Demoman": "",
|
||||
// "Medic": "",
|
||||
// }),
|
||||
//});
|
||||
|
||||
const isEditing = ref(false);
|
||||
|
||||
// this is the roles of the player we are editing
|
||||
const roles = ref([]);
|
||||
const updatedRoles = ref([]);
|
||||
|
||||
//const rolesMap = reactive({
|
||||
// "Role.PocketScout": undefined,
|
||||
// "Role.FlankScout": undefined,
|
||||
// "Role.PocketSoldier": undefined,
|
||||
// "Role.Roamer": undefined,
|
||||
// "Role.Demoman": undefined,
|
||||
// "Role.Medic": undefined,
|
||||
//});
|
||||
|
||||
const possibleRoles = [
|
||||
"PocketScout",
|
||||
"FlankScout",
|
||||
"PocketSoldier",
|
||||
"Roamer",
|
||||
"Demoman",
|
||||
"Medic",
|
||||
];
|
||||
|
||||
watch(isEditing, (newValue) => {
|
||||
if (newValue) {
|
||||
// editing
|
||||
roles.value = possibleRoles.map((roleName) => {
|
||||
console.log(roleName);
|
||||
return props.player.roles
|
||||
.find((playerRole) => playerRole.role == roleName) ?? undefined;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function updateRoles() {
|
||||
isEditing.value = false;
|
||||
updatedRoles.value = roles.value.filter(x => x);
|
||||
props.player.roles = updatedRoles.value;
|
||||
console.log(roles.value);
|
||||
console.log(updatedRoles.value);
|
||||
teamsStore.updateRoles(props.team.id, props.player.steamId, updatedRoles.value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -23,24 +83,39 @@ const rosterStore = useRosterStore();
|
|||
</td>
|
||||
<td>
|
||||
<div class="role-icons flex-middle">
|
||||
<div class="role-buttons" v-if="isEditing">
|
||||
<RoleTag
|
||||
v-for="role, i in possibleRoles"
|
||||
:role="role"
|
||||
:player="player"
|
||||
v-model="roles[i]"
|
||||
/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<i
|
||||
v-for="role in player.roles"
|
||||
:class="{
|
||||
[rosterStore.roleIcons[role.role]]: true,
|
||||
main: role.is_main,
|
||||
main: role.isMain,
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{{ player.playtime.toFixed(1) }} hours
|
||||
</td>
|
||||
<td>
|
||||
{{ new Date(player.created_at).toLocaleString() }}
|
||||
{{ new Date(player.createdAt).toLocaleString() }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="edit-group">
|
||||
<button>
|
||||
<template v-if="isEditing">
|
||||
<button class="editing" @click="updateRoles()">
|
||||
<i class="bi bi-check-lg" />
|
||||
</button>
|
||||
</template>
|
||||
<button v-else @click="isEditing = true">
|
||||
<i class="bi bi-pencil-fill edit-icon" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -94,7 +169,7 @@ const rosterStore = useRosterStore();
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.role-icons {
|
||||
.role-icons i {
|
||||
font-size: 24px;
|
||||
line-height: 0;
|
||||
color: var(--overlay-0);
|
||||
|
@ -104,6 +179,12 @@ const rosterStore = useRosterStore();
|
|||
color: var(--text);
|
||||
}
|
||||
|
||||
.role-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.edit-group {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
|
@ -122,4 +203,8 @@ const rosterStore = useRosterStore();
|
|||
.player-card:hover .edit-group > button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.edit-group > button.editing {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
<script setup lang="ts">
|
||||
import { type ViewTeamMembersResponse } from "@/client";
|
||||
import { useRosterStore } from "../stores/roster";
|
||||
|
||||
const rosterStore = useRosterStore();
|
||||
|
||||
const props = defineProps({
|
||||
role: String,
|
||||
player: Object as PropType<ViewTeamMembersResponse>,
|
||||
});
|
||||
|
||||
const roleObject = defineModel();
|
||||
|
||||
function toggle(isMain) {
|
||||
if (isMain == roleObject.value?.isMain) {
|
||||
roleObject.value = undefined;
|
||||
} else {
|
||||
if (!roleObject.value) {
|
||||
// create a new role object
|
||||
roleObject.value = {
|
||||
role: props.role,
|
||||
isMain: isMain
|
||||
}
|
||||
} else {
|
||||
roleObject.value.isMain = isMain;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="role">
|
||||
<div
|
||||
:class="{
|
||||
'role-info': true,
|
||||
'unselected': !roleObject,
|
||||
}"
|
||||
>
|
||||
<i
|
||||
:class="{
|
||||
[rosterStore.roleIcons[role]]: true,
|
||||
}"
|
||||
/>
|
||||
<span>
|
||||
{{ rosterStore.roleNames[role] }}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
:class="{
|
||||
'center': true,
|
||||
'selected': roleObject?.isMain
|
||||
}"
|
||||
@click="toggle(true)"
|
||||
>
|
||||
Main
|
||||
</button>
|
||||
<button
|
||||
:class="{
|
||||
'right': true,
|
||||
'selected': !(roleObject?.isMain ?? true)
|
||||
}"
|
||||
@click="toggle(false)"
|
||||
>
|
||||
Alternate
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.role {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.role-info {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--mantle);
|
||||
gap: 8px;
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px 0 0 8px;
|
||||
font-size: 10pt;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.role-info.unselected {
|
||||
color: var(--overlay-0);
|
||||
}
|
||||
|
||||
.role button {
|
||||
font-size: 10pt;
|
||||
background-color: var(--mantle);
|
||||
}
|
||||
|
||||
.role button.center {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.role button.right {
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.role button.selected {
|
||||
background-color: var(--accent-transparent);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.role i {
|
||||
line-height: unset;
|
||||
font-size: 12pt;
|
||||
}
|
||||
</style>
|
|
@ -27,7 +27,7 @@ onMounted(() => {
|
|||
v-for="team in teams.teams"
|
||||
>
|
||||
<RouterLink :to="'/team/id/' + team.id">
|
||||
{{ team.team_name }}
|
||||
{{ team.teamName }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -177,13 +177,15 @@ export const useRosterStore = defineStore("roster", () => {
|
|||
"Roamer": "tf2-FlankSoldier",
|
||||
"Demoman": "tf2-Demo",
|
||||
"Medic": "tf2-Medic",
|
||||
});
|
||||
|
||||
"Role.PocketScout": "tf2-PocketScout",
|
||||
"Role.FlankScout": "tf2-FlankScout",
|
||||
"Role.PocketSoldier": "tf2-PocketSoldier",
|
||||
"Role.Roamer": "tf2-FlankSoldier",
|
||||
"Role.Demoman": "tf2-Demo",
|
||||
"Role.Medic": "tf2-Medic",
|
||||
const roleNames = reactive({
|
||||
"PocketScout": "Pocket Scout",
|
||||
"FlankScout": "Flank Scout",
|
||||
"PocketSoldier": "Pocket Soldier",
|
||||
"Roamer": "Roamer",
|
||||
"Demoman": "Demoman",
|
||||
"Medic": "Medic",
|
||||
});
|
||||
|
||||
function selectPlayerForRole(player: PlayerTeamRole, role: string) {
|
||||
|
@ -211,6 +213,7 @@ export const useRosterStore = defineStore("roster", () => {
|
|||
definitelyAvailable,
|
||||
canBeAvailable,
|
||||
roleIcons,
|
||||
roleNames,
|
||||
mainRoles,
|
||||
alternateRoles,
|
||||
}
|
||||
|
|
|
@ -30,15 +30,15 @@ export const useScheduleStore = defineStore("schedule", () => {
|
|||
function getWindowStart(team: TeamSchema) {
|
||||
// convert local 00:00 to league timezone
|
||||
let localMidnight = moment().startOf("isoWeek");
|
||||
let leagueTime = localMidnight.clone().tz(team.tz_timezone);
|
||||
let leagueTime = localMidnight.clone().tz(team.tzTimezone);
|
||||
|
||||
let nextMinuteOffsetTime = leagueTime.clone();
|
||||
|
||||
if (nextMinuteOffsetTime.minute() > team.minute_offset) {
|
||||
if (nextMinuteOffsetTime.minute() > team.minuteOffset) {
|
||||
nextMinuteOffsetTime.add(1, "hour");
|
||||
}
|
||||
|
||||
nextMinuteOffsetTime.minute(team.minute_offset);
|
||||
nextMinuteOffsetTime.minute(team.minuteOffset);
|
||||
|
||||
const deltaMinutes = nextMinuteOffsetTime.diff(leagueTime, "minutes");
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Cacheable from "@/cacheable";
|
||||
import { AvailabilitfClient, type TeamSpec, type ViewTeamMembersResponse, type ViewTeamResponse, type ViewTeamsResponse } from "@/client";
|
||||
import { AvailabilitfClient, type RoleSchema, type TeamSpec, type ViewTeamMembersResponse, type ViewTeamResponse, type ViewTeamsResponse } from "@/client";
|
||||
import { defineStore } from "pinia";
|
||||
import { computed, reactive, ref, type Reactive, type Ref } from "vue";
|
||||
import { useClientStore } from "./client";
|
||||
|
@ -47,11 +47,12 @@ export const useTeamsStore = defineStore("teams", () => {
|
|||
response = response
|
||||
.map((member): ViewTeamMembersResponse => {
|
||||
// TODO: snake_case to camelCase
|
||||
member.roles = member.roles.sort((a, b) => {
|
||||
if (a.is_main == b.is_main) {
|
||||
member.roles = member.roles
|
||||
.sort((a, b) => {
|
||||
if (a.isMain == b.isMain) {
|
||||
return 0;
|
||||
}
|
||||
return a.is_main ? -1 : 1;
|
||||
return a.isMain ? -1 : 1;
|
||||
});
|
||||
return member;
|
||||
});
|
||||
|
@ -70,6 +71,13 @@ export const useTeamsStore = defineStore("teams", () => {
|
|||
});
|
||||
}
|
||||
|
||||
async function updateRoles(teamId: number, playerId: number, roles: RoleSchema[]) {
|
||||
return await client.default
|
||||
.editMemberRoles(teamId.toString(), playerId.toString(), {
|
||||
roles,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
teams,
|
||||
teamMembers,
|
||||
|
@ -77,5 +85,6 @@ export const useTeamsStore = defineStore("teams", () => {
|
|||
fetchTeam,
|
||||
fetchTeamMembers,
|
||||
createTeam,
|
||||
updateRoles
|
||||
};
|
||||
});
|
||||
|
|
|
@ -45,12 +45,15 @@ onMounted(() => {
|
|||
teamsStore.fetchTeams()
|
||||
.then((teamsList) => {
|
||||
options.value = Object.values(teamsList.teams);
|
||||
|
||||
// select team with id in query parameter if exists
|
||||
const queryTeam = teamsList.teams.find(x => x.id == route.query.teamId);
|
||||
if (queryTeam) {
|
||||
selectedTeam.value = queryTeam;
|
||||
schedule.team = queryTeam;
|
||||
schedule.fetchSchedule();
|
||||
} else {
|
||||
selectedTeam.value = options.value[0];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -64,7 +67,7 @@ onMounted(() => {
|
|||
Availability for
|
||||
<v-select
|
||||
:options="options"
|
||||
label="team_name"
|
||||
label="teamName"
|
||||
v-model="selectedTeam"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useRoute, useRouter, RouterLink } from "vue-router";
|
||||
import { useTeamsStore } from "../stores/teams";
|
||||
import { computed, onMounted } from "vue";
|
||||
import PlayerTeamCard from "../components/PlayerTeamCard.vue";
|
||||
|
@ -12,6 +12,11 @@ const team = computed(() => {
|
|||
return teamsStore.teams[route.params.id];
|
||||
});
|
||||
|
||||
const availableMembers = computed(() => {
|
||||
return teamsStore.teamMembers[route.params.id]
|
||||
.filter((member) => member.availability > 0);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
teamsStore.fetchTeam(route.params.id)
|
||||
.then(() => teamsStore.fetchTeamMembers(route.params.id));
|
||||
|
@ -22,10 +27,20 @@ onMounted(() => {
|
|||
<main>
|
||||
<template v-if="team">
|
||||
<h1>
|
||||
{{ team.team_name }}
|
||||
{{ team.teamName }}
|
||||
<RouterLink :to="'/schedule?teamId=' + team.id">
|
||||
<button class="accent">
|
||||
<i class="bi bi-calendar-fill margin"></i>
|
||||
View schedule
|
||||
</button>
|
||||
</RouterLink>
|
||||
<em class="aside" v-if="teamsStore.teamMembers[route.params.id]">
|
||||
{{ teamsStore.teamMembers[route.params.id]?.length }} member(s),
|
||||
{{ availableMembers?.length }} currently available
|
||||
</em>
|
||||
</h1>
|
||||
<table class="member-table">
|
||||
<thead>
|
||||
<!--thead>
|
||||
<tr>
|
||||
<th>
|
||||
Name
|
||||
|
@ -40,11 +55,13 @@ onMounted(() => {
|
|||
Joined
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</thead-->
|
||||
<tbody>
|
||||
<PlayerTeamCard
|
||||
v-for="member in teamsStore.teamMembers[route.params.id]"
|
||||
:player="member"
|
||||
:team="team"
|
||||
:key="member.username"
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -55,6 +72,13 @@ onMounted(() => {
|
|||
<style scoped>
|
||||
h1 {
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1 > em.aside {
|
||||
font-size: 12pt;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
table.member-table {
|
||||
|
|
|
@ -274,7 +274,7 @@ def view_team_members(player: Player, team_id: int, **kwargs):
|
|||
|
||||
def map_role_to_schema(player_team_role: PlayerTeamRole):
|
||||
return ViewTeamMembersResponse.RoleSchema(
|
||||
role=str(player_team_role.role),
|
||||
role=player_team_role.role.name,
|
||||
is_main=player_team_role.is_main,
|
||||
)
|
||||
|
||||
|
@ -297,3 +297,59 @@ def view_team_members(player: Player, team_id: int, **kwargs):
|
|||
).dict(by_alias=True)
|
||||
|
||||
return list(map(map_to_response, player_teams))
|
||||
|
||||
class EditMemberRolesJson(BaseModel):
|
||||
roles: list[ViewTeamMembersResponse.RoleSchema]
|
||||
|
||||
@api_team.patch("/id/<team_id>/edit-player/<target_player_id>")
|
||||
@spec.validate(
|
||||
resp=Response(
|
||||
HTTP_204=None,
|
||||
HTTP_403=None,
|
||||
HTTP_404=None,
|
||||
),
|
||||
operation_id="edit_member_roles"
|
||||
)
|
||||
@requires_authentication
|
||||
def edit_member_roles(
|
||||
json: EditMemberRolesJson,
|
||||
player: Player,
|
||||
team_id: int,
|
||||
target_player_id: int,
|
||||
**kwargs,
|
||||
):
|
||||
print("hiiii lol")
|
||||
target_player = db.session.query(
|
||||
PlayerTeam
|
||||
).where(
|
||||
PlayerTeam.player_id == target_player_id
|
||||
).where(
|
||||
PlayerTeam.team_id == team_id
|
||||
).options(
|
||||
joinedload(PlayerTeam.player),
|
||||
joinedload(PlayerTeam.player_roles),
|
||||
).one_or_none()
|
||||
|
||||
if not target_player:
|
||||
abort(401)
|
||||
|
||||
# TODO: change this to a MERGE statement
|
||||
|
||||
for role in target_player.player_roles:
|
||||
# delete role if not found in json
|
||||
f = filter(lambda x: x.role == role.role.name, json.roles)
|
||||
matched_role = next(f, None)
|
||||
|
||||
if not matched_role:
|
||||
db.session.delete(role)
|
||||
|
||||
for schema in json.roles:
|
||||
role = PlayerTeamRole()
|
||||
role.player_team = target_player
|
||||
role.role = PlayerTeamRole.Role[schema.role]
|
||||
role.is_main = schema.is_main
|
||||
db.session.merge(role)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return make_response({ }, 204)
|
||||
|
|
Loading…
Reference in New Issue