Skip to content

fix(a11y): EntityRow and MetricCard onClick — add role=button, tabIndex, onKeyDown (QUA-169)#1523

Closed
hungdqdesign wants to merge 89 commits intopaperclipai:masterfrom
hungdqdesign:fix/entity-row-metric-card-a11y-qua-169
Closed

fix(a11y): EntityRow and MetricCard onClick — add role=button, tabIndex, onKeyDown (QUA-169)#1523
hungdqdesign wants to merge 89 commits intopaperclipai:masterfrom
hungdqdesign:fix/entity-row-metric-card-a11y-qua-169

Conversation

@hungdqdesign
Copy link
Copy Markdown

Summary

Fixes keyboard accessibility for two widely-used reusable components:

EntityRow (click-only mode, no to prop):

  • Add role="button" + tabIndex={0} + onKeyDown (Enter/Space)

MetricCard (onClick variant):

  • Add role="button" + tabIndex={0} + onKeyDown (Enter/Space)

Related Issue

QUA-169: [A11Y] EntityRow and MetricCard onClick variants not keyboard-accessible

Acceptance Criteria

  • EntityRow with onClick is keyboard-navigable
  • MetricCard with onClick is keyboard-navigable
  • Enter/Space trigger click action
  • No regression for mouse/touch users
  • WCAG 2.1 AA compliant

Impact

These are reusable components used across many pages — fix propagates broadly.

Test plan

  • Tab to EntityRow → focus visible
  • Press Enter/Space on EntityRow → action triggered
  • Tab to MetricCard → focus visible
  • Press Enter/Space on MetricCard → action triggered
  • Mouse click still works normally on both

🤖 PM-coordinated PR (QUA-169)

