From 3f6f1748e655803c6fc3106394ade597e46b0423 Mon Sep 17 00:00:00 2001 From: panda Date: Thu, 23 Mar 2023 15:07:30 +0800 Subject: [PATCH] ui: add scoreboard pjax (#545) --- packages/hydrooj/src/handler/contest.ts | 3 +- .../pages/contest_scoreboard.page.ts | 10 +++ .../templates/contest_scoreboard.html | 84 +----------------- .../templates/partials/scoreboard.html | 86 +++++++++++++++++++ 4 files changed, 99 insertions(+), 84 deletions(-) create mode 100644 packages/ui-default/templates/partials/scoreboard.html diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index ae36fcb2d..2eac35757 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -280,7 +280,6 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler { config.lockAt = this.tdoc.lockAt; } const [, rows, udict, pdict] = await contest.getScoreboard.call(this, domainId, tid, config); - this.response.template = 'contest_scoreboard.html'; // eslint-disable-next-line @typescript-eslint/naming-convention const page_name = this.tdoc.rule === 'homework' ? 'homework_scoreboard' @@ -288,6 +287,8 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler { this.response.body = { tdoc: this.tdoc, rows, udict, pdict, page_name, }; + this.response.pjax = 'partials/scoreboard.html'; + this.response.template = 'contest_scoreboard.html'; } async exportGhost(domainId: string, tid: ObjectId) { diff --git a/packages/ui-default/pages/contest_scoreboard.page.ts b/packages/ui-default/pages/contest_scoreboard.page.ts index 3ea594b30..ebdc4a6e4 100644 --- a/packages/ui-default/pages/contest_scoreboard.page.ts +++ b/packages/ui-default/pages/contest_scoreboard.page.ts @@ -1,5 +1,6 @@ import $ from 'jquery'; import { NamedPage } from 'vj/misc/Page'; +import { pjax } from 'vj/utils'; const page = new NamedPage('contest_scoreboard', () => { const { tdoc } = UiContext; @@ -34,6 +35,15 @@ const page = new NamedPage('contest_scoreboard', () => { $('.rank--unrank').closest('tr').hide(); } }); + + const beginAt = new Date(UiContext.tdoc.beginAt).getTime(); + const endAt = new Date(UiContext.tdoc.endAt).getTime(); + function updateScoreboard() { + const now = Date.now(); + if (beginAt <= now && now <= endAt) pjax.request(UiContext.scoreboardUrl || '', { push: false }); + } + + setInterval(updateScoreboard, 180000); }); export default page; diff --git a/packages/ui-default/templates/contest_scoreboard.html b/packages/ui-default/templates/contest_scoreboard.html index cb24abb74..0cc046569 100644 --- a/packages/ui-default/templates/contest_scoreboard.html +++ b/packages/ui-default/templates/contest_scoreboard.html @@ -3,13 +3,6 @@ {{ set(UiContext, 'tdoc', tdoc) }} {% set type = 'homework' if tdoc.rule == 'homework' else 'contest' %} -{% macro renderRecord(cell, canView) %} - - {%- set _color = utils.status.getScoreColor(cell.score|default(cell.value)) -%} - {{ cell.value|string|nl2br|safe }} - -{% endmacro %} - {% block content %}
@@ -35,82 +28,7 @@
- {% if model.contest.isLocked(tdoc) %} -
-
- {{ _('The scoreboard was frozen with {0} minutes remaining at {1} - submissions in the last {0} minutes of the contest are still shown as pending.').format((tdoc.endAt - tdoc.lockAt) / 1000 / 60, datetimeSpan(tdoc.lockAt))|safe }} -
-
- {% elif model.contest.isDone(tdoc) and tdoc.lockAt and not tdoc.unlocked %} -
-
- {{ _('Please wait until contest host unfreeze the scoreboard.') }} -
-
- {% endif %} -
- - - {%- for column in rows[0] -%} - - {%- endfor -%} - - - - {%- for column in rows[0] -%} - - {%- endfor -%} - - - - {%- set canViewAll = handler.user.own(tdoc) or model.contest.canShowRecord.call(handler, tdoc) -%} - {%- for row in rows -%}{%- if loop.index0 > 0 -%} - - {%- for column in row -%} - - {%- endfor -%} - - {%- endif -%}{%- endfor -%} - -
- {%- if column.type == 'problem' and column.raw -%} - - {{ column.value }}
{{ pdict[column.raw].nAccept|default(0) }}/{{ pdict[column.raw].nSubmit|default(0) }} -
- {%- else -%} - {{ column.value|string|nl2br|safe }} - {%- endif -%} -
- {%- if column.type == 'rank' -%} - {{ '*' if column.value == '0' else column.value|string|nl2br|safe }} - {%- elif column.type == 'user' -%} - {%- set canView = canViewAll or handler.user._id == column.raw -%} - - {{ user.render_inline(udict[column.raw], badge=false) }} - {%- elif column.type == 'record' and column.raw -%} - - {{ column.value|string|nl2br|safe }} - - {%- elif column.type == 'records' -%} - {%- for record in column.raw -%} - {%- if loop.index0 -%}/{%- endif -%} - {%- if record.raw -%} - - {%- set _color = utils.status.getScoreColor(record.score|default(record.value)) -%} - {{ record.value|string|nl2br|safe }} - - {%- else -%} - {{ record.value|string|nl2br|safe }} - {%- endif -%} - {%- endfor -%} - {%- else -%} - {{ column.value|string|nl2br|safe }} - {%- endif -%} -
-
+ {% include "partials/scoreboard.html" %}
{% endblock %} diff --git a/packages/ui-default/templates/partials/scoreboard.html b/packages/ui-default/templates/partials/scoreboard.html new file mode 100644 index 000000000..40d4d5767 --- /dev/null +++ b/packages/ui-default/templates/partials/scoreboard.html @@ -0,0 +1,86 @@ +{% import "components/user.html" as user with context %} +{% macro renderRecord(cell, canView) %} + + {%- set _color = utils.status.getScoreColor(cell.score|default(cell.value)) -%} + {{ cell.value|string|nl2br|safe }} + +{% endmacro %} + +
+ {% if model.contest.isLocked(tdoc) %} +
+
+ {{ _('The scoreboard was frozen with {0} minutes remaining at {1} - submissions in the last {0} minutes of the contest are still shown as pending.').format((tdoc.endAt - tdoc.lockAt) / 1000 / 60, datetimeSpan(tdoc.lockAt))|safe }} +
+
+ {% elif model.contest.isDone(tdoc) and tdoc.lockAt and not tdoc.unlocked %} +
+
+ {{ _('Please wait until contest host unfreeze the scoreboard.') }} +
+
+ {% endif %} +
+ + + {%- for column in rows[0] -%} + + {%- endfor -%} + + + + {%- for column in rows[0] -%} + + {%- endfor -%} + + + + {%- set canViewAll = handler.user.own(tdoc) or model.contest.canShowRecord.call(handler, tdoc) -%} + {%- for row in rows -%}{%- if loop.index0 > 0 -%} + + {%- for column in row -%} + + {%- endfor -%} + + {%- endif -%}{%- endfor -%} + +
+ {%- if column.type == 'problem' and column.raw -%} + + {{ column.value }}
{{ pdict[column.raw].nAccept|default(0) }}/{{ pdict[column.raw].nSubmit|default(0) }} +
+ {%- else -%} + {{ column.value|string|nl2br|safe }} + {%- endif -%} +
+ {%- if column.type == 'rank' -%} + {{ '*' if column.value == '0' else column.value|string|nl2br|safe }} + {%- elif column.type == 'user' -%} + {%- set canView = canViewAll or handler.user._id == column.raw -%} + + {{ user.render_inline(udict[column.raw], badge=false) }} + {%- elif column.type == 'record' and column.raw -%} + + {{ column.value|string|nl2br|safe }} + + {%- elif column.type == 'records' -%} + {%- for record in column.raw -%} + {%- if loop.index0 -%}/{%- endif -%} + {%- if record.raw -%} + + {%- set _color = utils.status.getScoreColor(record.score|default(record.value)) -%} + {{ record.value|string|nl2br|safe }} + + {%- else -%} + {{ record.value|string|nl2br|safe }} + {%- endif -%} + {%- endfor -%} + {%- else -%} + {{ column.value|string|nl2br|safe }} + {%- endif -%} +
+
+
\ No newline at end of file