Fix contact add link to use Contacts_Edit_Action SPA route
Add multi-route support for controllers and SPA actions Add screenshot feature to rsx:debug and convert contacts edit to SPA 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -248,7 +248,7 @@ class Rsx {
|
||||
pattern = Rsx._routes[class_name][action_name];
|
||||
} else {
|
||||
// Not found in PHP routes - check if it's a SPA action
|
||||
pattern = Rsx._try_spa_action_route(class_name);
|
||||
pattern = Rsx._try_spa_action_route(class_name, params_obj);
|
||||
|
||||
if (!pattern) {
|
||||
// Route not found - use default pattern /_/{controller}/{action}
|
||||
@@ -261,6 +261,60 @@ class Rsx {
|
||||
return Rsx._generate_url_from_pattern(pattern, params_obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the best matching route pattern from available patterns based on provided parameters
|
||||
*
|
||||
* Selection algorithm:
|
||||
* 1. Filter patterns where all required parameters can be satisfied by provided params
|
||||
* 2. Among satisfiable patterns, prioritize those with MORE parameters (more specific)
|
||||
* 3. If tie, any pattern works (deterministic by using first match)
|
||||
*
|
||||
* @param {Array<string>} patterns Array of route patterns
|
||||
* @param {Object} params_obj Provided parameters
|
||||
* @returns {string|null} Selected pattern or null if none match
|
||||
*/
|
||||
static _select_best_route_pattern(patterns, params_obj) {
|
||||
const satisfiable = [];
|
||||
|
||||
for (const pattern of patterns) {
|
||||
// Extract required parameters from pattern
|
||||
const required_params = [];
|
||||
const matches = pattern.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g);
|
||||
if (matches) {
|
||||
// Remove the : prefix from each match
|
||||
for (const match of matches) {
|
||||
required_params.push(match.substring(1));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if all required parameters are provided
|
||||
let can_satisfy = true;
|
||||
for (const required of required_params) {
|
||||
if (!(required in params_obj)) {
|
||||
can_satisfy = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_satisfy) {
|
||||
satisfiable.push({
|
||||
pattern: pattern,
|
||||
param_count: required_params.length
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (satisfiable.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Sort by parameter count descending (most parameters first)
|
||||
satisfiable.sort((a, b) => b.param_count - a.param_count);
|
||||
|
||||
// Return the pattern with the most parameters
|
||||
return satisfiable[0].pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate URL from route pattern by replacing parameters
|
||||
*
|
||||
@@ -327,9 +381,10 @@ class Rsx {
|
||||
* Returns the route pattern or null if not found
|
||||
*
|
||||
* @param {string} class_name The action class name
|
||||
* @param {Object} params_obj The parameters for route selection
|
||||
* @returns {string|null} The route pattern or null
|
||||
*/
|
||||
static _try_spa_action_route(class_name) {
|
||||
static _try_spa_action_route(class_name, params_obj) {
|
||||
// Get all classes from manifest
|
||||
const all_classes = Manifest.get_all_classes();
|
||||
|
||||
@@ -346,8 +401,18 @@ class Rsx {
|
||||
const routes = class_object._spa_routes || [];
|
||||
|
||||
if (routes.length > 0) {
|
||||
// Return the first route pattern
|
||||
return routes[0];
|
||||
// Select best matching route based on parameters
|
||||
const selected = Rsx._select_best_route_pattern(routes, params_obj);
|
||||
|
||||
if (!selected) {
|
||||
// Routes exist but none are satisfiable
|
||||
throw new Error(
|
||||
`No suitable route found for SPA action ${class_name} with provided parameters. ` +
|
||||
`Available routes: ${routes.join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user