hungdqdesign and others added 30 commits March 21, 2026 00:24
… and add missing models (#1357)

Cursor CLI now rejects "auto" as a model selection with "Cannot use this
model: auto". Change the default to "composer-2" and add "composer-2" +
"composer-2-fast" to the fallback model list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…awbot.vn

Add allowedHosts: "all" to vite server config so that requests from
custom domain behind Cloudflare are not blocked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Break the monolithic AgentDetail page into focused, maintainable modules:
- AgentDetail.tsx: slim orchestrator (593 LOC, down from 3988)
- agent-detail/OverviewTab.tsx: dashboard with charts, issues, costs
- agent-detail/InstructionsTab.tsx: instructions bundle editor
- agent-detail/ConfigurationTab.tsx: agent config form + permissions + keys
- agent-detail/SkillsTab.tsx: skill management
- agent-detail/RunsTab.tsx: run list + run detail (lazy loaded via React.lazy)
- agent-detail/LogViewer.tsx: live transcript/log viewer
- agent-detail/KeysTab.tsx: API key management
- agent-detail/WorkspaceOperations.tsx: workspace operation UI
- agent-detail/utils.ts: shared utilities and types

RunsTab is lazy-loaded for better initial page performance.
No functional changes — pure extraction refactor.

QUA-123

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…calls

When /agents/:id/wakeup is called directly (not via the checkout route),
the contextSnapshot lacks issueId/projectId/workspaceId, causing the run
to fall back to agent_home instead of the project workspace.

Now enqueueWakeup auto-detects the agent's in-progress checked-out issue
and enriches the context with issueId, projectId, and projectWorkspaceId.
Also persists resolved projectId to contextSnapshot when only issueId was
provided.

Fixes #1387

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… locks (QUA-12)

release() now clears executionRunId, executionAgentNameKey, and
executionLockedAt alongside checkoutRunId. Previously these fields
persisted after release, causing permanent stale locks that blocked
re-checkout by other agents.

Adds unit tests verifying all execution fields are nulled on release.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nsert (#QUA-91)

Gemini adapter output sometimes contains null bytes (0x00) which PostgreSQL
rejects in TEXT and JSONB columns. Add stripNullBytes() sanitization at the
DB write layer (setRunStatus + appendRunEvent) to protect against any adapter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On Windows with WIN1252 system locale, child process stdout/stderr
default to the system encoding, causing crashes when adapter output
contains Unicode characters. Add setEncoding("utf8") on streams
immediately after spawn, matching the pattern used in codex-local.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…#1465)

Users running adapters like codex_local with non-standard models (e.g.
grok-4.20-beta) were blocked by the hardcoded model dropdown. Now:

- ModelDropdown shows a "Use <custom>" option when search doesn't match
  any known model
- InlineEntitySelector gains allowCustomValue prop for the same behavior
- NewIssueDialog model override selector enables custom values
- Custom model values display correctly in trigger buttons

Closes #1465

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nsert (#QUA-91)

Gemini adapter output sometimes contains null bytes (0x00) which PostgreSQL
rejects in TEXT and JSONB columns. Add stripNullBytes() sanitization at the
DB write layer (setRunStatus + appendRunEvent) to protect against any adapter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On Windows with WIN1252 system locale, child process stdout/stderr
default to the system encoding, causing crashes when adapter output
contains Unicode characters. Add setEncoding("utf8") on streams
immediately after spawn, matching the pattern used in codex-local.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… and add missing models (#1357)

Cursor CLI now rejects "auto" as a model selection with "Cannot use this
model: auto". Change the default to "composer-2" and add "composer-2" +
"composer-2-fast" to the fallback model list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…awbot.vn

Add allowedHosts: "all" to vite server config so that requests from
custom domain behind Cloudflare are not blocked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cancelActiveForAgentInternal now matches cancelRunInternal's escalation
pattern: SIGTERM → grace period → SIGKILL. The runningProcesses entry
is deferred until after the grace window to prevent orphaned processes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…1461)

The codex adapter's getQuotaWindows spawns the codex CLI in its class
constructor. If codex is not installed, spawn emits ENOENT which can
crash the server when the Costs → Providers page is loaded.

Wrap each adapter.getQuotaWindows() call in try-catch to handle both
synchronous throws and async rejections gracefully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s equivalents

- packages/db: replaced `cp -r` with `fs.cpSync(..., {recursive: true})`
- cli: replaced `chmod +x` with a Node.js platform check that only
  runs chmodSync on darwin/linux, skipping Windows entirely

Closes #1462
Closes #1463

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…#1165)

enqueueWakeup can throw (budget blocked, agent state conflict, etc).
Without a try-catch inside the tickTimers loop, one failing agent
aborts the entire tick — silently stopping all scheduled heartbeats.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… local_trusted mode

When a bearer token is present but fails validation (expired JWT, invalid key),
the default local_trusted board actor was not cleared, allowing unauthenticated
requests to inherit full board-level access. This enabled agents with expired
auth to perform destructive operations like deleting other agents.

Now clears the actor to { type: "none" } when a bearer token is present before
validation, so only successful verification restores the proper actor type.

Fixes #1314

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jwtConfig() only read PAPERCLIP_AGENT_JWT_SECRET, but server startup
(index.ts) accepts BETTER_AUTH_SECRET as a fallback. When only
BETTER_AUTH_SECRET is set (common in local dev), all agent runs failed
to get PAPERCLIP_API_KEY injected. Align the fallback chain so local
agents authenticate correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…th EPERM

On Windows without Developer Mode, symlink creation fails with EPERM.
The new symlinkOrCopy helper catches EPERM and falls back to
fs.cp(source, target, {recursive: true}), allowing skills to be
installed without requiring elevated privileges.

Closes #1464

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
)

On Windows without Developer Mode, symlink creation fails with EPERM.
Add a three-tier fallback: symlink → junction → recursive copy.
This ensures skills installation works for all Windows users without
requiring elevated permissions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hungdqdesign and others added 17 commits March 22, 2026 07:40
- Filter tabs: All | Active | Planned | Achieved
- Default filter: active (most useful view)
- Persist preference to localStorage key goals:statusFilter
- Empty state when filtered results = 0
- Pattern matches Routines page filter bar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nt Tasks (QUA-162)

Section headers for Recent Activity and Recent Tasks lacked navigation links,
creating dead-ends for users who want to see the full list. Added subtle
"View all →" links pointing to /activity and /issues respectively.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
assertAdapterConfigConstraints now checks that the configured model
exists in the adapter's known model list for all adapter types, not
just opencode_local. Returns a clear 422 error with available models
when a mismatch is detected.

Also expanded the PATCH handler guard to call validation for all
adapter types, preventing silent misconfiguration that causes agents
to fail at runtime.

Closes #1388

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
buildWakeText hardcoded ~/.openclaw/workspace/ as the claimed API key
location. When an agent has a different workspace (e.g. workspace-nora),
the path was wrong and the agent couldn't find its token.

Now accepts an optional workspacePath from agent config or paperclip
workspace context, falling back to the original default only when
neither is available.

Closes #1371

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts:
#	server/src/__tests__/heartbeat-context-content-trust.test.ts
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 22, 2026

Greptile Summary

This PR adds keyboard accessibility (role="button", tabIndex={0}, onKeyDown Enter/Space) to the onClick-only variants of EntityRow and MetricCard — two widely-used reusable components. The direction is correct and the ARIA pattern is broadly sound, but there are two substantive issues with the onKeyDown implementation and a consistency gap with the design system's focus-ring style.

Key findings:

  • Event-bubbling in onKeyDown (both components): Neither handler guards against bubbled events (e.target === e.currentTarget). If a focusable child element (e.g. a <button> or <a> in the trailing prop of EntityRow) is focused and the user presses Space, e.preventDefault() fires before the child's keyup-triggered click, hijacking the action and calling the outer onClick instead. See inline comments on EntityRow.tsx:70 and MetricCard.tsx:51.
  • Missing design-system focus ring (both components): The project's interactive elements (see button.tsx) use outline-none + focus-visible:ring-[3px] to render a consistent focus ring. These new role="button" divs fall back to the browser default outline, which is visually inconsistent and may differ across environments. See inline comments on EntityRow.tsx:65 and MetricCard.tsx:46.
  • PR description is missing a "thinking path": Per CONTRIBUTING.md, PR descriptions should include a top-down "thinking path" explaining what was changed, why it matters, benefits, and risks. Please add this section.
  • No before/after screenshots: CONTRIBUTING.md asks for screenshots when there is a visible change. Focus-ring behaviour is a visible UI change — please include before/after screenshots (e.g. showing the focused state of an EntityRow with and without the fix).

Confidence Score: 3/5

  • Safe to merge for mouse/touch users, but the keyboard fix has an event-bubbling gap that could misbehave when focusable children are present inside the components.
  • The two changed UI files are straightforward and introduce no regressions for existing mouse/touch behaviour. However, both onKeyDown handlers lack a target === currentTarget guard, meaning Space/Enter keypresses on focusable children will incorrectly bubble up and trigger the outer onClick while also preventing the child's own default action. The missing focus-visible ring is an inconsistency but not a blocker. The PR description also lacks the required thinking path and screenshots per CONTRIBUTING.md.
  • ui/src/components/EntityRow.tsx and ui/src/components/MetricCard.tsx — specifically the onKeyDown handlers on the role="button" divs.

Important Files Changed

Filename Overview
ui/src/components/EntityRow.tsx Adds role="button", tabIndex={0}, and onKeyDown handler to the onClick-only (no to prop) render path. The accessibility intent is correct, but there are two concerns: (1) the onKeyDown handler fires on bubbled events from focusable children in trailing, which can steal Space/Enter from inner buttons; (2) no explicit focus-visible ring class is added, leaving the focus indicator relying on browser defaults rather than the project's design-system ring style.
ui/src/components/MetricCard.tsx Adds role="button", tabIndex={0}, and onKeyDown (Enter/Space) to the onClick-only render path. Logic is sound. Minor concern: no explicit focus-visible ring class, inconsistent with the design system's button focus pattern.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: ui/src/components/EntityRow.tsx
Line: 70

Comment:
**`onKeyDown` fires on events bubbled from focusable children**

The handler doesn't verify that the event originated on the root `<div>` itself. If `trailing` contains a focusable child element — such as an `<a>`, a `<button>`, or another `role="button"` node — and the user presses Space while focused on that child:

1. The keydown event bubbles up to this div.
2. The handler calls `e.preventDefault()`, which **suppresses the child button's subsequent `keyup`-triggered click** (browsers fire button clicks on Space `keyup`, and `preventDefault` on `keydown` cancels it).
3. The outer `onClick` fires instead of the intended inner action.

Add a target guard to restrict the handler to self-focus only. Replace the handler expression with one that checks `e.target === e.currentTarget` before acting.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: ui/src/components/MetricCard.tsx
Line: 51

Comment:
**`onKeyDown` fires on events bubbled from child elements**

Same event-bubbling issue as in `EntityRow`: if any child inside `inner` becomes focusable (e.g. an icon wrapped in a link), a Space or Enter keydown bubbles up here. `e.preventDefault()` is called before the child's `keyup` click fires, hijacking the interaction and triggering the outer `onClick` instead.

Add a `e.target === e.currentTarget` check before the key guard to scope the handler strictly to the card's own focus.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: ui/src/components/EntityRow.tsx
Line: 65-74

Comment:
**Missing focus-visible ring — inconsistent with design system**

All other interactive elements in this project (see `ui/src/components/ui/button.tsx`) pair `outline-none` with an explicit `focus-visible:ring-[3px]` class so the focus indicator matches the design system. Without it, this `<div>` falls back to the browser's default outline, which is visually inconsistent and can appear differently (or be suppressed) across browsers.

Consider adding the same `focus-visible:outline-none focus-visible:ring-[3px]` classes used by `<Button>` — conditioned on `isClickable` — alongside the `classes` variable.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: ui/src/components/MetricCard.tsx
Line: 46-55

Comment:
**Missing focus-visible ring — inconsistent with design system**

Like the `EntityRow` change, this wrapper div will show the raw browser outline on focus rather than the project's design-system ring style (see `ui/src/components/ui/button.tsx` for the pattern). For a PR claiming WCAG 2.1 AA compliance, having a non-standard, browser-default focus ring is worth addressing to ensure consistent, predictable visual feedback across the UI.

Add `focus-visible:outline-none focus-visible:ring-[3px]` (plus an appropriate `rounded-lg` so the ring follows the card shape) to the wrapper `className`.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "fix(a11y): add role=..."

onClick={onClick}
role={isClickable ? "button" : undefined}
tabIndex={isClickable ? 0 : undefined}
onKeyDown={isClickable ? (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick?.(); } } : undefined}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 onKeyDown fires on events bubbled from focusable children

The handler doesn't verify that the event originated on the root <div> itself. If trailing contains a focusable child element — such as an <a>, a <button>, or another role="button" node — and the user presses Space while focused on that child:

  1. The keydown event bubbles up to this div.
  2. The handler calls e.preventDefault(), which suppresses the child button's subsequent keyup-triggered click (browsers fire button clicks on Space keyup, and preventDefault on keydown cancels it).
  3. The outer onClick fires instead of the intended inner action.

Add a target guard to restrict the handler to self-focus only. Replace the handler expression with one that checks e.target === e.currentTarget before acting.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/components/EntityRow.tsx
Line: 70

Comment:
**`onKeyDown` fires on events bubbled from focusable children**

The handler doesn't verify that the event originated on the root `<div>` itself. If `trailing` contains a focusable child element — such as an `<a>`, a `<button>`, or another `role="button"` node — and the user presses Space while focused on that child:

1. The keydown event bubbles up to this div.
2. The handler calls `e.preventDefault()`, which **suppresses the child button's subsequent `keyup`-triggered click** (browsers fire button clicks on Space `keyup`, and `preventDefault` on `keydown` cancels it).
3. The outer `onClick` fires instead of the intended inner action.

Add a target guard to restrict the handler to self-focus only. Replace the handler expression with one that checks `e.target === e.currentTarget` before acting.

How can I resolve this? If you propose a fix, please make it concise.

role="button"
tabIndex={0}
onClick={onClick}
onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick(); } }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 onKeyDown fires on events bubbled from child elements

