]> git.localhorst.tv Git - alttp.git/commitdiff
tournament monitors
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 27 Mar 2022 12:33:44 +0000 (14:33 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 27 Mar 2022 12:33:44 +0000 (14:33 +0200)
app/Models/User.php
app/Policies/ParticipantPolicy.php
app/Policies/RoundPolicy.php
app/Policies/TournamentPolicy.php
resources/js/components/rounds/SeedButton.js
resources/js/components/tournament/Detail.js
resources/js/helpers/Participant.js
resources/js/helpers/Tournament.js
resources/js/helpers/permissions.js
resources/js/i18n/de.js
resources/js/i18n/en.js

index eea1426d8fcc7c592aca5592b5a2ef70f7765253..e5bb4f174b49b5f2a96446627ab0148421f7f725 100644 (file)
@@ -12,6 +12,10 @@ class User extends Authenticatable
 {
        use HasApiTokens, HasFactory, Notifiable;
 
+       public function isAdmin() {
+               return $this->role === 'admin';
+       }
+
        public function isParticipant(Tournament $tournament) {
                foreach ($tournament->participants as $participant) {
                        if ($participant->user_id == $this->id) {
@@ -39,6 +43,19 @@ class User extends Authenticatable
                return false;
        }
 
+       public function isTournamentCrew(Tournament $tournament) {
+               return $this->isTournamentAdmin($tournament) || $this->isTournamentMonitor($tournament);
+       }
+
+       public function isTournamentMonitor(Tournament $tournament) {
+               foreach ($tournament->participants as $participant) {
+                       if ($participant->user_id == $this->id) {
+                               return in_array('monitor', $participant->roles);
+                       }
+               }
+               return false;
+       }
+
 
        public function participation() {
                return $this->hasMany(Participant::class);
index f5b5246222b0adb1a3561ef99d82c11c2fc39679..8622d12de3c9e3909abe2ef8f02345a9300c9da4 100644 (file)
@@ -18,7 +18,7 @@ class ParticipantPolicy
         */
        public function viewAny(User $user)
        {
-               return $user->role === 'admin';
+               return $user->isAdmin();
        }
 
        /**
@@ -30,7 +30,7 @@ class ParticipantPolicy
         */
        public function view(User $user, Participant $participant)
        {
-               return $user->role === 'admin';
+               return $user->isAdmin();
        }
 
        /**
@@ -53,7 +53,7 @@ class ParticipantPolicy
         */
        public function update(User $user, Participant $participant)
        {
-               return $user->role === 'admin';
+               return $user->isAdmin();
        }
 
        /**
index 230b2254d9c9469d29d388c56905aa9b0647464b..c1a1a4845beb157e0ddcc50547ced4d28b440531 100644 (file)
@@ -101,7 +101,7 @@ class RoundPolicy
         */
        public function setSeed(User $user, Round $round)
        {
-               return $user->role === 'admin' || ($user->isParticipant($round->tournament) && !$round->locked);
+               return $user->isAdmin() || (!$round->locked && ($user->isRunner($round->tournament) || $user->isTournamentAdmin($round->tournament)));
        }
 
        /**
@@ -113,7 +113,7 @@ class RoundPolicy
         */
        public function lock(User $user, Round $round)
        {
-               return $user->role === 'admin' || $user->isTournamentAdmin($round->tournament);
+               return $user->isAdmin() || $user->isTournamentAdmin($round->tournament);
        }
 
        /**
index fa27298435246cd4f2f186ca4be4f886ce42c5a7..72b5dcba3131dfe9ae53c4f4c463fef6f34ec7da 100644 (file)
@@ -101,7 +101,7 @@ class TournamentPolicy
         */
        public function addRound(User $user, Tournament $tournament)
        {
-               return $user->role === 'admin' || (!$tournament->locked && $user->isParticipant($tournament));
+               return $user->isAdmin() || (!$tournament->locked && ($user->isRunner($tournament) || $user->isTournamentAdmin($tournament)));
        }
 
        /**
@@ -113,7 +113,7 @@ class TournamentPolicy
         */
        public function viewProtocol(User $user, Tournament $tournament)
        {
-               return $user->role === 'admin' || $user->isTournamentAdmin($tournament);
+               return $user->isAdmin() || $user->isTournamentCrew($tournament);
        }
 
 }
index 1d68b6a833ca129caa9b481cf40182b8df488c46..d9d343304eca067fc7996fa72c940f187a85badc 100644 (file)
@@ -18,7 +18,7 @@ const SeedButton = ({ round, tournament, user }) => {
                        </Button>
                );
        }
-       if (maySetSeed(user, tournament)) {
+       if (maySetSeed(user, tournament, round)) {
                return <>
                        <SeedDialog
                                onHide={() => setShowDialog(false)}
index 1afcc29f10611a1e434c13f3a035dcfad3da9cee..cfea60d2bcd8100bb164282bd89017880e15f0da 100644 (file)
@@ -14,8 +14,10 @@ import {
 } from '../../helpers/permissions';
 import {
        getTournamentAdmins,
+       getTournamentMonitors,
        hasRunners,
        hasTournamentAdmins,
+       hasTournamentMonitors,
 } from '../../helpers/Tournament';
 import { withUser } from '../../helpers/UserContext';
 import i18n from '../../i18n';
@@ -66,6 +68,16 @@ const Detail = ({
                                        )}
                                </>
                        : null}
+                       {hasTournamentMonitors(tournament) ?
+                               <>
+                                       <div className="d-flex align-items-center justify-content-between">
+                                               <h2>{i18n.t('tournaments.monitors')}</h2>
+                                       </div>
+                                       {getTournamentMonitors(tournament).map(p =>
+                                               <p key={p.id}><Box user={p.user} /></p>
+                                       )}
+                               </>
+                       : null}
                </Col>
                <Col lg={{ order: 1, span: 8 }} xl={{ order: 1, span: 9 }}>
                        <div className="d-flex align-items-center justify-content-between">
index 8545e0335c2f37c9fb854138e1a930211d18648e..4b4b6ef51c5ee0cb72a73b9ddaca50e2d2321e1a 100644 (file)
@@ -41,6 +41,12 @@ export const isRunner = participant =>
 export const isTournamentAdmin = participant =>
        participant && participant.roles && participant.roles.includes('admin');
 
+export const isTournamentCrew = participant =>
+       isTournamentAdmin(participant) || isTournamentMonitor(participant);
+
+export const isTournamentMonitor = participant =>
+       participant && participant.roles && participant.roles.includes('monitor');
+
 export const patchUser = (participant, user) => {
        if (!participant || !user) return participant;
        if (participant.user_id != user.id) return participant;
@@ -65,6 +71,8 @@ export default {
        findResult,
        isRunner,
        isTournamentAdmin,
+       isTournamentCrew,
+       isTournamentMonitor,
        patchUser,
        sortByResult,
 };
index ec141d12829b9758405314e052ddeae2aba9d7d7..7dbcb9b5b294386c8d4a725eeeacdcbb64b854da 100644 (file)
@@ -29,6 +29,20 @@ export const getTournamentAdmins = tournament => {
                .sort(Participant.compareUsername);
 };
 
+export const getTournamentCrew = tournament => {
+       if (!tournament || !tournament.participants || !tournament.participants.length) return [];
+       return tournament.participants
+               .filter(Participant.isTournamentCrew)
+               .sort(Participant.compareUsername);
+};
+
+export const getTournamentMonitors = tournament => {
+       if (!tournament || !tournament.participants || !tournament.participants.length) return [];
+       return tournament.participants
+               .filter(Participant.isTournamentMonitor)
+               .sort(Participant.compareUsername);
+};
+
 export const hasRunners = tournament => {
        return getRunners(tournament).length > 0;
 };
@@ -37,6 +51,14 @@ export const hasTournamentAdmins = tournament => {
        return getTournamentAdmins(tournament).length > 0;
 };
 
+export const hasTournamentCrew = tournament => {
+       return getTournamentCrew(tournament).length > 0;
+};
+
+export const hasTournamentMonitors = tournament => {
+       return getTournamentMonitors(tournament).length > 0;
+};
+
 export const patchParticipant = (tournament, participant) => {
        if (!tournament) return tournament;
        if (!tournament.participants || !tournament.participants.length) {
@@ -103,6 +125,12 @@ export default {
        findParticipant,
        getRunners,
        getTournamentAdmins,
+       getTournamentCrew,
+       getTournamentMonitors,
+       hasRunners,
+       hasTournamentAdmins,
+       hasTournamentCrew,
+       hasTournamentMonitors,
        patchResult,
        patchRound,
        patchUser,
index 3df65d6461dfbd94d27c5caf1a7f7f6e8ea488ee..f86b5851c94c4553486b3f2b741678de9c345197 100644 (file)
@@ -23,24 +23,35 @@ export const isTournamentAdmin = (user, tournament) => {
        return p && p.roles && p.roles.includes('admin');
 };
 
+export const isTournamentCrew = (user, tournament) =>
+       isTournamentAdmin(user, tournament) || isTournamentMonitor(user, tournament);
+
+export const isTournamentMonitor = (user, tournament) => {
+       const p = isParticipant(user, tournament);
+       return p && p.roles && p.roles.includes('monitor');
+};
+
 export const hasFinished = (user, round) =>
        user && round && round.results &&
        round.results.find(r => r.user_id == user.id && r.has_finished);
 
 export const mayAddRounds = (user, tournament) =>
-       isAdmin(user) || (!tournament.locked && isParticipant(user, tournament));
+       isAdmin(user) || (!tournament.locked &&
+               (isRunner(user, tournament) || isTournamentAdmin(user, tournament)));
 
 export const mayLockRound = (user, tournament) =>
        isAdmin(user) || (!tournament.locked && isTournamentAdmin(user, tournament));
 
-export const maySetSeed = (user, tournament) =>
-       isAdmin(user) || isParticipant(user, tournament);
+export const maySetSeed = (user, tournament, round) =>
+       isAdmin(user) || (!round.locked &&
+               (isRunner(user, tournament) || isTournamentAdmin(user, tournament)));
 
 export const mayViewProtocol = (user, tournament) =>
-       isAdmin(user) || isTournamentAdmin(user, tournament);
+       isAdmin(user) || isTournamentCrew(user, tournament);
 
 export const maySeeResults = (user, tournament, round) =>
-       isAdmin(user) || hasFinished(user, round) || Round.isComplete(tournament, round);
+       isAdmin(user) || hasFinished(user, round) ||
+               isTournamentMonitor(user, tournament) || Round.isComplete(tournament, round);
 
 // Users
 
index 9416ead6722c7f21809642c4ec0231fec1089b49..17cb41f0cc49e96fe30d77a3f17d01d91a5324ed 100644 (file)
@@ -114,6 +114,7 @@ export default {
                        placementSubjectToChange: 'Das Turnier wurde noch nicht abgeschlossen, die Platzierung kann sich noch ändern.',
                        roleNames: {
                                admin: 'Administrator',
+                               monitor: 'Monitor',
                                runner: 'Runner',
                        },
                        roles: 'Teilnahme als',
@@ -177,6 +178,7 @@ export default {
                },
                tournaments: {
                        admins: 'Organisation',
+                       monitors: 'Monitore',
                        noRecord: 'Turnier wird nicht gewertet',
                        scoreboard: 'Scoreboard',
                },
index 6aa5cc8802d4b132e0c6e8f3990e0546a90546c1..f0c6871e1ef499e075721bb15b82536b5f1fe97a 100644 (file)
@@ -114,6 +114,7 @@ export default {
                        placementSubjectToChange: 'Tournament incomplete, placement subject to change.',
                        roleNames: {
                                admin: 'Administrator',
+                               monitor: 'Monitor',
                                runner: 'Runner',
                        },
                        roles: 'Participated as',
@@ -177,6 +178,7 @@ export default {
                },
                tournaments: {
                        admins: 'Admins',
+                       monitors: 'Monitors',
                        noRecord: 'Tournament set to not be recorded',
                        scoreboard: 'Scoreboard',
                },