fix(spa-nav): refresh navigation immediately when modules are toggled
This commit is contained in:
@@ -1,8 +1,23 @@
|
|||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { navTree, MainNode, NAV_TREE_VERSION } from '../nav/tree';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { navTree as initialNavTree, MainNode } from '../nav/tree';
|
||||||
|
|
||||||
|
function getCurrentNavTree(): MainNode[] {
|
||||||
|
const tree = window.WNW_NAV_TREE;
|
||||||
|
return Array.isArray(tree) && tree.length > 0
|
||||||
|
? (tree as MainNode[])
|
||||||
|
: initialNavTree;
|
||||||
|
}
|
||||||
|
|
||||||
export function useActiveSection(): { main: MainNode; all: MainNode[] } {
|
export function useActiveSection(): { main: MainNode; all: MainNode[] } {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
const [navTree, setNavTree] = useState<MainNode[]>(getCurrentNavTree);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleNavUpdate = () => setNavTree(getCurrentNavTree());
|
||||||
|
window.addEventListener('woonoow:navigation-updated', handleNavUpdate);
|
||||||
|
return () => window.removeEventListener('woonoow:navigation-updated', handleNavUpdate);
|
||||||
|
}, []);
|
||||||
|
|
||||||
function pick(): MainNode {
|
function pick(): MainNode {
|
||||||
// Special case: /settings should match settings section
|
// Special case: /settings should match settings section
|
||||||
@@ -32,8 +47,5 @@ export function useActiveSection(): { main: MainNode; all: MainNode[] } {
|
|||||||
const main = pick();
|
const main = pick();
|
||||||
const children = Array.isArray(main.children) ? main.children : [];
|
const children = Array.isArray(main.children) ? main.children : [];
|
||||||
|
|
||||||
// Debug: ensure we are using the latest tree module (driven by PHP-localized window.wnw.isDev)
|
|
||||||
const isDev = Boolean((window as any).wnw?.isDev);
|
|
||||||
|
|
||||||
return { main: { ...main, children }, all: navTree } as const;
|
return { main: { ...main, children }, all: navTree } as const;
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,20 @@ export default function Modules() {
|
|||||||
mutationFn: async ({ moduleId, enabled }: { moduleId: string; enabled: boolean }) => {
|
mutationFn: async ({ moduleId, enabled }: { moduleId: string; enabled: boolean }) => {
|
||||||
return api.post('/modules/toggle', { module_id: moduleId, enabled });
|
return api.post('/modules/toggle', { module_id: moduleId, enabled });
|
||||||
},
|
},
|
||||||
onSuccess: (data, variables) => {
|
onSuccess: (data: any, variables) => {
|
||||||
|
if (Array.isArray(data?.enabled_modules)) {
|
||||||
|
queryClient.setQueryData(['modules-enabled'], { enabled: data.enabled_modules });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(data?.nav_tree)) {
|
||||||
|
window.WNW_NAV_TREE = data.nav_tree;
|
||||||
|
window.dispatchEvent(new CustomEvent('woonoow:navigation-updated', {
|
||||||
|
detail: { moduleId: variables.moduleId, enabled: variables.enabled },
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
queryClient.invalidateQueries({ queryKey: ['modules'] });
|
queryClient.invalidateQueries({ queryKey: ['modules'] });
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['modules-enabled'] });
|
||||||
toast.success(
|
toast.success(
|
||||||
variables.enabled
|
variables.enabled
|
||||||
? __('Module enabled successfully')
|
? __('Module enabled successfully')
|
||||||
|
|||||||
23
admin-spa/src/types/window.d.ts
vendored
23
admin-spa/src/types/window.d.ts
vendored
@@ -60,6 +60,14 @@ interface WNW_Store {
|
|||||||
position?: string;
|
position?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface WNW_NavNode {
|
||||||
|
key: string;
|
||||||
|
path: string;
|
||||||
|
icon: string;
|
||||||
|
label: string;
|
||||||
|
children?: any[];
|
||||||
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
WNW_API: WNW_API_Config; // Make required to avoid "possibly undefined" check in every usage if we are sure it exists
|
WNW_API: WNW_API_Config; // Make required to avoid "possibly undefined" check in every usage if we are sure it exists
|
||||||
@@ -67,19 +75,20 @@ declare global {
|
|||||||
WNW_WC_MENUS?: WNW_WC_MENUS;
|
WNW_WC_MENUS?: WNW_WC_MENUS;
|
||||||
WNW_CONFIG?: WNW_CONFIG;
|
WNW_CONFIG?: WNW_CONFIG;
|
||||||
WNW_STORE?: WNW_Store;
|
WNW_STORE?: WNW_Store;
|
||||||
WNW_NAV_TREE?: Array<{
|
WNW_NAV_TREE?: WNW_NavNode[];
|
||||||
key: string;
|
|
||||||
path: string;
|
|
||||||
icon: string;
|
|
||||||
label: string;
|
|
||||||
children?: any[];
|
|
||||||
}>;
|
|
||||||
WNW_ADDON_ROUTES?: Array<{
|
WNW_ADDON_ROUTES?: Array<{
|
||||||
path: string;
|
path: string;
|
||||||
component_url: string;
|
component_url: string;
|
||||||
props?: Record<string, any>;
|
props?: Record<string, any>;
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface WindowEventMap {
|
||||||
|
'woonoow:navigation-updated': CustomEvent<{
|
||||||
|
moduleId?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { };
|
export { };
|
||||||
|
|||||||
@@ -151,6 +151,10 @@ class ModulesController extends WP_REST_Controller {
|
|||||||
'success' => true,
|
'success' => true,
|
||||||
'module_id' => $module_id,
|
'module_id' => $module_id,
|
||||||
'enabled' => $enabled,
|
'enabled' => $enabled,
|
||||||
|
'enabled_modules' => ModuleRegistry::get_enabled_modules(),
|
||||||
|
'nav_tree' => class_exists('\WooNooW\Compat\NavigationRegistry')
|
||||||
|
? \WooNooW\Compat\NavigationRegistry::get_frontend_nav_tree()
|
||||||
|
: [],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ if (! defined('ABSPATH')) exit;
|
|||||||
class NavigationRegistry
|
class NavigationRegistry
|
||||||
{
|
{
|
||||||
const NAV_OPTION = 'wnw_nav_tree';
|
const NAV_OPTION = 'wnw_nav_tree';
|
||||||
const NAV_VERSION = '1.3.1'; // Updated Coupons link
|
const NAV_VERSION = '1.3.3'; // Reordered marketing links by usage priority
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize hooks
|
* Initialize hooks
|
||||||
@@ -217,14 +217,19 @@ class NavigationRegistry
|
|||||||
{
|
{
|
||||||
$children = [];
|
$children = [];
|
||||||
|
|
||||||
|
// Coupons - always available
|
||||||
|
$children[] = ['label' => __('Coupons', 'woonoow'), 'mode' => 'spa', 'path' => '/marketing/coupons'];
|
||||||
|
|
||||||
|
// Affiliate - only if module enabled
|
||||||
|
if (\WooNooW\Core\ModuleRegistry::is_enabled('affiliate')) {
|
||||||
|
$children[] = ['label' => __('Affiliates', 'woonoow'), 'mode' => 'spa', 'path' => '/marketing/affiliates'];
|
||||||
|
}
|
||||||
|
|
||||||
// Newsletter - only if module enabled
|
// Newsletter - only if module enabled
|
||||||
if (\WooNooW\Core\ModuleRegistry::is_enabled('newsletter')) {
|
if (\WooNooW\Core\ModuleRegistry::is_enabled('newsletter')) {
|
||||||
$children[] = ['label' => __('Newsletter', 'woonoow'), 'mode' => 'spa', 'path' => '/marketing/newsletter'];
|
$children[] = ['label' => __('Newsletter', 'woonoow'), 'mode' => 'spa', 'path' => '/marketing/newsletter'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coupons - always available
|
|
||||||
$children[] = ['label' => __('Coupons', 'woonoow'), 'mode' => 'spa', 'path' => '/marketing/coupons'];
|
|
||||||
|
|
||||||
return $children;
|
return $children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user