Same event-bubbling issue as in EntityRow: if any child inside inner becomes focusable (e.g. an icon wrapped in a link), a Space or Enter keydown bubbles up here. e.preventDefault() is called before the child's keyup click fires, hijacking the interaction and triggering the outer onClick instead.

Add a e.target === e.currentTarget check before the key guard to scope the handler strictly to the card's own focus.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/components/MetricCard.tsx
Line: 51

Comment:
**`onKeyDown` fires on events bubbled from child elements**

Same event-bubbling issue as in `EntityRow`: if any child inside `inner` becomes focusable (e.g. an icon wrapped in a link), a Space or Enter keydown bubbles up here. `e.preventDefault()` is called before the child's `keyup` click fires, hijacking the interaction and triggering the outer `onClick` instead.

Add a `e.target === e.currentTarget` check before the key guard to scope the handler strictly to the card's own focus.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +65 to 74
<div
className={classes}
onClick={onClick}
role={isClickable ? "button" : undefined}
tabIndex={isClickable ? 0 : undefined}
onKeyDown={isClickable ? (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick?.(); } } : undefined}
>
{content}
</div>
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing focus-visible ring — inconsistent with design system

All other interactive elements in this project (see ui/src/components/ui/button.tsx) pair outline-none with an explicit focus-visible:ring-[3px] class so the focus indicator matches the design system. Without it, this <div> falls back to the browser's default outline, which is visually inconsistent and can appear differently (or be suppressed) across browsers.

