Skip to content

feat(rox-appointment-booking): add action bridge and UI - #216

Open
RishadAlam wants to merge 7 commits into
mainfrom
feat/rox-appointment-booking
Open

feat(rox-appointment-booking): add action bridge and UI#216
RishadAlam wants to merge 7 commits into
mainfrom
feat/rox-appointment-booking

Conversation

@RishadAlam

@RishadAlam RishadAlam commented Sep 1, 2026

Copy link
Copy Markdown
Member

Description

Adds the Free half of the Rox Appointment Booking integration: the action bridge that forwards 25 write actions to Pro, the flow-builder UI, and the trigger registration. Requires the matching bit-integrations-pro PR.

Motivation & Context

Extracted from Bit-Pi so Bit Integrations users can trigger flows from Rox Appointment Booking events and write back to its records. Free holds no integration logic — it fires bit_integrations_rox_appointment_booking_* filters that Pro answers.

Related Links: (if applicable)

Must merge together with Bit-Apps-Pro/bit-integrations-pro#146 — Free only fires the hooks; without the Pro PR every action returns "Bit Integrations Pro plugin is not installed or activate".

Extracted from Bit-Apps-Pro/bit-pi#830.

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📚 Documentation update
  • ⚡ Improvement
  • 🔄 Code refactor

Key Changes

Backend

  • Added RecordApiHelper with one switch case per action, each carrying its literal hook string, and LogHandler::save on every path so a failed run leaves a Task Log entry.
  • Added four read-only catalog endpoints (services, agents, categories, locations) that back the config dropdowns and never cross the Pro hook.
  • Added the RoxAppointmentBooking entry to AllTriggersName.
  • Fixed a missing or renamed mainAction defaulting to create_customer, which silently created a customer record instead of reporting. It now returns "Invalid action".

Frontend

  • Added the three-step wizard, edit screen, field map, Utilities section and action picker entry, with every action Pro-gated.
  • Added a natural-key row beside every id — "Find Customer by Email", "Find Order by Number" — so a flow can identify a record with what the trigger actually carries. Either half satisfies the requirement.
  • Added catalog dropdowns for service, agent, category and location on the actions where they are configuration rather than the record being targeted.
  • Fixed required id fields showing no pre-added row, so the requirement only surfaced when Save was blocked.

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Tests added/updated
  • Documentation updated if needed
  • README updated if needed

Changelog

  • New Integration: Rox Appointment Booking — 16 triggers and 25 actions (Pro)
  • Feature: Identify a customer, agent, service, category, order or payment by e-mail, title, slug, order number or transaction id instead of an internal id
  • Fix: An unknown action no longer creates a customer record

Free holds no integration logic: RecordApiHelper turns the chosen action into a
literal filter call and Pro answers it. One switch case per action, each with its
own hook string so the wiring is greppable from either plugin, and every path
falls through to LogHandler::save so a failed run leaves something in the Task
Log.

Each Hooks::apply passes only what its handler reads — the field map alone for
most, plus $utilities where the action has optional selects, plus the config
where it has a catalog dropdown or a required status enum. The argument count,
the accepted_args in Pro and the handler signature agree for all 25.

The controller also serves the catalog lists behind the config dropdowns
(services, agents, categories, locations). Those are read-only fetches, so they
stay in Free and never cross the Pro hook. Only lists an action actually uses are
exposed; there is no unused refresh route.

AllTriggersName registers the trigger side under the same PascalCase key the
Pro controller passes to Flow::exists.
Three-step wizard plus the edit screen, cloned from the FluentCart layout so the
field-map header, the centred add-row button, the loader and the section
headings match every other integration.

What goes in the field map versus a dropdown follows one rule: the field map is
for values that change per run, dropdowns are for configuration chosen once.

  field map   the record the action targets, the customer (a form submission
              carries it), dates, amounts, free text
  dropdown    catalog references that do not vary — service, agent, category,
              location — plus the required status enums and, under Utilities,
              the optional ones

