lxbme opened a new pull request, #3462:
URL: https://github.com/apache/apisix-dashboard/pull/3462
Please answer these questions before submitting a pull request, **or your PR
will get closed**.
**Why submit this pull request?**
- [ ] Bugfix
- [x] New feature provided
- [ ] Improve performance
- [ ] Backport patches
**What changes will this PR take into?**
Choosing a plugin meant picking from a grid of bare names —
`ai-aws-content-moderation`, `graphql-proxy-cache`, `workflow`, `api-breaker` —
with no description and nothing to click. Once a plugin was open, the drawer
showed its name and the editor was handed that plugin's JSON schema, so there
was validation and completion, but nothing anywhere said what the plugin was
*for*, and nothing linked out. A user who did not already know the plugin had
to leave the dashboard and search for it.
Each plugin now carries a link to its documentation: an icon on the plugin
card, and an icon with a label in the editor drawer's title row.
### Why a link rather than a description
The gateway cannot supply the text. Of the plugins returned by `GET
/apisix/admin/plugins?all=true` on APISIX 3.17.0, **none carries a
`schema.description`**. Bundling a name-to-description table in the dashboard
would mean 107 entries times five locales, maintained against a plugin list
that changes every gateway release — and a stale description is worse than
none. The docs site is the only available source, and its URL is derivable from
the plugin name.
### The URL is derived, and the exceptions are enumerated
`src/utils/pluginDocs.ts` maps a plugin name and the UI language to a URL or
to `null`. Coverage was measured against the live docs site across every plugin
name the gateway reports in both subsystems (106 http plus `mqtt-proxy` from
stream):
| Result | Count |
|---|---|
| Resolves on the released docs | 100 / 107 |
| Documented under a different name | 2 (`serverless-pre-function`,
`serverless-post-function` share `/plugins/serverless/`) |
| No page at all | 2 (`example-plugin` is the gateway's sample; `ai` has no
page of its own) |
| Newer than the current docs release | 3 (`ai-cache`, `ai-lakera-guard`,
`mcp-bridge` — they resolve only under `/next/`) |
The two `serverless-*` names get a slug override. The other five render **no
link at all**: a dashboard that is the first thing many people see of APISIX
should not hand out broken links, and a missing affordance is a smaller failure
than one that lies.
The three unreleased plugins deliberately do not link `/next/`. That would
resolve today, but it points users at documentation for a version they are not
running, and those entries would expire silently once the released docs catch
up. Their absence is self-correcting; a stale `/next/` pointer is not.
### Following the UI language
The link resolves to `/zh/docs/...` when the dashboard is in Chinese and to
the English docs otherwise. Coverage was measured separately for Chinese and is
identical — 100 of 107, and **the same seven names fail in both locales,
character for character** — so following the language introduces no failure
mode that English does not already have. The docs site publishes English and
Chinese only; `/es/`, `/de/` and `/tr/` are 404, so those three fall back to
English rather than producing a URL that does not exist.
The comparison is exact (`language === 'zh'`), not a prefix match:
`src/config/i18n.ts` derives `supportedLngs` from the resource keys, so the
only possible values are the five bare codes with no regional variants. This
matches how `antdConfigProvider` already indexes its locale table.
### Why the control is an anchor
`PluginDocsLink` renders a Mantine `Anchor`, i.e. a real `<a href
target="_blank" rel="noopener noreferrer">`, following the pattern
`Header/index.tsx` already uses for the docs button. The repo's `RouteLinkBtn`
is a Mantine `Button` carrying `href`; middle-click, ⌘-click and "copy link
address" are exactly what someone reaching for documentation does, and none of
them work on a `<button>`. `RouteLinkBtn`'s own call sites are deliberately
untouched.
The e2e assertions use `getByRole('link', …)`, which fails if the control
ever regresses to a button.
### Two call sites, six surfaces
`PluginCard` and `PluginEditorDrawer` are both shared: the card renders in
the select-plugins picker, in the list of already-selected plugins, and on the
Plugin Metadata page; the drawer is used by the plugins form field and by
Plugin Metadata. Two edits therefore cover every place a plugin is chosen or
configured.
The link is unconditional on drawer mode — it shows in `add`, `edit` and
`view` alike. What a plugin does is the same question whether you are choosing
it, configuring it, or reading someone else's configuration, and `view` is what
a read-only operator sees.
On the card the link is icon-only, with an `aria-label` naming the plugin,
so a screen reader can tell which of a hundred identical icons it has landed
on. In the drawer the label is visible and **no** `aria-label` is set:
overriding a visible label with text that does not contain it would break WCAG
2.5.3 Label in Name. The drawer's label reuses the existing top-level `docs`
key rather than introducing a second key meaning the same thing.
One new string, `form.plugins.docsFor`, in all five locales. It is
interpolated with `escapeValue: false`, prophylactically — #3459 shipped an
accessible name reading `R&D` before that was caught.
**Related issues**
Closes #3461
**Checklist:**
- [x] Did you explain what problem does this PR solve? Or what new features
have been added?
- [x] Have you added corresponding test cases?
- [ ] Have you modified the corresponding document?
- [x] Is this PR backward compatible? If it is not backward compatible,
please discuss on the mailing list first
Tests:
- `src/utils/pluginDocs.test.ts` — 13 cases: a plain name; both
`serverless-*` collapsing to `serverless`; each of the five undocumented names
returning `null`; the `/zh` prefix; `es`/`de`/`tr` falling back to English
rather than emitting a `/es/` URL that does not exist; and the zh prefix
combined with a slug override, which is the interaction the individual cases
miss.
- `e2e/tests/regression/plugin.docs-link.spec.ts` — five tests: the drawer
link carries the exact expected `href` and `target="_blank"`; a plugin with no
documentation page (`example-plugin`) exposes **no** link, which is the
assertion that fails if the exception table is dropped; the same link's `href`
gains `/zh/` after switching the UI to Chinese; a picker card exposes a link
whose accessible name is `key-auth documentation`, which is the only coverage
of the component's icon-only branch; and an undocumented plugin's card exposes
no link.
The card sits inside a `Combobox.Option`, so whether a nested anchor's click
survives Mantine's option handling was checked by hand in a real browser rather
than inferred: clicking the icon opens a new tab on the plugin's documentation
page and leaves the picker open and unchanged. No `stopPropagation` was needed,
so none was added.
Verified: `pnpm test` (122 passed), `pnpm lint`, `pnpm exec tsc -b`, and
both a `--mode test` and a production `pnpm build`, all clean. The new spec
passes 5/5 in isolation.
A full Playwright run on this machine is not currently a usable signal, and
the reason is worth stating rather than hiding behind a pass rate. The suite's
own `bulk-1000` spec drives etcd into multi-second stalls — its logs show
51-second raft reads on the health-probe key — after which unrelated specs fail
with `has no healthy etcd endpoint available`. Separately, this machine cannot
run the Monaco-backed specs headless at all. Both were confirmed to be
independent of this change by checking out `master` (`89fc2ed1`), rebuilding,
and re-running the failures: every one of the eight specs sampled that way
fails identically on `master`, and the specs that recovered once etcd was
healthy — including this PR's own — recovered on both trees.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]