Consider adding the same focus-visible:outline-none focus-visible:ring-[3px] classes used by <Button> — conditioned on isClickable — alongside the classes variable.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/components/EntityRow.tsx
Line: 65-74

Comment:
**Missing focus-visible ring — inconsistent with design system**

All other interactive elements in this project (see `ui/src/components/ui/button.tsx`) pair `outline-none` with an explicit `focus-visible:ring-[3px]` class so the focus indicator matches the design system. Without it, this `<div>` falls back to the browser's default outline, which is visually inconsistent and can appear differently (or be suppressed) across browsers.

Consider adding the same `focus-visible:outline-none focus-visible:ring-[3px]` classes used by `<Button>` — conditioned on `isClickable` — alongside the `classes` variable.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +46 to 55
<div
className="h-full"
role="button"
tabIndex={0}
onClick={onClick}
onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick(); } }}
>
{inner}
</div>
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing focus-visible ring — inconsistent with design system

Like the EntityRow change, this wrapper div will show the raw browser outline on focus rather than the project's design-system ring style (see ui/src/components/ui/button.tsx for the pattern). For a PR claiming WCAG 2.1 AA compliance, having a non-standard, browser-default focus ring is worth addressing to ensure consistent, predictable visual feedback across the UI.

Add focus-visible:outline-none focus-visible:ring-[3px] (plus an appropriate rounded-lg so the ring follows the card shape) to the wrapper className.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/components/MetricCard.tsx
Line: 46-55

