Skip to content
This repository was archived by the owner on Mar 3, 2020. It is now read-only.

Commit 4a7b5b5

Browse files
justinwraygsingh93
authored andcommitted
Level Deletion Confirmation and Bug Fixes (#512)
* Level Deletion Confirmation and Bug Fixes * Added deletion confirmation dialog when deleting levels. * Level data is now deleted from HintLog, ScoresLog, and FailuresLog, when a level is deleted. * Cache invalidation performed on level deletion for records containing levels. * Moved all awaitable queries into a vector which are now executed via AsyncMysqlConnection::multiQuery().
1 parent 2b1474b commit 4a7b5b5

File tree

6 files changed

+169
-19
lines changed

6 files changed

+169
-19
lines changed

src/controllers/AdminController.php

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,14 +1593,26 @@ class=
15931593
$quiz_status_off_id =
15941594
'fb--levels--level-'.strval($quiz->getId()).'-status--off';
15951595

1596-
$quiz_id = 'quiz_id'.strval($quiz->getId());
1596+
$quiz_id = strval($quiz->getId());
1597+
$quiz_id_txt = 'quiz_id'.strval($quiz->getId());
15971598

15981599
$countries_select =
15991600
await $this->genGenerateCountriesSelect($quiz->getEntityId());
16001601

1602+
$delete_button =
1603+
<div style="display: inline">
1604+
<input type="hidden" name="level_id" value={$quiz_id} />
1605+
<a
1606+
href="#"
1607+
class="fb-cta cta--red js-delete-level"
1608+
style="margin-right: 20px">
1609+
{tr('Delete')}
1610+
</a>
1611+
</div>;
1612+
16011613
$adminsections->appendChild(
16021614
<section class="admin-box validate-form section-locked">
1603-
<form class="level_form quiz_form" name={$quiz_id}>
1615+
<form class="level_form quiz_form" name={$quiz_id_txt}>
16041616
<input type="hidden" name="level_type" value="quiz" />
16051617
<input
16061618
type="hidden"
@@ -1729,9 +1741,7 @@ class=
17291741
<a href="#" class="admin--edit" data-action="edit">
17301742
{tr('EDIT')}
17311743
</a>
1732-
<button class="fb-cta cta--red" data-action="delete">
1733-
{tr('Delete')}
1734-
</button>
1744+
{$delete_button}
17351745
<button class="fb-cta cta--yellow" data-action="save">
17361746
{tr('Save')}
17371747
</button>
@@ -1923,7 +1933,19 @@ class=
19231933
$flag_status_off_id =
19241934
'fb--levels--level-'.strval($flag->getId()).'-status--off';
19251935

1926-
$flag_id = 'flag_id'.strval($flag->getId());
1936+
$flag_id_txt = 'flag_id'.strval($flag->getId());
1937+
$flag_id = strval($flag->getId());
1938+
1939+
$delete_button =
1940+
<div style="display: inline">
1941+
<input type="hidden" name="level_id" value={$flag_id} />
1942+
<a
1943+
href="#"
1944+
class="fb-cta cta--red js-delete-level"
1945+
style="margin-right: 20px">
1946+
{tr('Delete')}
1947+
</a>
1948+
</div>;
19271949

19281950
$attachments_div =
19291951
<div class="attachments">
@@ -2108,7 +2130,7 @@ class="fb-cta cta--red"
21082130

21092131
$adminsections->appendChild(
21102132
<section class="validate-form admin-box section-locked">
2111-
<form class="level_form flag_form" name={$flag_id}>
2133+
<form class="level_form flag_form" name={$flag_id_txt}>
21122134
<input type="hidden" name="level_type" value="flag" />
21132135
<input
21142136
type="hidden"
@@ -2248,9 +2270,7 @@ class=
22482270
<a href="#" class="admin--edit" data-action="edit">
22492271
{tr('EDIT')}
22502272
</a>
2251-
<button class="fb-cta cta--red" data-action="delete">
2252-
{tr('Delete')}
2253-
</button>
2273+
{$delete_button}
22542274
<button class="fb-cta cta--yellow" data-action="save">
22552275
{tr('Save')}
22562276
</button>
@@ -2447,7 +2467,19 @@ class=
24472467
$base_status_off_id =
24482468
'fb--levels--level-'.strval($base->getId()).'-status--off';
24492469

2450-
$base_id = 'base_id'.strval($base->getId());
2470+
$base_id = strval($base->getId());
2471+
$base_id_txt = 'base_id'.strval($base->getId());
2472+
2473+
$delete_button =
2474+
<div style="display: inline">
2475+
<input type="hidden" name="level_id" value={$base_id} />
2476+
<a
2477+
href="#"
2478+
class="fb-cta cta--red js-delete-level"
2479+
style="margin-right: 20px">
2480+
{tr('Delete')}
2481+
</a>
2482+
</div>;
24512483

24522484
$attachments_div =
24532485
<div class="attachments">
@@ -2635,7 +2667,7 @@ class="fb-cta cta--red"
26352667

26362668
$adminsections->appendChild(
26372669
<section class="validate-form admin-box section-locked">
2638-
<form class="level_form base_form" name={$base_id}>
2670+
<form class="level_form base_form" name={$base_id_txt}>
26392671
<input type="hidden" name="level_type" value="base" />
26402672
<input
26412673
type="hidden"
@@ -2748,9 +2780,7 @@ class=
27482780
<a href="#" class="admin--edit" data-action="edit">
27492781
{tr('EDIT')}
27502782
</a>
2751-
<button class="fb-cta cta--red" data-action="delete">
2752-
{tr('Delete')}
2753-
</button>
2783+
{$delete_button}
27542784
<button class="fb-cta cta--yellow" data-action="save">
27552785
{tr('Save')}
27562786
</button>

src/controllers/modals/ActionModalController.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,28 @@ private function getModal(string $modal): (:xhp, :xhp) {
9999
</div>
100100
</div>;
101101
return tuple($title, $content);
102+
case 'delete-level':
103+
$title =
104+
<h4>
105+
{tr('delete_')}<span class="highlighted">{tr('Level')}</span>
106+
</h4>;
107+
$content =
108+
<div class="action-main">
109+
<p>
110+
{tr(
111+
'Are you sure you want to delete this level? All data for this level will be irreversibly removed, including scores.',
112+
)}
113+
</p>
114+
<div class="action-actionable">
115+
<a href="#" class="fb-cta cta--red js-close-modal">
116+
{tr('No')}
117+
</a>
118+
<a href="#" id="delete_level" class="fb-cta cta--yellow">
119+
{tr('Yes')}
120+
</a>
121+
</div>
122+
</div>;
123+
return tuple($title, $content);
102124
case 'logout':
103125
$title =
104126
<h4>

src/models/HintLog.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private static function hintlogFromRow(Map<string, string> $row): HintLog {
152152
}
153153
}
154154

155-
// Get all scores.
155+
// Get all hints.
156156
public static async function genAllHints(): Awaitable<array<HintLog>> {
157157
$db = await self::genDb();
158158
$result = await $db->queryf('SELECT * FROM hints_log ORDER BY ts DESC');
@@ -165,7 +165,7 @@ private static function hintlogFromRow(Map<string, string> $row): HintLog {
165165
return $hints;
166166
}
167167

168-
// Get all scores by team.
168+
// Get all hints by team.
169169
public static async function genAllHintsByTeam(
170170
int $team_id,
171171
): Awaitable<array<HintLog>> {
@@ -182,4 +182,22 @@ private static function hintlogFromRow(Map<string, string> $row): HintLog {
182182

183183
return $hints;
184184
}
185+
186+
// Get all hints by level.
187+
public static async function genAllHintsByLevel(
188+
int $level_id,
189+
): Awaitable<array<HintLog>> {
190+
$db = await self::genDb();
191+
$result = await $db->queryf(
192+
'SELECT * FROM hints_log WHERE level_id = %d',
193+
$level_id,
194+
);
195+
196+
$hints = array();
197+
foreach ($result->mapRows() as $row) {
198+
$hints[] = self::hintlogFromRow($row);
199+
}
200+
201+
return $hints;
202+
}
185203
}

src/models/Level.php

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,9 +645,51 @@ private static function levelFromRow(Map<string, string> $row): Level {
645645
$level = await self::gen($level_id);
646646
await Country::genSetUsed($level->getEntityId(), false);
647647

648-
await $db->queryf('DELETE FROM levels WHERE id = %d LIMIT 1', $level_id);
648+
// Remove team points for level
649+
$scores = await ScoreLog::genAllScoresByLevel($level_id);
650+
$level_delete_queries = Vector {};
651+
foreach ($scores as $score) {
652+
$team_id = $score->getTeamId();
653+
$points = $score->getPoints();
654+
$level_delete_queries->add(
655+
sprintf(
656+
'UPDATE teams SET points = points - %d WHERE id = %d',
657+
$points,
658+
$team_id,
659+
),
660+
);
661+
}
649662

650-
self::invalidateMCRecords(); // Invalidate Memcached Level data.
663+
// Remove hint penalties from teams points for level
664+
$hints = await HintLog::genAllHintsByLevel($level_id);
665+
foreach ($hints as $hint) {
666+
$team_id = $hint->getTeamId();
667+
$penalty = $hint->getPenalty();
668+
$level_delete_queries->add(
669+
sprintf(
670+
'UPDATE teams SET points = points + %d WHERE id = %d',
671+
$penalty,
672+
$team_id,
673+
),
674+
);
675+
}
676+
677+
// Delete all references to level
678+
$level_delete_queries->addAll(
679+
Set {
680+
sprintf('DELETE FROM levels WHERE id = %d LIMIT 1', $level_id),
681+
sprintf('DELETE FROM hints_log WHERE level_id = %d', $level_id),
682+
sprintf('DELETE FROM scores_log WHERE level_id = %d', $level_id),
683+
sprintf('DELETE FROM failures_log WHERE level_id = %d', $level_id),
684+
},
685+
);
686+
await $db->multiQuery($level_delete_queries);
687+
688+
self::invalidateMCRecords();
689+
Control::invalidateMCRecords();
690+
MultiTeam::invalidateMCRecords();
691+
HintLog::invalidateMCRecords();
692+
ScoreLog::invalidateMCRecords();
651693
}
652694

653695
// Enable or disable level by passing 1 or 0.

src/models/ScoreLog.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,24 @@ private static function scorelogFromRow(Map<string, string> $row): ScoreLog {
202202
return $scores;
203203
}
204204

205+
// Get all scores by level.
206+
public static async function genAllScoresByLevel(
207+
int $level_id,
208+
): Awaitable<array<ScoreLog>> {
209+
$db = await self::genDb();
210+
$result = await $db->queryf(
211+
'SELECT * FROM scores_log WHERE level_id = %d',
212+
$level_id,
213+
);
214+
215+
$scores = array();
216+
foreach ($result->mapRows() as $row) {
217+
$scores[] = self::scorelogFromRow($row);
218+
}
219+
220+
return $scores;
221+
}
222+
205223
// Log successful score.
206224
public static async function genLogValidScore(
207225
int $level_id,

src/static/js/admin.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ function deleteTeamPopup(team_id) {
4646
sendAdminRequest(delete_team, true);
4747
}
4848

49+
//Confirm level deletion
50+
function deleteLevelPopup(level_id) {
51+
var delete_level = {
52+
action: 'delete_level',
53+
level_id: level_id
54+
};
55+
sendAdminRequest(delete_level, true);
56+
}
57+
4958
// Reset the database
5059
function resetDatabase() {
5160
var reset_database = {
@@ -1402,6 +1411,17 @@ module.exports = {
14021411
});
14031412
});
14041413

1414+
// prompt delete level
1415+
$('.js-delete-level').on('click', function(event) {
1416+
event.preventDefault();
1417+
var level_id = $(this).prev('input').attr('value');
1418+
Modal.loadPopup('p=action&modal=delete-level', 'action-delete-level', function() {
1419+
$('#delete_level').click(function() {
1420+
deleteLevelPopup(level_id);
1421+
});
1422+
});
1423+
});
1424+
14051425
// prompt logout
14061426
$('.js-prompt-logout').on('click', function(event) {
14071427
event.preventDefault();

0 commit comments

Comments
 (0)