Skip to content

Commit

Permalink
Merge pull request #152 from ustclug/vue-term
Browse files Browse the repository at this point in the history
Multiple enhancements to UI
  • Loading branch information
RTXUX authored Oct 12, 2023
2 parents c7be2d6 + a24298b commit cb334ce
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 8 deletions.
12 changes: 10 additions & 2 deletions frontend/static/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ table {
.content {
margin: 0 auto 2em;
padding: 0 1em;
max-width: 72em;
max-width: 81em;
}
@media screen and (min-width: 48em) {
.content {
Expand Down Expand Up @@ -121,7 +121,7 @@ h1 {
}
@media screen and (min-width: 48em) {
.challenges {
max-width: 25em;
max-width: 28em;
margin-left: 1em;
}
}
Expand Down Expand Up @@ -189,3 +189,11 @@ table .narrow {
max-width: 50%;
width: 100%;
}
/* revert changes by purecss in form */
#token {
border: revert;
background-color: revert;
padding: revert;
vertical-align: revert;
border-radius: revert;
}
23 changes: 21 additions & 2 deletions frontend/templates/hub.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
</td>
<td class="center narrow"><span class="category" :style="{backgroundColor: category_color(challenge.category)}">{{ challenge.category }}</span></td>
<td class="center narrow">{{ challenge.score }}</td>
<td class="center narrow">{{ (clear_count.challenges.find(i=>i.challenge===challenge.pk)||{count:0}).count }}</td>
<td class="center narrow">{{ get_challenge_count(challenge) }}</td>
</tr>
<tr v-if="challenge===opened && challenge.flags.length>1" v-for="(flag, flag_index) in challenge.flags" class="flag">
<td>
Expand All @@ -101,7 +101,7 @@
</td>
<td></td>
<td class="center narrow">{{ flag.score }}</td>
<td class="center narrow">{{ (clear_count.flags.find(i=>i.challenge===challenge.pk&&i.flag===flag_index)||{count:0}).count }}</td>
<td class="center narrow">{{ get_subchallenge_count(challenge, flag_index) }}</td>
</tr>
</template>
<tr v-if="user.is_staff">
Expand Down Expand Up @@ -216,6 +216,25 @@ <h1>{{ opened.name }}</h1>
} while (!color.valid());
return color.hex();
},
get_challenge_count(challenge) {
let count = (this.clear_count.flags.find(i => i.challenge === challenge.pk) || {count: 0}).count;
// are there any sub-flags?
if (challenge.flags.length > 1) {
let max_sub = 0;
for (let j = 0; j < challenge.flags.length; j++) {
let sub_count = this.get_subchallenge_count(challenge, j);
if (sub_count > max_sub) {
max_sub = sub_count;
}
}
return `${count} (${max_sub})`;
}
return count;
},
get_subchallenge_count(challenge, flag_index) {
let count = (this.clear_count.flags.find(i => i.challenge === challenge.pk && i.flag === flag_index) || {count: 0}).count;
return count;
}
},
updated: function () {
this.$nextTick(function () {
Expand Down
27 changes: 26 additions & 1 deletion frontend/templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ <h1>修改个人信息</h1>
如果你看到这条消息,说明你的浏览器版本过低或网络存在问题,导致比赛平台不能正常加载。请忽略以下显示的任何信息,换用最新版 Firefox 或 Chrome 浏览器访问比赛平台。
</div>
<div v-if="user.group==='banned'" class="msg-error">
由于违反规则,你的参赛资格已被取消,如有疑问请联系 <a href="mailto:[email protected]">[email protected]</a>
由于违反规则,你的参赛资格已被取消,如有疑问请联系 <a href="mailto:[email protected]">[email protected]</a>
并在邮件中粘贴下面的 token。
</div>
<div v-if="user && user.group==='banned'" class="msg-info">
<label for="token">Token:</label>
<button @click.prevent.stop="token_show=!token_show">{{ token_show?'隐藏':'显示' }}</button>
<input v-show="token_show" type="text" id="token" :value="user.token" readonly>
<button @click.prevent.stop="token_copy()">{{ token_copy_text }}</button>
Token 是一些题目的登录凭证,禁止分享,否则视为作弊
</div>
<div v-if="info.length" class="msg-info">
<div v-for="i in info">{{ i }}</div>
Expand Down Expand Up @@ -89,6 +97,21 @@ <h1>修改个人信息</h1>
{{ user_.json|json_script:'json-user' }}
{{ profile_required|json_script:'json-profile_required' }}
<script>
function token_copy() {
let t = app.token_show;
app.token_show = true;
Vue.nextTick(function () {
let copyText = document.getElementById("token");
copyText.select();
copyText.setSelectionRange(0, 99999);
document.execCommand("copy");
app.token_show = t;
app.token_copy_text = '已复制';
setTimeout(function () {
app.token_copy_text = '复制';
}, 1000);
});
}
let user = JSON.parse(document.getElementById('json-user').textContent);
let profile_required = JSON.parse(document.getElementById('json-profile_required').textContent);
let fields_required = {};
Expand Down Expand Up @@ -132,6 +155,8 @@ <h1>修改个人信息</h1>
fields: fields_required,
info,
submit_disabled: false,
token_show: false,
token_copy_text: '复制',
},
methods: {
submit() {
Expand Down
87 changes: 84 additions & 3 deletions frontend/templates/terms.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,96 @@
{% extends 'base.html' %}
{% load static %}

{% block js %}
{{ block.super }}
<script src="{% static 'vue.min.js' %}"></script>
{% endblock %}

{% block content %}
{% verbatim %}
<div id="app">
<form method="post">
{% endverbatim %}{% comment %} 用户条款页面支持以下的扩展:
<script id="json-quiz" type="application/json">
{"header": "请选择所有不违反以上条款的内容:", "questions": [[true, "使用搜索引擎搜索以尝试解题"], [false, "问做出题目的舍友 flag"], [false, "在群聊中分享自己的解题方法"], [true, "一边听歌一边做题"]]}
</script>
{% endcomment %}
{% csrf_token %}
{% for obj in terms %}
<h1>{{ obj.name }}</h1>
<input type="hidden" name="terms" value="{{ obj.pk }}">
<div>{{ obj.content|safe }}</div>
{% endfor %}
{% if user_ %}
<button type="submit" class="pure-button pure-button-primary">我理解并同意以上条款</button>
{% endif %}
{% verbatim %}
<div v-if="user_">
<div id="vue-quiz" v-if="quizs">
<hr>
<p>以下问题回答正确后,同意按钮才会启用。</p>
<span v-if="quizs.header">{{ quizs.header }}</span>
<ul>
<li v-for="(quiz, index) in quizs.questions">
<div>
<input type="checkbox" :name="`quiz-${index}`" @change="check()">
<label v-for="`quiz-${quiz.pk}`">{{ quiz[1] }}</label>
</div>
</li>
</ul>
</div>
<!-- 请读者注意:以任何形式提交理解并同意的网络请求均视为已经完全理解并且同意以上条款的内容。 -->
<button type="submit" class="pure-button pure-button-primary" :disabled="!enable_submit">我理解并同意以上条款</button>
</div>
</form>
</div>
{% endverbatim %}
{{ user_.json|json_script:'json-user' }}
<script>
app = new Vue({
el: '#app',
data: {
user_: JSON.parse(document.getElementById('json-user').textContent),
enable_submit: false,
quizs: null,
},
created() {
this.init_quiz();
},
methods: {
init_quiz() {
const ele = document.getElementById('json-quiz');
if (!ele) {
this.enable_submit = true;
return;
}
const quizs = JSON.parse(ele.textContent);
// comment out this if you don't want to shuffle the quizs.
this.inplace_shuffle(quizs.questions);
this.quizs = quizs;
},
check() {
for (const [index, quiz] of this.quizs.questions.entries()) {
const ele = document.getElementsByName(`quiz-${index}`)[0];
const user_checked = ele.checked;
const correct_ans = quiz[0];
if (correct_ans != user_checked) {
this.enable_submit = false;
return;
}
}
this.enable_submit = true;
},
inplace_shuffle(array) {
// https://stackoverflow.com/a/2450976/8460426
let current_index = array.length;
let random_index;

while (current_index > 0) {
random_index = Math.floor(Math.random() * current_index);
current_index--;

[array[current_index], array[random_index]] = [array[random_index], array[current_index]];
}
}
}
});
</script>
{% endblock %}

0 comments on commit cb334ce

Please sign in to comment.