Every id also offers a natural-key row ("Find Customer by Email", "Find Order by
Number"), so a flow can identify a record with what the trigger actually has.
The pair is mandatory but either half satisfies it, so neither carries a required
flag; generateMappedField seeds the row from the pair instead, leaving it
switchable in the dropdown, and checkRequiredSelect blocks the save when no half
is mapped. Without that seeding an action whose only requirement is an id opened
with a blank row and no sign anything was needed.

Lookup keys are prefixed find_by_ so they can never collide with a writable
column of the same name.

All 25 actions are Pro, so every module carries is_pro and the action select is
gated for non-Pro users.
…uilder

Lazy import plus a case in the new, edit and info routers, and an entry in the
action picker.

The picker entry carries an explicit name. `type` is the routing key that has to
stay PascalCase to match the switch cases and Flow::exists, while the card
renders `name || type` — so without it the integration showed as
"RoxAppointmentBooking" with no spaces. Same split as the NextCrm and ModernCart
entries.
…customer

mainAction defaulted to create_customer, so a flow whose action was missing or
renamed silently created a customer record instead of reporting. It now falls
through to the switch default and returns "Invalid action".

Verified: an empty and a misspelled mainAction both error, a valid one still
succeeds, and no customer row is written by either failing case.
Removes the file headers that only repeat the filename, the arg-count labels
above the hook registrations (the 10, N in each line already says it), and the
notes that describe the object literal directly underneath them. Several
explanations were also duplicated across staticData, IntegLayout and CommonFunc;
each now lives once, next to the definition it justifies.

What stays is the part that is not in the code: the phpcs pragmas and translator
notes, and the reasons a later reader would otherwise undo — why the catalog
fields are dropdowns rather than field-map rows, why an either-group carries no
required flag, why the status lists are safe to hardcode, and why mainAction has
no default.
Copilot AI lite review requested due to automatic review settings September 1, 2026 09:51
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

🔍 WordPress Plugin Check Report

⚠️ Status: Passed with warnings

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
1 0 1

⚠️ Warnings (1)

📁 readme.txt (1 warning)
📍 Line 🔖 Check 💬 Message
0 mismatched_plugin_name Plugin name "Bit integrations - Form Integration, Webhook, Spreadsheets, CRM, LMS & Email Automation" is different from the name declared in plugin header "Bit Integrations".

🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

There are a few concrete correctness/accessibility issues (catalog label fallback edge case, user-facing typo, and a non-descriptive aria-label) that should be fixed before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds the “Free” half of the Rox Appointment Booking integration to Bit Integrations: a Pro-gated Flow Builder UI plus backend routes/controllers that expose read-only catalogs and forward write actions to Pro via prefixed hooks.

Changes:

  • Registers the Rox Appointment Booking integration in the action picker UI and integration routing (new/edit/info).
  • Adds a full action configuration UI (action select, required selects, catalog selects, field mapping, and utilities) driven by a new staticData.js.
  • Adds backend action routes/controller + RecordApiHelper that proxies actions to Pro hooks and logs every execution, plus adds RoxAppointmentBooking to AllTriggersName.
File summaries
File Description
frontend/src/components/Flow/New/SelectAction.jsx Adds Rox Appointment Booking to the action selection grid (Pro-gated).
frontend/src/components/AllIntegrations/RoxAppointmentBooking/staticData.js Defines action list, field schemas, option sets, and “required either” rules for mappings.
frontend/src/components/AllIntegrations/RoxAppointmentBooking/RoxAppointmentBookingIntegLayout.jsx Main configuration UI: action picker, required selects, catalog dropdowns, field map, utilities section.
frontend/src/components/AllIntegrations/RoxAppointmentBooking/RoxAppointmentBookingFieldMap.jsx Field mapping row UI (required rows locked; optional rows add/remove).
frontend/src/components/AllIntegrations/RoxAppointmentBooking/RoxAppointmentBookingCommonFunc.js Refresh catalog helpers, mapping validation, required-select validation, and initial field-map generation.
frontend/src/components/AllIntegrations/RoxAppointmentBooking/RoxAppointmentBookingAuthorization.jsx Adds plugin-presence authorization via WP constant check + tutorial link wiring.
frontend/src/components/AllIntegrations/RoxAppointmentBooking/RoxAppointmentBookingActions.jsx Utilities modal UI for optional enum selections stored under conf.utilities.*.
frontend/src/components/AllIntegrations/RoxAppointmentBooking/RoxAppointmentBooking.jsx New-integration wizard wrapper: state init, step transition validation, save config hook.
frontend/src/components/AllIntegrations/RoxAppointmentBooking/EditRoxAppointmentBooking.jsx Edit screen for existing Rox Appointment Booking action configs.
frontend/src/components/AllIntegrations/NewInteg.jsx Adds lazy import + routing case for creating the integration.
frontend/src/components/AllIntegrations/IntegInfo.jsx Adds authorization/info rendering for Rox Appointment Booking in integration info view.
frontend/src/components/AllIntegrations/EditInteg.jsx Adds lazy import + routing case for editing the integration.
backend/Core/Util/AllTriggersName.php Registers Rox Appointment Booking in the triggers list (Pro-gated).
backend/Actions/RoxAppointmentBooking/RoxAppointmentBookingController.php Adds authorize endpoint, catalog refresh endpoints, and execution entrypoint.
backend/Actions/RoxAppointmentBooking/Routes.php Wires AJAX routes for authorize + four catalog refresh endpoints.
backend/Actions/RoxAppointmentBooking/RecordApiHelper.php Proxies 25 actions to prefixed hooks, returns “Invalid action” on unknown, and logs outcomes.
Review details
  • Files reviewed: 16/17 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +35 to +39
$defaultResponse = [
'success' => false,
// translators: %s: Plugin name
'message' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro')
];
Comment on lines +95 to +100
function ($row) {
return (object) [
'value' => (int) $row->id,
'label' => $row->label !== '' ? $row->label : '#' . $row->id,
];
},
Comment on lines +110 to +114
<button
onClick={() => delFieldMap(i, roxAppointmentBookingConf, setRoxAppointmentBookingConf)}
className="icn-btn sh-sm ml-1"
type="button"
aria-label="btn">
RoxAppointmentBookingAuthorization reads tutorialLinks.roxAppointmentBooking,
which had no entry, so the authorization screen showed no documentation link.
Copilot AI review requested due to automatic review settings September 1, 2026 12:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

2 participants