feat: add manager profile pages#618
Conversation
Add profile pages for label entities and link risk manager/curator displays into the new route.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughIntroduces a manager profile feature: new utility helpers ( ChangesManager Profile Feature
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser / Router
participant ManagerPage as pages/managers/[slug].vue
participant Composable as useEulerManagerProfile
participant Utils as manager-profile utils
participant Stores as Euler Stores
Browser->>ManagerPage: navigate to /managers/:slug
ManagerPage->>Composable: useEulerManagerProfile(slug)
Composable->>Stores: read label entities, vault lists, product lists
Composable->>Utils: getEulerLabelEntitySlug(), isEulerLabelProductManagedBy()
Utils-->>Composable: resolved slugs, filtered products/vaults
Composable-->>ManagerPage: entity, productEntries, evaults, securitizeVaults, earnVaults, vaultCount, isLoading
ManagerPage->>ManagerPage: render identity, metrics, products, vault sections
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
composables/useEulerManagerProfile.ts (2)
35-61: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winConsider precomputing an entity→slug map to avoid repeated O(n) scans.
getEulerLabelEntitySlugrunsObject.entries(entities).find(...)(up to twice) for every manager of every vault, so each list recompute is roughly O(vaults · managers · entities). Building a reverse map once per recompute keeps the filters near-linear.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@composables/useEulerManagerProfile.ts` around lines 35 - 61, The filtering in useEulerManagerProfile.ts repeatedly calls getEulerLabelEntitySlug for every manager, causing nested O(n) scans over entities during evaults, securitizeVaults, and earnVaults recomputation. Precompute a reverse entity-to-slug lookup once per recompute in the same composable, then have managesEntity and managesEarnEntity read from that map instead of calling getEulerLabelEntitySlug repeatedly. Keep the existing computed lists and filter/sort flow, but make the slug resolution constant-time by keying off the same entities source used by getEulerLabelEntitySlug.
35-43: 🗄️ Data Integrity & Integration | 🔵 TrivialCache entity slug lookups in
useEulerManagerProfile
getEulerLabelEntitySlugscansentitieswithObject.entriesfor every manager check, so these computed filters repeat the same work. A reverse lookup map would avoid the extra passes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@composables/useEulerManagerProfile.ts` around lines 35 - 43, Cache the repeated entity slug resolution in useEulerManagerProfile by introducing a reverse lookup from entity id to slug instead of calling getEulerLabelEntitySlug inside every managesEntity and managesEarnEntity check. Build the lookup once from entities, then use it in the managers.some callbacks so the computed filters no longer repeatedly scan Object.entries. Keep the changes localized around getEulerLabelEntitySlug, managesEntity, and managesEarnEntity.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@components/entities/manager/ManagerEntityLink.vue`:
- Around line 59-67: The clickable `span` in `ManagerEntityLink.vue` is
mouse-only and needs keyboard support. Update the `spanLink && isLinked` branch
on the `<span>` used for `goToManager` to be accessible by adding link semantics
and keyboard activation, such as `role="link"`, `tabindex="0"`, and a keydown
handler for Enter/Space, while keeping the existing click behavior and avoiding
nested anchors.
In `@components/entities/vault/VaultItem.vue`:
- Around line 301-308: The manager-profile link is using the click-only span
branch in ManagerEntityLink, so it is not keyboard accessible from the vault
cards. Update the shared span-link path in ManagerEntityLink so it renders a
tabbable, keyboard-activatable control with proper link semantics, and make the
VaultItem usage continue through that fixed path rather than relying on the
non-accessible span behavior.
---
Nitpick comments:
In `@composables/useEulerManagerProfile.ts`:
- Around line 35-61: The filtering in useEulerManagerProfile.ts repeatedly calls
getEulerLabelEntitySlug for every manager, causing nested O(n) scans over
entities during evaults, securitizeVaults, and earnVaults recomputation.
Precompute a reverse entity-to-slug lookup once per recompute in the same
composable, then have managesEntity and managesEarnEntity read from that map
instead of calling getEulerLabelEntitySlug repeatedly. Keep the existing
computed lists and filter/sort flow, but make the slug resolution constant-time
by keying off the same entities source used by getEulerLabelEntitySlug.
- Around line 35-43: Cache the repeated entity slug resolution in
useEulerManagerProfile by introducing a reverse lookup from entity id to slug
instead of calling getEulerLabelEntitySlug inside every managesEntity and
managesEarnEntity check. Build the lookup once from entities, then use it in the
managers.some callbacks so the computed filters no longer repeatedly scan
Object.entries. Keep the changes localized around getEulerLabelEntitySlug,
managesEntity, and managesEarnEntity.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2f674161-5228-4d81-a9d8-4e6637ca87c5
📒 Files selected for processing (12)
components/entities/manager/ManagerEntityLink.vuecomponents/entities/vault/SecuritizeVaultItem.vuecomponents/entities/vault/VaultBorrowItem.vuecomponents/entities/vault/VaultEarnItem.vuecomponents/entities/vault/VaultItem.vuecomponents/entities/vault/overview/SecuritizeVaultOverview.vuecomponents/entities/vault/overview/VaultOverviewBlockGeneral.vuecomponents/entities/vault/overview/earn/VaultOverviewEarnBlockGeneral.vuecomposables/useEulerManagerProfile.tspages/managers/[slug].vuetests/utils/manager-profile.test.tsutils/manager-profile.ts
| <span | ||
| v-if="spanLink && isLinked" | ||
| :class="textClass" | ||
| :data-id="dataKey && dataField ? 'data-point' : undefined" | ||
| :data-key="dataKey || undefined" | ||
| :data-field="dataField || undefined" | ||
| :data-value="displayName" | ||
| @click.stop.prevent="goToManager" | ||
| >{{ displayName }}</span> |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Clickable span is not keyboard accessible.
In the spanLink && isLinked branch the navigation lives on a <span> with only a mouse @click handler, so keyboard users can't focus or activate it. Since this branch exists to avoid nested anchors inside link rows, consider adding role="link", tabindex="0", and a keydown handler (Enter/Space).
♿ Suggested accessibility attributes
<span
v-if="spanLink && isLinked"
:class="textClass"
+ role="link"
+ tabindex="0"
:data-id="dataKey && dataField ? 'data-point' : undefined"
:data-key="dataKey || undefined"
:data-field="dataField || undefined"
:data-value="displayName"
`@click.stop.prevent`="goToManager"
+ `@keydown.enter.stop.prevent`="goToManager"
+ `@keydown.space.stop.prevent`="goToManager"
>{{ displayName }}</span>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <span | |
| v-if="spanLink && isLinked" | |
| :class="textClass" | |
| :data-id="dataKey && dataField ? 'data-point' : undefined" | |
| :data-key="dataKey || undefined" | |
| :data-field="dataField || undefined" | |
| :data-value="displayName" | |
| @click.stop.prevent="goToManager" | |
| >{{ displayName }}</span> | |
| <span | |
| v-if="spanLink && isLinked" | |
| :class="textClass" | |
| role="link" | |
| tabindex="0" | |
| :data-id="dataKey && dataField ? 'data-point' : undefined" | |
| :data-key="dataKey || undefined" | |
| :data-field="dataField || undefined" | |
| :data-value="displayName" | |
| `@click.stop.prevent`="goToManager" | |
| `@keydown.enter.stop.prevent`="goToManager" | |
| `@keydown.space.stop.prevent`="goToManager" | |
| >{{ displayName }}</span> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@components/entities/manager/ManagerEntityLink.vue` around lines 59 - 67, The
clickable `span` in `ManagerEntityLink.vue` is mouse-only and needs keyboard
support. Update the `spanLink && isLinked` branch on the `<span>` used for
`goToManager` to be accessible by adding link semantics and keyboard activation,
such as `role="link"`, `tabindex="0"`, and a keydown handler for Enter/Space,
while keeping the existing click behavior and avoiding nested anchors.
| <ManagerEntityLink | ||
| :entities="entities" | ||
| :label="entityName" | ||
| :src="entityLogos" | ||
| /> | ||
| <span | ||
| class="text-p2 text-content-primary truncate" | ||
| data-id="data-point" | ||
| span-link | ||
| text-class="text-p2 text-content-primary hover:text-accent-600 underline transition-colors truncate" | ||
| :data-key="vault.address.toLowerCase()" | ||
| data-field="risk-manager" | ||
| :data-value="entityName" | ||
| >{{ entityName }}</span> | ||
| /> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Make the manager-profile affordance keyboard accessible.
Using span-link here routes through ManagerEntityLink’s click-only <span> branch, so the new profile destination is not tabbable or activatable from the keyboard inside these vault cards. Please fix the shared span-link path before rolling this pattern out across the other list items in this PR.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@components/entities/vault/VaultItem.vue` around lines 301 - 308, The
manager-profile link is using the click-only span branch in ManagerEntityLink,
so it is not keyboard accessible from the vault cards. Update the shared
span-link path in ManagerEntityLink so it renders a tabbable,
keyboard-activatable control with proper link semantics, and make the VaultItem
usage continue through that fixed path rather than relying on the non-accessible
span behavior.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Reviewed current head 1138f42baffd32f7f6d04e479131efc869a2e887.
Verdict: COMMENT — one non-blocking accessibility/UX suggestion inline; no correctness or security blocker found.
Scope reviewed:
- New
/managers/[slug]page anduseEulerManagerProfiledata path. - Shared
ManagerEntityLinkand profile helper utilities. - Refactor of curator/risk-manager display across vault cards and overview blocks.
- Active bot feedback: CodeRabbit had a walkthrough/pre-merge summary only; no material inline findings to verify.
Validation performed:
git diff --check origin/development...HEADnpm run test:run -- tests/utils/manager-profile.test.tsnpx eslint components/entities/manager/ManagerEntityLink.vue composables/useEulerManagerProfile.ts pages/managers/[slug].vue utils/manager-profile.ts tests/utils/manager-profile.test.tsnpm run typechecknpm run build- Headed Chromium/Xvfb browser smoke on a local production build:
- Desktop
/managers/k3?network=ethereum: rendered manager identity, social links, product cards, and managed vault list. - Mobile
/managers/k3?network=ethereum: same content rendered in the narrow viewport. /managers/not-a-real-manager?network=ethereum: rendered the not-found state.
- Desktop
Smoke coverage: browser visual smoke + mobile smoke; no wallet/signing coverage, as this PR is read-only navigation/profile UI.
Screenshots: captured during local smoke, but not attached here because the available GitHub CLI path in this environment does not support binary PNG upload. No sensitive content was captured.
Scalability / maintainability hygiene pass:
- Good direction overall: the repeated avatar/name rendering was centralized in
ManagerEntityLink, and helper logic has focused utility tests. - Sibling surfaces checked: lend/borrow/earn cards, Securitize cards, and vault overview blocks now use the shared component where this PR touches manager display. Explore/list filters remain name-based filters and are out of scope for profile navigation.
- Remaining refinement is the
spanLinkaccessibility point inline; because most card call sites need to avoid nested anchors, the shared component is the right place to make that behavior reusable and keyboard-accessible.
| :class="avatarClass" | ||
| :label="displayName" | ||
| :src="entityLogos" | ||
| /> |
There was a problem hiding this comment.
💡 Suggestion: spanLink makes the manager destination mouse-clickable, but it renders as a plain <span> with no href, role="link", tabindex, or keyboard handler. Most of the new vault-card call sites use this mode to avoid nested anchors, so keyboard and screen-reader users do not get the same navigation affordance as mouse users. Consider making the span mode an accessible link-like control (for example role="link", tabindex="0", and Enter/Space handling) or otherwise restructuring the card/link relationship so the shared component stays accessible everywhere.
|
🚅 Deployed to the euler-lite-pr-618 environment in euler-lite
|
Add keyboard semantics to the span-based manager profile affordance used inside vault cards.
Normalize manager profile links and surface labeled governance addresses plus product metadata from labels.
Align manager profiles with the review notes by removing governance addresses and individual lending vault lists, using market cards, and keeping flexible profile links.
Drop the low-value links stat card now that profile links render directly below the summary.
Remove the extra manager-profile label and place the back button with the manager identity header.
Summary
Changes
Test plan
Summary by CodeRabbit
New Features
Bug Fixes
Tests