From: Daniel Karbach Date: Sun, 20 Mar 2022 20:14:26 +0000 (+0100) Subject: tournament admins X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=eebc6384e56336b66ec250fc2aea3be6171d53ff;p=alttp.git tournament admins --- diff --git a/app/Models/Participant.php b/app/Models/Participant.php index c2a8d8a..8aac88c 100644 --- a/app/Models/Participant.php +++ b/app/Models/Participant.php @@ -17,6 +17,10 @@ class Participant extends Model return $this->belongsTo(User::class); } + protected $casts = [ + 'roles' => 'array', + ]; + protected $with = [ 'user', ]; diff --git a/app/Models/User.php b/app/Models/User.php index 535af2e..4f56ac1 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -14,13 +14,31 @@ class User extends Authenticatable public function isParticipant(Tournament $tournament) { foreach ($tournament->participants as $participant) { - if ($participant->user->id == $this->id) { + if ($participant->user_id == $this->id) { return true; } } return false; } + public function isRunner(Tournament $tournament) { + foreach ($tournament->participants as $participant) { + if ($participant->user_id == $this->id) { + return in_array('runner', $participant->roles); + } + } + return false; + } + + public function isTournamentAdmin(Tournament $tournament) { + foreach ($tournament->participants as $participant) { + if ($participant->user_id == $this->id) { + return in_array('admin', $participant->roles); + } + } + return false; + } + public function participation() { return $this->hasMany(Participant::class); } diff --git a/app/Policies/TournamentPolicy.php b/app/Policies/TournamentPolicy.php index 2cc6b6e..fa27298 100644 --- a/app/Policies/TournamentPolicy.php +++ b/app/Policies/TournamentPolicy.php @@ -113,7 +113,7 @@ class TournamentPolicy */ public function viewProtocol(User $user, Tournament $tournament) { - return $user->role === 'admin'; + return $user->role === 'admin' || $user->isTournamentAdmin($tournament); } } diff --git a/database/migrations/2022_03_20_191356_participant_roles.php b/database/migrations/2022_03_20_191356_participant_roles.php new file mode 100644 index 0000000..33867e8 --- /dev/null +++ b/database/migrations/2022_03_20_191356_participant_roles.php @@ -0,0 +1,32 @@ +text('roles')->default('["runner"]'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('participants', function(Blueprint $table) { + $table->dropColumn('roles'); + }); + } +}; diff --git a/resources/js/components/results/List.js b/resources/js/components/results/List.js index 8775529..cdd90e8 100644 --- a/resources/js/components/results/List.js +++ b/resources/js/components/results/List.js @@ -3,9 +3,10 @@ import React from 'react'; import Item from './Item'; import { sortByResult } from '../../helpers/Participant'; +import { getRunners } from '../../helpers/Tournament'; const List = ({ round, tournament }) =>
- {sortByResult(tournament.participants, round).map((participant, index) => + {sortByResult(getRunners(tournament), round).map((participant, index) =>

{i18n.t('tournaments.scoreboard')}

- {tournament.participants ? + {hasRunners(tournament) ? : null} + {hasTournamentAdmins(tournament) ? + <> +
+

{i18n.t('tournaments.admins')}

+
+ {getTournamentAdmins(tournament).map(p => +

+ )} + + : null} ; diff --git a/resources/js/helpers/Participant.js b/resources/js/helpers/Participant.js index eb94340..d79349b 100644 --- a/resources/js/helpers/Participant.js +++ b/resources/js/helpers/Participant.js @@ -40,6 +40,12 @@ export const findResult = (participant, round) => { return round.results.find(result => result.user_id === participant.user_id); }; +export const isRunner = participant => + participant && participant.roles && participant.roles.includes('runner'); + +export const isTournamentAdmin = participant => + participant && participant.roles && participant.roles.includes('admin'); + export const patchUser = (participant, user) => { if (!participant || !user) return participant; if (participant.user_id != user.id) return participant; @@ -62,6 +68,8 @@ export default { compareResult, compareUsername, findResult, + isRunner, + isTournamentAdmin, patchUser, sortByResult, }; diff --git a/resources/js/helpers/Tournament.js b/resources/js/helpers/Tournament.js index a3f97cc..31414de 100644 --- a/resources/js/helpers/Tournament.js +++ b/resources/js/helpers/Tournament.js @@ -2,8 +2,7 @@ import Participant from './Participant'; import Round from './Round'; export const calculateScores = tournament => { - if (!tournament || !tournament.participants || !tournament.participants.length) return []; - const scores = tournament.participants.map(participant => ({ participant, score: 0 })); + const scores = getRunners(tournament).map(participant => ({ participant, score: 0 })); if (!tournament.rounds || !tournament.rounds.length) return scores; tournament.rounds.forEach(round => { const filtered = Participant @@ -39,7 +38,7 @@ export const compareScore = (a, b) => { const b_score = b && b.score ? b.score : 0; if (a_score < b_score) return -1; if (b_score < a_score) return 1; - return 0; + return Participant.compareUsername(a.participant, b.participant); }; export const findParticipant = (tournament, user) => { @@ -48,6 +47,28 @@ export const findParticipant = (tournament, user) => { return tournament.participants.find(p => p.user_id == user.id); }; +export const getRunners = tournament => { + if (!tournament || !tournament.participants || !tournament.participants.length) return []; + return tournament.participants + .filter(Participant.isRunner) + .sort(Participant.compareUsername); +}; + +export const getTournamentAdmins = tournament => { + if (!tournament || !tournament.participants || !tournament.participants.length) return []; + return tournament.participants + .filter(Participant.isTournamentAdmin) + .sort(Participant.compareUsername); +}; + +export const hasRunners = tournament => { + return getRunners(tournament).length > 0; +}; + +export const hasTournamentAdmins = tournament => { + return getTournamentAdmins(tournament).length > 0; +}; + export const patchResult = (tournament, result) => { if (!tournament || !tournament.rounds) return tournament; return { diff --git a/resources/js/helpers/permissions.js b/resources/js/helpers/permissions.js index 23272d9..21016f1 100644 --- a/resources/js/helpers/permissions.js +++ b/resources/js/helpers/permissions.js @@ -13,6 +13,16 @@ export const isParticipant = (user, tournament) => user && tournament && tournament.participants && tournament.participants.find(p => p.user && p.user.id == user.id); +export const isRunner = (user, tournament) => { + const p = isParticipant(user, tournament); + return p && p.roles && p.roles.includes('runner'); +}; + +export const isTournamentAdmin = (user, tournament) => { + const p = isParticipant(user, tournament); + return p && p.roles && p.roles.includes('admin'); +}; + export const hasFinished = (user, round) => user && round && round.results && round.results.find(r => r.user_id == user.id && r.has_finished); @@ -23,8 +33,8 @@ export const mayAddRounds = (user, tournament) => export const maySetSeed = (user, tournament) => isAdmin(user) || isParticipant(user, tournament); -export const mayViewProtocol = user => - isAdmin(user); +export const mayViewProtocol = (user, tournament) => + isAdmin(user) || isTournamentAdmin(user, tournament); export const maySeeResults = (user, tournament, round) => isAdmin(user) || hasFinished(user, round) || Round.isComplete(tournament, round); diff --git a/resources/js/i18n/de.js b/resources/js/i18n/de.js index 75c0b02..3bfadc1 100644 --- a/resources/js/i18n/de.js +++ b/resources/js/i18n/de.js @@ -144,6 +144,7 @@ export default { setSeedSuccess: 'Seed eingetragen', }, tournaments: { + admins: 'Organisation', scoreboard: 'Scoreboard', }, users: { diff --git a/resources/js/i18n/en.js b/resources/js/i18n/en.js index d2ee9c0..ccd5e95 100644 --- a/resources/js/i18n/en.js +++ b/resources/js/i18n/en.js @@ -144,6 +144,7 @@ export default { setSeedSuccess: 'Seed set', }, tournaments: { + admins: 'Admins', scoreboard: 'Scoreboard', }, users: {