PROD-10021#4974
Conversation
…ge Base across Settings and Integrations Introduce a shared admin-UI layer (src/js/admin/common) exposed as @bb/admin-common (window.bbAdminCommon) through a single bb-admin-common script handle and bb-admin-common-style stylesheet, so the global admin header and the Knowledge Base modal ship once and are reused by every admin React app instead of being duplicated per bundle. - BBAdminHeader: shared global header (BuddyBoss logo, "Search for settings" search, Mothership IPN bell relocation, help/KB icon), driven by props (onSearch / onSelectResult / ipnRootId / onHelp). - Move the Knowledge Base modal subsystem (KnowledgeBaseModal, KbContext, kbApi/kbCache/sanitizeKbArticle, sub-components) into the shared layer. kbApi/modal now read apiUrl + nonce from whichever app global is present (bbAdminData || bbIntegrationsData). - Settings: render BBAdminHeader instead of the local Header.js (removed); move the 227-line fixed header CSS and the KB modal CSS out of admin.scss into the shared common.css so the header + KB styles are single-source. - Integrations marketplace page consumes the shared header + KB modal. The marketplace "Search integrations" field sits in the toolbar before the category dropdown; the global header search queries bb_admin_search_settings (capability-before-nonce) and deep-links into Settings. Exclude the Integrations screen from the legacy .bb-tab-header so the header is not rendered twice. - Webpack: replace the inherited DependencyExtractionWebpackPlugin to externalize @bb/admin-common in the settings/integrations bundles (no duplication) and add the `common` build target; register the handles in bb-admin-common-assets.php.
|
@claude |
|
Claude finished @jitendrabanjara1991's task in 4m 53s —— View job PR Review: PROD-10021 — Integration 2.0 + Shared Admin-Common Layer
SummaryThis PR introduces the Integrations marketplace admin page, a shared Critical / High1. Cross-bundle import of
|
…misc cleanups Follow-up fixes from the whole-branch review of the shared admin-common layer / Integrations marketplace. - Sanitizer: move sanitize.js into the shared layer (common/utils) and export sanitizeHtml/safeUrl/sanitizeCustomColumns from @bb/admin-common. IntegrationCard/IntegrationDrawer now import it from the shared external instead of reaching across the bundle boundary into settings/utils, so it ships once. Settings keeps a thin re-export shim at settings/utils/ sanitize.js so its ~40 existing importers are unchanged. - IntegrationDrawer: add proper modal focus management for role="dialog" aria-modal="true" — move focus into the panel on open, trap Tab inside it, and restore focus to the opener on close. - BBAdminHeader: key search-result rows by result.route (not array index) so React reconciliation is stable as results change. - Integrations App: wrap the header onSearch/onSelectResult handlers in useCallback so BBAdminHeader's search effect doesn't re-subscribe on every render. - IntegrationCard: drop the redundant onKeyDown handler (native <button> already activates onClick on Enter/Space). - KnowledgeBaseModal: remove the now-unused triggerRef prop and its dead focus-restore branch (no caller passes it post header-unification); the previously-focused-element fallback remains. - IntegrationGrid: add a visually-hidden aria-live="polite" "Loading integrations…" announcement and aria-hidden on the skeleton cards. - package.json: build the common target before settings/integrations in build:admin. - Fix the stale wp_localize_script comment in bb-admin-integrations-page.php to list all localized keys.
|
@claude |
|
Claude finished @jitendrabanjara1991's task in 4m 14s —— View job PR Review: PROD-10021 — Integration 2.0 + Shared Admin-Common Layer
SummaryThis PR introduces three related things: a shared Previously Reported — Now Fixed ✅
Medium1. Settings
|
…, vendor, tier, requires, screenshots) + review cleanups Client now reads the agreed (all-optional) API keys so the Integrations UI lights up automatically once buddyboss.com populates them; when a field is absent the UI falls back to today's behavior (no breakage). - Card: install_url → primary "Install" button; plugin_url → "Learn More" (falls back to link / link_url); both can show. vendor_name → subtitle; tier === 'pro' → PRO badge. - Drawer: vendor (name/url), Install/Learn More/Support actions, Requires/Recommended dependency rows (with FREE/PREMIUM tags), screenshots gallery. - integrationsApi.js requests all keys in the list + detail _fields. - Add docs/superpowers/specs/2026-06-25-integrations-api-field-contract.md (field names, types, JSON example) for the API team. Review cleanups (from the whole-branch review): - Settings App.js: wrap the header onSearch/onSelectResult in useCallback (stable identity, matching the Integrations app) so BBAdminHeader's search effect doesn't re-subscribe on every render. - kbApi.js: replace the hand-rolled decodeEntities with @wordpress/html- entities (canonical full named-entity coverage; externalized, not bundled). - Fix a "the the" typo; document that commonConfig intentionally omits withCommonExternal (it IS window.bbAdminCommon).
…into PROD-10021 * 'PROD-10021' of github.com:buddyboss/buddyboss-platform: PROD-10021 - Integration drawer UI and structure # Conflicts: # src/bp-core/admin/bb-settings/integrations/build/index.asset.php # src/bp-core/admin/bb-settings/integrations/build/index.js # src/bp-core/admin/bb-settings/integrations/build/styles/admin.css # src/js/admin/integrations/components/IntegrationDrawer.js
…uttons - Open the detail drawer only when the card title is clicked. The card body is no longer a single clickable button; the title is now a <button> with the native chrome reset and a hover affordance. - Rework the card action buttons to match Figma: - Lay the actions out space-between — Install on the left, Learn More on the right. - "Install" links to install_url when present; when absent it renders as a disabled, greyed button (#f7ae99 border / #f9bead label) so the layout stays consistent. - "Learn More ↗" is a borderless link (dark label + ArrowUpRight icon) that shows when there's no install_url, or alongside Install when the API provides a dedicated plugin_url. Destination falls back plugin_url → link → link_url.
The line under the plugin title is the integration's category, not a vendor name (the API has no vendor field; collection_name is just "Third-party"). - App.js: build a categoryMap (term ID → name) from the categories already fetched for the filter dropdown, and pass it to the grid. - IntegrationGrid: forward categoryMap to each card. - IntegrationCard: resolve integrations_category[0] → categoryMap[id] and render it as the subtitle (drops the unused vendor_name read). - SCSS: rename the subtitle rule card-vendor → card-category (same styles).
Align the card's internal layout to the Figma dev-mode spec (cardAddon): - Group the title + category into a heading block, mirroring Figma's Frame 115, so the 16px text gap separates the heading from the description rather than spacing the title and category apart. - Replicate the per-row padding instead of a flat gap: title row padding 1px 0 (Frame 116), category row padding 3px 0 (Frame 117) — giving a 4px title↔category gap, 16px+3px category↔description, and 16px+1px logo↔title. - Add min-height: 270px to the card (Figma cardAddon min height) so cards render at a uniform height.
|
@claude |
|
Claude finished @jitendrabanjara1991's task in 5m 3s —— View job PR Review: PROD-10021 — Integration 2.0 + Shared Admin-Common Layer
SummaryThis is a fresh, from-scratch review of the full diff. The PR introduces an Integrations marketplace admin page, a shared Previously Reported — Now Fixed ✅
Still Open From Review 21.
|
Pagination - Replace the "Previous / Page X of Y / Next" control with the Settings 2.0 numbered footer: item count + page buttons with ellipsis + prev/next arrows (bb-admin-pagination), matching the discussions/forums list screens. - Pagination.js rewritten (getPageNumbers inlined so the standalone bundle stays independent of the settings bundle); App.js tracks `total` (from x-wp-total) and renders the footer whenever the list is ready. - admin.scss: include the bb-admin-pagination mixin + a right-aligned __footer / __item-count; drop the old centered pagination styles. Review fixes - sanitize.js (shared): fix a protocol-relative URL bypass in isAllowedUrl — '//host/path' no longer short-circuits as a relative URL; it now falls through to the scheme allowlist. - App.js: wrap the drawer onClose/onSelect handlers in useCallback so the IntegrationDrawer Escape-key effect doesn't re-subscribe on every App render. - Drop the no-op unset($request) / unset($e) calls (PHPCS doesn't flag unused vars); $request gets a clarifying comment, the catch sets $ipn_root_id = ''.
|
@claude |
|
Claude finished @jitendrabanjara1991's task in 5m 28s —— View job PR Review: PROD-10021 — Integration 2.0 + Shared Admin-Common Layer
SummaryThis is a fresh, from-scratch review of the full diff (4th cycle). All 14 issues raised across three prior reviews are resolved except one. One new medium finding is identified. The PR is otherwise production-ready. Previously Reported — Now Fixed ✅
Still Open from Review 31. Double "the" typo in
|
- bb-admin-common-assets.php: fix a double "the" in the docblock that spanned
a line break ("…so the / the layer ships once…").
- App.js: note in the tier-tabs re-enable comment that WAI-ARIA arrow-key
navigation must be added when Free/Pro are unlocked (no-op while only the
"All" tab is focusable, so not wired yet).
|
@claude On #2 — I deliberately did not add the handler now (it'd be dead code until Free/Pro unlock, and the reviewer themselves said |
|
Claude finished @jitendrabanjara1991's task in 4m 21s —— View job PR Review: PROD-10021 — Integration 2.0 + Shared Admin-Common Layer
SummaryFresh read of all 53 changed files (5th cycle). All 15 issues raised across four prior review cycles are resolved. No new critical or medium issues found. Previously Reported — All Fixed ✅
On issue 15 — tablist arrow-key navigationThe developer's decision to defer the handler is accepted. The comment at { /* Tier tabs — Figma layout. Only "All" is wired today; Free/Pro
are disabled (not no-op) until the API exposes a free/pro
field (Q5), so a visible filter never silently returns the
same results. Re-enable by: (1) removing `disabled`, (2) handling
`tier` in the list query, and (3) adding WAI-ARIA arrow-key
navigation (onKeyDown on the tablist — Left/Right cycles tabs);
a11y nav is unnecessary while only one tab is focusable. */ }With only one focusable tab, the WAI-ARIA Tabs Pattern's arrow-key requirement is not currently violated. The prior review explicitly said "not necessarily now." The comment ensures the future developer cannot unlock the tabs without seeing the a11y requirement. This is an acceptable resolution. Informational
|
Switch the drawer's content.rendered sanitizer from the basic sanitizeHtml to sanitizeKbArticle — the same rich-content sanitizer the Knowledge Base modal uses. It allows WP block markup, images, and trusted video embeds (<iframe> from a YouTube/Vimeo host allowlist), so integration content with real media now renders the same way the KB articles do, with the same security posture.
…anch merge The KB subsystem moved into the shared admin-common layer on this branch. The Help branch's HelpScreen still imports KbContext / taxonomyCache / curatedOverrides from their old settings paths, so those break once both land in dev. - common/index.js: export the KB helpers from the public API (getTaxonomy, clearTaxonomy, getCuratedOverrides; KbProvider/useKb already public). - Add backward-compat shims at the old settings paths that re-export from @bb/admin-common, so existing consumers resolve to the single shared KB instance with no duplicate bundle (a duplicate KbContext would break useKb): - settings/context/KbContext.js - settings/components/knowledge-base/taxonomyCache.js - settings/components/knowledge-base/curatedOverrides.js
…into PROD-10021 * 'PROD-10021' of github.com:buddyboss/buddyboss-platform: PROD-10021 - Integrations make colors dynamic
… cleanup REST proxy (class-bb-rest-integrations-endpoint.php): - Add a path-prefix allowlist (bb_integrations_allowed_path_prefixes, default /wp-json/wp/v2/integrations) so the proxy can only fetch the public Integrations directory endpoints, not arbi - Negatively cache upstream failures for 1 minute (replays the WP_Error) so a slow/broken upstream isn't re-hit on every Admin page (bb-admin-integrations-page.php): - Bail with an actionable notice when the shared common build is missing, instead of loading the bundle with an unre Client: - integrationsApi: give debounce() a .cancel() method; drop the unused clearIntegrationsCache helper. - App.js: cancel the debounced search on unmount (no setState after unmount). - IntegrationCard / IntegrationDrawer: use s the logo and screenshot <img> sources — the image-specific sanitizer.
Badge: - Read the plan from acf.type_label (the API returns it nested under acf). Show the PRO badge for any non-"free" label (case-insensitive — the paid value is "Premium", not "Pro"); Free shows no badge. - Match the Settings 2.0 .bb-pro-badge UI: crown icon + "PRO" on the gradient pill (linear-gradient #f7dfdb→#d8d6ff, 1px #e0623d border). Free/Pro filter (server-side): - Tabs filter the list by acf.type_label via the API: TIER_PARAM maps All→'', Free→"Free", Pro→"Premium"; buildListPath appends ?type_label=…, and the fetch keys on tier. Pagination/counts come from the API headers, so it stays correct per tab and scales to any directory size (no client-side fetch-all). - Enable the tabs (the buddyboss.com API now honors type_label), reset to page 1 on tab change, and add WAI-ARIA arrow-key navigation. - Request `acf` in the list + detail _fields.
Badge: - Read the plan from acf.type_label (the API returns it nested under acf). Show the PRO badge for any non-"free" label (case-insensitive — the paid value is "Premium", not "Pro"); Free shows no badge. - Match the Settings 2.0 .bb-pro-badge UI: crown icon + "PRO" on the gradient pill (linear-gradient #f7dfdb→#d8d6ff, 1px #e0623d border). Free/Pro filter (server-side): - Tabs filter the list by acf.type_label via the API: TIER_PARAM maps All→'', Free→"Free", Pro→"Premium"; buildListPath appends ?type_label=…, and the fetch keys on tier. Pagination/counts come from the API headers, so it stays correct per tab and scales to any directory size (no client-side fetch-all). - Enable the tabs (the buddyboss.com API now honors type_label), reset to page 1 on tab change, and add WAI-ARIA arrow-key navigation. - Request `acf` in the list + detail _fields.
…om the card
Free wordpress.org plugins can now be installed, activated and deactivated in
place from the marketplace cards.
Server:
- class-bb-admin-integrations-ajax.php (new): activate/deactivate AJAX —
capability before nonce, check_ajax_referer, and the target plugin file is
resolved from the wp.org slug server-side (never trusts a client path).
Registered in bb-admin-settings-init.php under is_admin()/wp_doing_ajax().
- bb-admin-integrations-page.php: localize bbIntegrationsPlugins (installed
slug→{file,active} map + caps + nonce), cap-gated and only on this page, so
cards render the right button with zero extra requests; enqueue core
`updates` (install-plugin flow + filesystem-credentials modal).
Client:
- utils/pluginActions.js (new): wporgSlug() derives the slug from
acf.plugin_link; install via core wp.updates; activate/deactivate via the
guarded AJAX.
- App.js holds the installed map in state and updates it on each action (no
refetch); threads a `plugins` prop App → Grid → Card.
- IntegrationCard.js: state-driven primary button — Install → Activate →
Deactivate for free wp.org plugins (busy + inline error states, gated on
install_plugins / activate_plugins). Pro plugins and free non-wp.org links
render a disabled "Install" (matches Figma — no "Get Pro"). "Learn More ↗"
→ acf.plugin_link.
- admin.scss: cursor:pointer on the action button (it's a <button>) + an
inline card error style.
Make the card follow the standard two-step WordPress flow: clicking "Install" now installs the plugin (inactive) and the button changes to "Activate" — activation is a separate, deliberate click, not automatic. handleInstall marks the plugin installed-but-inactive after wp.updates installs it (the plugin file is resolved server-side from the slug on activate) instead of chaining an immediate activate.
|
@claude |
|
Claude finished @jitendrabanjara1991's task in 6m 46s —— View job PR Review: PROD-10021 — Integration 2.0 + Shared Admin-Common Layer
SummaryThis is a fresh, from-scratch review of the full diff (6th cycle). All 15 issues raised across the five prior review cycles are confirmed fixed. The codebase is in strong shape. This pass surfaces 2 medium and 2 low findings, 3 of which are new. Previously Reported — All Fixed ✅
New Since Last Review — Tabs Re-EnabledBetween review 5 and this review, the Free/Pro tier tabs have been fully activated: the Medium1. WAI-ARIA Tabs Pattern:
|
Jira Issue:
https://buddyboss.atlassian.net/browse/PROD-10021
General Note
Keep all conversations related to this PR in the associated Jira issue(s). Do NOT add comment on this PR or edit this PR’s description.
Notes to Developer
Notes to Reviewer