return $result->toJson();
}
+ public function unverify(Request $request, Result $result) {
+ $this->authorize('unverify', $result);
+
+ $result->verified_at = null;
+ $result->verified_by()->associate(null);
+ $result->save();
+
+ Protocol::resultUnverified(
+ $result->round->tournament,
+ $result,
+ $request->user(),
+ );
+
+ ResultChanged::dispatch($result);
+
+ return $result->toJson();
+ }
+
public function verify(Request $request, Result $result) {
$this->authorize('verify', $result);
ProtocolAdded::dispatch($protocol);
}
+ public static function resultUnverified(Tournament $tournament, Result $result, User $user) {
+ $protocol = static::create([
+ 'tournament_id' => $tournament->id,
+ 'user_id' => $user->id,
+ 'type' => 'result.unverify',
+ 'details' => [
+ 'tournament' => static::tournamentMemo($tournament),
+ 'result' => static::resultMemo($result),
+ 'runner' => static::userMemo($result->user),
+ 'round' => static::roundMemo($result->round),
+ ],
+ ]);
+ ProtocolAdded::dispatch($protocol);
+ }
+
public static function resultVerified(Tournament $tournament, Result $result, User $user) {
$protocol = static::create([
'tournament_id' => $tournament->id,
return false;
}
+ /**
+ * Determine whether the user can unverify the result.
+ *
+ * @param \App\Models\User $user
+ * @param \App\Models\Result $result
+ * @return \Illuminate\Auth\Access\Response|bool
+ */
+ public function unverify(User $user, Result $result)
+ {
+ return $user->isTournamentCrew($result->round->tournament);
+ }
+
/**
* Determine whether the user can verify the result.
*
<Spoiler>{{time}}</Spoiler>,
</Trans>;
}
+ case 'result.unverify':
case 'result.verify': {
const number = getEntryRoundNumber(entry);
const runner = getEntryResultRunner(entry);
return <Icon.VERIFIED />;
case 'round.create':
return <Icon.ADD />;
+ case 'result.unverify':
case 'round.delete':
return <Icon.REMOVE />;
case 'round.edit':
import Icon from '../common/Icon';
import Box from '../users/Box';
-import { mayVerifyResult } from '../../helpers/permissions';
+import { mayUnverifyResult, mayVerifyResult } from '../../helpers/permissions';
import { useUser } from '../../hooks/user';
const Verification = ({ actions, result, round, tournament }) => {
+ const [unverifying, setUnverifying] = React.useState(false);
const [verifying, setVerifying] = React.useState(false);
const { t } = useTranslation();
[user, result, round, tournament],
);
+ const mayUnverify = React.useMemo(
+ () => mayUnverifyResult(user, tournament, round, result),
+ [user, result, round, tournament],
+ );
+
+ const handleUnverifyClick = React.useCallback(async () => {
+ setUnverifying(true);
+ try {
+ await actions.unverifyResult(result);
+ } catch (e) {
+ console.error(e);
+ }
+ setUnverifying(false);
+ }, [actions, result]);
+
const handleVerifyClick = React.useCallback(async () => {
setVerifying(true);
try {
const date = result?.verified_at ? new Date(result.verified_at) : null;
if (result?.verified_at) {
- return <div>
- {result.verified_by ?
- <Trans i18nKey="results.verifiedAtBy">
- {{date}}
- <Box user={result.verified_by} />
- </Trans>
- :
- t('results.verifiedAt', { date })
- }
+ return <div className="d-flex justify-content-between">
+ <div>
+ {result.verified_by ?
+ <Trans i18nKey="results.verifiedAtBy">
+ {{date}}
+ <Box user={result.verified_by} />
+ </Trans>
+ :
+ t('results.verifiedAt', { date })
+ }
+ </div>
+ {mayUnverify ?
+ <Button
+ onClick={handleUnverifyClick}
+ title={t('results.unverify')}
+ variant="outline-danger"
+ >
+ <Icon.REMOVE title="" />
+ </Button>
+ : null}
</div>;
}
Verification.propTypes = {
actions: PropTypes.shape({
+ unverifyResult: PropTypes.func,
verifyResult: PropTypes.func,
}),
result: PropTypes.shape({
return mayVerifyResults(user, tournament) && user && result && user.id !== result.user_id;
};
+export const mayUnverifyResults = mayVerifyResults;
+export const mayUnverifyResult = mayVerifyResult;
+
// Twitch
export const mayManageTwitchBot = user => isAnyChannelAdmin(user);
result: {
comment: 'Ergebnis von Runde {{number}} kommentiert: <1>{{comment}}</1>',
report: 'Ergebnis von <1>{{time}}</1> bei Runde {{number}} eingetragen',
+ unverify: 'Verifikation von Ergebnis in Runde {{number}} von {{runner}} (<2>{{time}}</2>) zurückgezogen',
verify: 'Ergebnis in Runde {{number}} von {{runner}} (<2>{{time}}</2>) verifiziert',
},
round: {
score: 'Punkte',
table: 'Tabelle',
time: 'Zeit: {{ time }}',
+ unverify: 'Verifikation entziehen',
+ unverifyError: 'Fehler beim Entziehen',
+ unverifySuccess: 'Verifikation entzogen',
verification: 'Verifikation',
verificationPending: 'Noch nicht verifiziert',
verifiedAt: 'Verifiziert am {{ date, L }}',
result: {
comment: 'Result of round {{number}} commented: <1>{{comment}}</1>',
report: 'Result of <1>{{time}}</1> reported for round {{number}}',
+ unverify: 'Revoked verification for round {{number}} result of {{runner}} (<2>{{time}}</2>)',
verify: 'Verified round {{number}} result of {{runner}} (<2>{{time}}</2>)',
},
round: {
score: 'Score',
table: 'Table',
time: 'Time: {{ time }}',
+ unverify: 'Revoke verification',
+ unverifyError: 'Error revoking verification',
+ unverifySuccess: 'Verification revoked',
verification: 'Verification',
verificationPending: 'Pending verification',
verifiedAt: 'Verified on {{ date, L }}',
import Detail from '../components/tournament/Detail';
import {
mayEditContent,
+ mayUnverifyResults,
mayVerifyResults,
} from '../helpers/permissions';
import { getTranslation } from '../helpers/Technique';
}
}, [id, t]);
+ const unverifyResult = React.useCallback(async (result) => {
+ try {
+ const response = await axios.post(`/api/results/${result.id}/unverify`);
+ toastr.success(t('results.unverifySuccess'));
+ setTournament(tournament => patchResult(tournament, response.data));
+ } catch (e) {
+ toastr.error(t('results.unverifyError', e));
+ }
+ });
+
const verifyResult = React.useCallback(async (result) => {
try {
const response = await axios.post(`/api/results/${result.id}/verify`);
} : null,
moreRounds: canLoadMoreRounds(tournament) ? moreRounds : null,
selfAssignGroups,
+ unverifyResult: mayUnverifyResults(user, tournament) ? unverifyResult : null,
verifyResult: mayVerifyResults(user, tournament) ? verifyResult : null,
}), [addRound, moreRounds, selfAssignGroups, tournament, user, verifyResult]);
Route::post('results', 'App\Http\Controllers\ResultController@create');
Route::post('results/{result}/verify', 'App\Http\Controllers\ResultController@verify');
+Route::post('results/{result}/unverify', 'App\Http\Controllers\ResultController@unverify');
Route::post('rounds', 'App\Http\Controllers\RoundController@create');
Route::put('rounds/{round}', 'App\Http\Controllers\RoundController@update');