Comment:
**Missing focus-visible ring — inconsistent with design system**

Like the `EntityRow` change, this wrapper div will show the raw browser outline on focus rather than the project's design-system ring style (see `ui/src/components/ui/button.tsx` for the pattern). For a PR claiming WCAG 2.1 AA compliance, having a non-standard, browser-default focus ring is worth addressing to ensure consistent, predictable visual feedback across the UI.

Add `focus-visible:outline-none focus-visible:ring-[3px]` (plus an appropriate `rounded-lg` so the ring follows the card shape) to the wrapper `className`.

How can I resolve this? If you propose a fix, please make it concise.

hungdqdesign and others added 7 commits March 22, 2026 09:44
…-tabs

refactor(ui): split AgentDetail.tsx into tab-based modules
fix(ui): allow custom model input for adapters
A queued heartbeat run that never started (startedAt IS NULL) is now
treated as stale in isTerminalOrMissingHeartbeatRun(), allowing checkout
to supersede its executionRunId lock. Also added a final fallback in
checkout() that clears stale executionRunId locks regardless of issue
status, preventing permanent 409 conflicts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… (QUA-165)

- aria-label={expanded ? "Collapse" : "Expand"} for screen reader context
- aria-expanded={expanded} to announce state changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e (QUA-166, QUA-167)

- Projects page: add status filter bar (All / Backlog / Planned / In Progress / Completed)
  with count badges and localStorage persistence (key: projects:statusFilter)
- ApprovalCard: show Loader2 spinner + "Approving..."/"Rejecting..." label while
  mutation is pending, so users get clear feedback on action progress

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@hungdqdesign hungdqdesign force-pushed the fix/entity-row-metric-card-a11y-qua-169 branch from a6b1005 to d9008cf Compare March 22, 2026 03:52
@hungdqdesign hungdqdesign closed this by deleting the head repository Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant