From 00392f1272695011caa0f9c5fca2400a92557783 Mon Sep 17 00:00:00 2001 From: undefined Date: Wed, 11 Dec 2024 18:20:28 +0800 Subject: [PATCH] ui: better domain_user page performance --- framework/eslint-config/package.json | 2 +- packages/hydrooj/src/handler/domain.ts | 17 ++++++++--------- packages/ui-default/backendlib/template.ts | 3 +++ packages/ui-default/package.json | 4 ++-- packages/ui-default/pages/domain_user.page.js | 2 +- packages/ui-default/templates/domain_user.html | 17 +++++++++++++++-- .../ui-default/templates/domain_user_raw.html | 5 +++++ 7 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 packages/ui-default/templates/domain_user_raw.html diff --git a/framework/eslint-config/package.json b/framework/eslint-config/package.json index 8cb52e77d..2a7a58c1c 100644 --- a/framework/eslint-config/package.json +++ b/framework/eslint-config/package.json @@ -4,7 +4,7 @@ "license": "MIT", "main": "react.yaml", "dependencies": { - "@stylistic/eslint-plugin": "^2.11.0", + "@stylistic/eslint-plugin": "^2.12.0", "@typescript-eslint/eslint-plugin": "^8.17.0", "@typescript-eslint/parser": "^8.17.0", "eslint-config-airbnb": "^19.0.4", diff --git a/packages/hydrooj/src/handler/domain.ts b/packages/hydrooj/src/handler/domain.ts index 438ff8629..8c55d3ce3 100644 --- a/packages/hydrooj/src/handler/domain.ts +++ b/packages/hydrooj/src/handler/domain.ts @@ -96,7 +96,8 @@ class DomainDashboardHandler extends ManageHandler { class DomainUserHandler extends ManageHandler { @requireSudo - async get({ domainId }) { + @param('format', Types.Range(['default', 'raw']), true) + async get({ domainId }, format = 'default') { const rudocs = {}; const [dudocs, roles] = await Promise.all([ domain.getMultiUserInDomain(domainId, { @@ -107,15 +108,13 @@ class DomainUserHandler extends ManageHandler { }).toArray(), domain.getRoles(domainId), ]); - const uids = dudocs.map((dudoc) => dudoc.uid); - const udict = await user.getList(domainId, uids); - for (const role of roles) rudocs[role._id] = []; - for (const dudoc of dudocs) { - const udoc = udict[dudoc.uid]; - if (!(udoc.priv & PRIV.PRIV_USER_PROFILE)) continue; - rudocs[udoc.role || 'default'].push(udoc); + // TODO: switch to getListForRender for better performance + const udict = await user.getList(domainId, dudocs.map((dudoc) => dudoc.uid)); + const users = dudocs.filter((dudoc) => udict[dudoc.uid].priv & PRIV.PRIV_USER_PROFILE); + for (const role of roles) { + rudocs[role._id] = users.filter((dudoc) => dudoc.role === role._id).map((i) => udict[i.uid]); } - this.response.template = 'domain_user.html'; + this.response.template = format === 'raw' ? 'domain_user_raw.html' : 'domain_user.html'; this.response.body = { roles, rudocs, udict, domain: this.domain, }; diff --git a/packages/ui-default/backendlib/template.ts b/packages/ui-default/backendlib/template.ts index 51222dc63..51cd17e26 100644 --- a/packages/ui-default/backendlib/template.ts +++ b/packages/ui-default/backendlib/template.ts @@ -166,6 +166,7 @@ env.addGlobal('platformIcon', (platform) => { }); const render = (name: string, state: any) => new Promise((resolve, reject) => { + const start = Date.now(); env.render(name, { page_name: name.split('.')[0], ...state, @@ -180,6 +181,8 @@ const render = (name: string, state: any) => new Promise((resolve, rejec STATUS, UiContext: state.handler?.UiContext || {}, }, (err, res) => { + const end = Date.now(); + if (end - start > 5000) console.error(`Render of ${name} took ${end - start}ms`); if (err) reject(err); else resolve(res); }); diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index ac42b1915..e65d54550 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -88,11 +88,11 @@ "prop-types": "^15.8.1", "qface": "^1.4.1", "qrcode": "^1.5.4", - "react": "^19.0.0", + "react": "^18.3.1", "react-colorful": "^5.6.1", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", - "react-dom": "^19.0.0", + "react-dom": "^18.3.1", "react-query": "^3.39.3", "react-redux": "^9.1.2", "reconnecting-websocket": "^4.4.0", diff --git a/packages/ui-default/pages/domain_user.page.js b/packages/ui-default/pages/domain_user.page.js index 90a9a18d6..71884486a 100644 --- a/packages/ui-default/pages/domain_user.page.js +++ b/packages/ui-default/pages/domain_user.page.js @@ -73,7 +73,7 @@ const page = new NamedPage('domain_user', () => { function ensureAndGetSelectedUsers() { const users = _.map( $('.domain-users tbody [type="checkbox"]:checked'), - (ch) => $(ch).closest('tr').attr('data-uid'), + (ch) => $(ch).attr('data-uid') || $(ch).closest('tr').attr('data-uid'), ); if (users.length === 0) { Notification.error(i18n('Please select at least one user to perform this operation.')); diff --git a/packages/ui-default/templates/domain_user.html b/packages/ui-default/templates/domain_user.html index e3b72d7ae..a3b7dbec0 100644 --- a/packages/ui-default/templates/domain_user.html +++ b/packages/ui-default/templates/domain_user.html @@ -75,8 +75,20 @@

{{ _('{0}: Users').format(domain.name) }}

- {%- for role in roles -%} - {%- for rudoc in rudocs[role._id] -%} + {%- for role, udocs in rudocs -%} + {%- if udocs|length > 50 -%} + +
+ {%- for udoc in udocs -%} + {% set is_disabled=(rudoc._id == handler.user._id) %} + + [{{udoc._id}}]{{ user.render_inline(udoc, avatar=false, badge=false) }}    + {%- endfor -%} +
+ {{ role }} + + {%- else -%} + {%- for rudoc in udocs -%} {% set is_disabled=(rudoc._id == handler.user._id) %} @@ -101,6 +113,7 @@

{{ _('{0}: Users').format(domain.name) }}

{%- endfor -%} + {%- endif -%} {%- endfor -%} diff --git a/packages/ui-default/templates/domain_user_raw.html b/packages/ui-default/templates/domain_user_raw.html new file mode 100644 index 000000000..d64087c3e --- /dev/null +++ b/packages/ui-default/templates/domain_user_raw.html @@ -0,0 +1,5 @@ +
+{%- for role in roles -%}{%- for rudoc in rudocs[role._id] -%}
+{{ rudoc._id }},{{ rudoc.role }},{{ udict[rudoc._id].uname }},{{ udict[rudoc._id].displayName}}
+{% endfor -%}{%- endfor -%}
+
\ No newline at end of file