From d1c996dfab2da112190d53423f152d27752bb67b Mon Sep 17 00:00:00 2001 From: undefined Date: Fri, 28 Apr 2023 11:10:59 +0800 Subject: [PATCH 1/2] ui: scoreboard: virtual-scroll --- .../pages/contest_scoreboard.page.ts | 45 ++++++++--- .../templates/partials/scoreboard.html | 81 ++++++++++--------- 2 files changed, 77 insertions(+), 49 deletions(-) diff --git a/packages/ui-default/pages/contest_scoreboard.page.ts b/packages/ui-default/pages/contest_scoreboard.page.ts index 161658feb5..2a287c124a 100644 --- a/packages/ui-default/pages/contest_scoreboard.page.ts +++ b/packages/ui-default/pages/contest_scoreboard.page.ts @@ -1,3 +1,4 @@ +import Clusterize from 'clusterize.js'; import $ from 'jquery'; import { NamedPage } from 'vj/misc/Page'; import { pjax } from 'vj/utils'; @@ -5,7 +6,7 @@ import { pjax } from 'vj/utils'; const page = new NamedPage('contest_scoreboard', () => { const { tdoc } = UiContext; const key = `scoreboard-star/${tdoc.domainId}/${tdoc.docId}`; - const read = () => JSON.parse(localStorage.getItem(key) || '[]'); + const read = () => JSON.parse(localStorage.getItem(key) || '[]').map((i) => +i); const write = (data) => localStorage.setItem(key, JSON.stringify(data)); read().forEach((uid) => $(`.star.user--${uid}`).addClass('activated')); @@ -23,22 +24,40 @@ const page = new NamedPage('contest_scoreboard', () => { write(star); }); + const rows: Record = {}; + const total = []; + let nowRendering = []; + const unrank = []; + for (const line of $('.data-table tbody tr')) { + const uid = +$(line).find('[data-uid]').data('uid'); + line.style.display = 'table-row'; + rows[uid] = line.outerHTML; + nowRendering.push(uid); + total.push(uid); + if ($(line).find('.rank--unrank').length) unrank.push(uid); + $(line).remove(); + } + + const virtualizedList = new Clusterize({ + rows: nowRendering.map((i) => rows[i]), + scrollElem: $('.data-table').get(0), + contentElem: $('tbody').get(0), + }); + $('.select.filter').on('change', (e) => { const val = $(e.target).val(); - if (val === 'all') { - $('.data-table tbody tr').show(); - } else if (val === 'star') { - $('.data-table tbody tr').hide(); - read().forEach((uid) => $(`.star.user--${uid}`).closest('tr').show()); - } else if (val === 'rank') { - $('.data-table tbody tr').show(); - $('.rank--unrank').closest('tr').hide(); - } else { - $('.data-table tbody tr').hide(); + if (val === 'all') nowRendering = total; + else if (val === 'star') nowRendering = read(); + else if (val === 'rank') nowRendering = total.filter((i) => !unrank.includes(i)); + else { + nowRendering = []; const uids = val.toString().split(',').map((i) => +i.trim()).filter((i) => i); - if (!uids?.length) return; - uids.forEach((uid) => $(`.user--${uid}`).closest('tr').show()); + for (const uid of total) { + if (!uids.includes(+uid)) continue; + nowRendering.push(uid); + } } + virtualizedList.update(nowRendering.map((i) => rows[i])); }); const beginAt = new Date(UiContext.tdoc.beginAt).getTime(); diff --git a/packages/ui-default/templates/partials/scoreboard.html b/packages/ui-default/templates/partials/scoreboard.html index c71caee0b4..6f11e1f04f 100644 --- a/packages/ui-default/templates/partials/scoreboard.html +++ b/packages/ui-default/templates/partials/scoreboard.html @@ -6,6 +6,41 @@ {% endmacro %} +{% macro scoreboardRow(row) %} +{%- for column in row -%} + + {%- 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 -%} + +{%- endfor -%} +{% endmacro %} +
{% if model.contest.isLocked(tdoc) %}
@@ -42,42 +77,16 @@ {%- 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 -%} - - {%- 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 -%} - - {%- endfor -%} - - {%- endif -%}{%- endfor -%} + {%- for row in rows -%} + {%- if loop.index0 == 1001 -%} + {{ noscript_note.render() }} + {%- endif -%} + {%- if loop.index0 > 1000 -%} + {{ scoreboardRow(row) }} + {%- elif loop.index0 > 0 -%} + {{ scoreboardRow(row) }} + {%- endif -%} + {%- endfor -%}
From c0cfa13dff087e41c97c8a4db5e47ef54188e4c7 Mon Sep 17 00:00:00 2001 From: undefined Date: Sun, 30 Apr 2023 00:44:22 +0800 Subject: [PATCH 2/2] update packages --- packages/ui-default/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 2e984c5c69..8fbf90e16c 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -48,6 +48,7 @@ "chalk": "^5.2.0", "classnames": "^2.3.2", "clipboard": "^2.0.11", + "clusterize.js": "^1.0.0", "cordis": "^2.7.4", "diff": "^5.1.0", "diff-dom": "^5.0.4",