Add team mark missing

bulk-table-profile-actions
Kevin Chung 2020-05-02 15:04:04 -04:00
parent 76bd626c36
commit a2e5aa4b9e
9 changed files with 182 additions and 65 deletions

View File

@ -2,7 +2,7 @@ import "./main";
import $ from "jquery"; import $ from "jquery";
import CTFd from "core/CTFd"; import CTFd from "core/CTFd";
import { htmlEntities } from "core/utils"; import { htmlEntities } from "core/utils";
import { ezQuery, ezBadge } from "core/ezq"; import { ezAlert, ezQuery, ezBadge } from "core/ezq";
import { createGraph, updateGraph } from "core/graphs"; import { createGraph, updateGraph } from "core/graphs";
function createTeam(event) { function createTeam(event) {
@ -88,12 +88,12 @@ function deleteSelectedSubmissions(event, target) {
case "solves": case "solves":
submissions = $("input[data-submission-type=correct]:checked"); submissions = $("input[data-submission-type=correct]:checked");
type = "solve"; type = "solve";
title = "Solves" title = "Solves";
break; break;
case "fails": case "fails":
submissions = $("input[data-submission-type=incorrect]:checked"); submissions = $("input[data-submission-type=incorrect]:checked");
type = "fail"; type = "fail";
title = "Fails" title = "Fails";
break; break;
default: default:
break; break;
@ -102,11 +102,13 @@ function deleteSelectedSubmissions(event, target) {
let submissionIDs = submissions.map(function() { let submissionIDs = submissions.map(function() {
return $(this).data("submission-id"); return $(this).data("submission-id");
}); });
let target_string = submissionIDs.length === 1 ? type : (type + "s"); let target_string = submissionIDs.length === 1 ? type : type + "s";
ezQuery({ ezQuery({
title: `Delete ${title}`, title: `Delete ${title}`,
body: `Are you sure you want to delete ${submissionIDs.length} ${target_string}?`, body: `Are you sure you want to delete ${
submissionIDs.length
} ${target_string}?`,
success: function() { success: function() {
const reqs = []; const reqs = [];
for (var subId of submissionIDs) { for (var subId of submissionIDs) {
@ -148,6 +150,62 @@ function deleteSelectedAwards(event) {
}); });
} }
function solveSelectedMissingChallenges(event) {
event.preventDefault();
let challengeIDs = $("input[data-missing-challenge-id]:checked").map(
function() {
return $(this).data("missing-challenge-id");
}
);
let target = challengeIDs.length === 1 ? "challenge" : "challenges";
ezQuery({
title: `Mark Correct`,
body: `Are you sure you want to mark ${
challengeIDs.length
} correct for ${htmlEntities(TEAM_NAME)}?`,
success: function() {
ezAlert({
title: `User Attribution`,
body: `
Which user on ${htmlEntities(TEAM_NAME)} solved these challenges?
<div class="pb-3" id="query-team-member-solve">
${$("#team-member-select").html()}
</div>
`,
button: "Mark Correct",
success: function() {
const USER_ID = $("#query-team-member-solve > select").val();
const reqs = [];
for (var challengeID of challengeIDs) {
let params = {
provided: "MARKED AS SOLVED BY ADMIN",
user_id: USER_ID,
team_id: TEAM_ID,
challenge_id: challengeID,
type: "correct"
};
let req = CTFd.fetch("/api/v1/submissions", {
method: "POST",
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(params)
});
reqs.push(req);
}
Promise.all(reqs).then(responses => {
window.location.reload();
});
}
});
}
});
}
const api_funcs = { const api_funcs = {
team: [ team: [
x => CTFd.api.get_team_solves({ teamId: x }), x => CTFd.api.get_team_solves({ teamId: x }),
@ -404,17 +462,21 @@ $(() => {
}); });
$("#solves-delete-button").click(function(e) { $("#solves-delete-button").click(function(e) {
deleteSelectedSubmissions(e, "solves") deleteSelectedSubmissions(e, "solves");
}); });
$("#fails-delete-button").click(function(e) { $("#fails-delete-button").click(function(e) {
deleteSelectedSubmissions(e, "fails") deleteSelectedSubmissions(e, "fails");
}); });
$("#awards-delete-button").click(function(e) { $("#awards-delete-button").click(function(e) {
deleteSelectedAwards(e); deleteSelectedAwards(e);
}); });
$("#missing-solve-button").click(function(e) {
solveSelectedMissingChallenges(e);
});
$("#team-info-create-form").submit(createTeam); $("#team-info-create-form").submit(createTeam);
$("#team-info-edit-form").submit(updateTeam); $("#team-info-edit-form").submit(updateTeam);

View File

@ -197,12 +197,12 @@ function deleteSelectedSubmissions(event, target) {
case "solves": case "solves":
submissions = $("input[data-submission-type=correct]:checked"); submissions = $("input[data-submission-type=correct]:checked");
type = "solve"; type = "solve";
title = "Solves" title = "Solves";
break; break;
case "fails": case "fails":
submissions = $("input[data-submission-type=incorrect]:checked"); submissions = $("input[data-submission-type=incorrect]:checked");
type = "fail"; type = "fail";
title = "Fails" title = "Fails";
break; break;
default: default:
break; break;
@ -211,11 +211,13 @@ function deleteSelectedSubmissions(event, target) {
let submissionIDs = submissions.map(function() { let submissionIDs = submissions.map(function() {
return $(this).data("submission-id"); return $(this).data("submission-id");
}); });
let target_string = submissionIDs.length === 1 ? type : (type + "s"); let target_string = submissionIDs.length === 1 ? type : type + "s";
ezQuery({ ezQuery({
title: `Delete ${title}`, title: `Delete ${title}`,
body: `Are you sure you want to delete ${submissionIDs.length} ${target_string}?`, body: `Are you sure you want to delete ${
submissionIDs.length
} ${target_string}?`,
success: function() { success: function() {
const reqs = []; const reqs = [];
for (var subId of submissionIDs) { for (var subId of submissionIDs) {
@ -259,14 +261,18 @@ function deleteSelectedAwards(event) {
function solveSelectedMissingChallenges(event) { function solveSelectedMissingChallenges(event) {
event.preventDefault(); event.preventDefault();
let challengeIDs = $("input[data-missing-challenge-id]:checked").map(function() { let challengeIDs = $("input[data-missing-challenge-id]:checked").map(
function() {
return $(this).data("missing-challenge-id"); return $(this).data("missing-challenge-id");
}); }
);
let target = challengeIDs.length === 1 ? "challenge" : "challenges"; let target = challengeIDs.length === 1 ? "challenge" : "challenges";
ezQuery({ ezQuery({
title: `Mark Correct`, title: `Mark Correct`,
body: `Are you sure you want to mark ${challengeIDs.length} correct for ${htmlEntities(USER_NAME)}?`, body: `Are you sure you want to mark ${
challengeIDs.length
} correct for ${htmlEntities(USER_NAME)}?`,
success: function() { success: function() {
const reqs = []; const reqs = [];
for (var challengeID of challengeIDs) { for (var challengeID of challengeIDs) {
@ -286,7 +292,7 @@ function solveSelectedMissingChallenges(event) {
"Content-Type": "application/json" "Content-Type": "application/json"
}, },
body: JSON.stringify(params) body: JSON.stringify(params)
}) });
reqs.push(req); reqs.push(req);
} }
Promise.all(reqs).then(responses => { Promise.all(reqs).then(responses => {
@ -407,11 +413,11 @@ $(() => {
$("#user-mail-form").submit(emailUser); $("#user-mail-form").submit(emailUser);
$("#solves-delete-button").click(function(e) { $("#solves-delete-button").click(function(e) {
deleteSelectedSubmissions(e, "solves") deleteSelectedSubmissions(e, "solves");
}); });
$("#fails-delete-button").click(function(e) { $("#fails-delete-button").click(function(e) {
deleteSelectedSubmissions(e, "fails") deleteSelectedSubmissions(e, "fails");
}); });
$("#awards-delete-button").click(function(e) { $("#awards-delete-button").click(function(e) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -61,6 +61,15 @@
</div> </div>
</div> </div>
<template id="team-member-select">
<select class="form-control custom-select">
<option value=""> -- </option>
{% for member in members %}
<option value="{{ member.id }}">{{ member.name }}</option>
{% endfor %}
</select>
</template>
<div id="team-addresses-modal" class="modal fade"> <div id="team-addresses-modal" class="modal fade">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
@ -235,6 +244,9 @@
<a class="nav-item nav-link" id="nav-awards-tab" data-toggle="tab" href="#nav-awards" role="tab" <a class="nav-item nav-link" id="nav-awards-tab" data-toggle="tab" href="#nav-awards" role="tab"
aria-controls="nav-awards" aria-selected="false">Awards</a> aria-controls="nav-awards" aria-selected="false">Awards</a>
<a class="nav-item nav-link" id="nav-missing-tab" data-toggle="tab" href="#nav-missing" role="tab"
aria-controls="nav-missing" aria-selected="false">Missing</a>
</nav> </nav>
<div class="tab-content min-vh-50" id="nav-tabContent"> <div class="tab-content min-vh-50" id="nav-tabContent">
@ -424,6 +436,58 @@
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="nav-missing" role="tabpanel" aria-labelledby="nav-missing-tab">
<h3 class="text-center pt-5 d-block">Missing</h3>
<div class="row">
<div class="col-md-12">
<div class="float-right pb-3">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-success" id="missing-solve-button">
<i class="btn-fa fas fa-check"></i>
</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-striped border">
<thead>
<tr>
<th class="border-right" data-checkbox>
<div class="form-check text-center">
<input type="checkbox" class="form-check-input" data-checkbox-all>&nbsp;
</div>
</th>
<th class="sort-col text-center"><b>Challenge</b></th>
<th class="sort-col text-center"><b>Category</b></th>
<th class="sort-col text-center"><b>Value</b></th>
</tr>
</thead>
<tbody>
{% for challenge in missing %}
<tr class="chal-solve" data-href="{{ url_for("admin.challenges_detail", challenge_id=challenge.id) }}">
<td class="border-right" data-checkbox>
<div class="form-check text-center">
<input type="checkbox" class="form-check-input" value="{{ challenge.id }}" data-missing-challenge-id="{{ challenge.id }}"
data-missing-challenge-name="{{ challenge.name }}">&nbsp;
</div>
</td>
<td class="text-center chal" id="{{ challenge.id }}">
<a href="{{ url_for("admin.challenges_detail", challenge_id=challenge.id) }}">
{{ challenge.name }}
</a>
</td>
<td class="text-center">{{ challenge.category }}</td>
<td class="text-center">{{ challenge.value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div> </div>
</div> </div>

View File

@ -359,14 +359,6 @@
<td class="text-center">{{ award.value }}</td> <td class="text-center">{{ award.value }}</td>
<td class="text-center">{{ award.category }}</td> <td class="text-center">{{ award.category }}</td>
<td class="text-center"> <i class="award-icon award-{{ award.icon }}"></i> {{ award.icon }}</td> <td class="text-center"> <i class="award-icon award-{{ award.icon }}"></i> {{ award.icon }}</td>
<!-- <td class="text-center">
<span class="delete-award" data-toggle="tooltip"
data-placement="top" award-id="{{ award.id }}" award-name="{{ award.name }}"
title="Delete award #{{ award.id }}">
<i class="fas fa-times"></i>
</span>
</td> -->
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -419,13 +411,6 @@
</td> </td>
<td class="text-center">{{ challenge.category }}</td> <td class="text-center">{{ challenge.category }}</td>
<td class="text-center">{{ challenge.value }}</td> <td class="text-center">{{ challenge.value }}</td>
<!-- <td class="text-center">
<a class="correct-submission" data-toggle="tooltip" challenge-id="{{ challenge.id }}"
challenge-name="{{ challenge.name }}"
data-placement="top" title="Mark {{ challenge.name }} correct for {{ user.name }}">
<i class="fas fa-check"></i>
</a>
</td> -->
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

File diff suppressed because one or more lines are too long