feat(sideNav): make plugins work with new nav

This commit is contained in:
Johannes Millan 2025-09-09 22:26:57 +02:00
parent bd6bea5e11
commit 47ffd20edd
6 changed files with 54 additions and 1 deletions

View file

@ -23,6 +23,7 @@ import {
import { toggleHideFromMenu } from '../../features/project/store/project.actions';
import { NavConfig, NavItem, NavWorkContextItem } from './magic-side-nav.model';
import { TODAY_TAG } from '../../features/tag/tag.const';
import { PluginBridgeService } from '../../plugins/plugin-bridge.service';
@Injectable({
providedIn: 'root',
@ -34,6 +35,7 @@ export class MagicNavConfigService {
private readonly _shepherdService = inject(ShepherdService);
private readonly _matDialog = inject(MatDialog);
private readonly _store = inject(Store);
private readonly _pluginBridge = inject(PluginBridgeService);
// Simple state signals
private readonly _isProjectsExpanded = signal(
@ -66,6 +68,7 @@ export class MagicNavConfigService {
this._workContextService.activeWorkContextId$,
{ initialValue: null },
);
private readonly _pluginMenuEntries = this._pluginBridge.menuEntries;
// Main navigation configuration
readonly navConfig = computed<NavConfig>(() => ({
@ -100,6 +103,9 @@ export class MagicNavConfigService {
route: '/boards',
},
// Plugin entries
...this._buildPluginItems(),
// Separator
{ type: 'separator', id: 'sep-2' },
@ -228,6 +234,7 @@ export class MagicNavConfigService {
label: T.MH.SETTINGS,
icon: 'settings',
route: '/config',
tourClass: 'tour-settingsMenuBtn',
},
],
fullModeByDefault: true,
@ -337,6 +344,19 @@ export class MagicNavConfigService {
}));
}
private _buildPluginItems(): NavItem[] {
const pluginEntries = this._pluginMenuEntries();
return pluginEntries.map((entry) => ({
type: 'plugin',
id: `plugin-${entry.pluginId}-${entry.label}`,
label: entry.label,
icon: entry.icon || 'extension',
pluginId: entry.pluginId,
action: entry.onClick,
}));
}
// Public computed signals for expansion state (for component to check)
readonly isProjectsExpanded = computed(() => this._isProjectsExpanded());
readonly isTagsExpanded = computed(() => this._isTagsExpanded());

View file

@ -123,6 +123,7 @@
[svgIcon]="item.svgIcon"
[label]="item.label"
[showLabels]="showText()"
[tourClass]="item.tourClass"
(clicked)="onItemClick(item)"
></nav-item>
}
@ -134,6 +135,7 @@
[svgIcon]="item.svgIcon"
[label]="item.label"
[showLabels]="showText()"
[tourClass]="item.tourClass"
(clicked)="onItemClick(item)"
></nav-item>
}
@ -144,6 +146,18 @@
[svgIcon]="item.svgIcon"
[label]="item.label"
[showLabels]="showText()"
[tourClass]="item.tourClass"
(clicked)="onItemClick(item)"
></nav-item>
}
@case ('plugin') {
<nav-item
[container]="'action'"
[icon]="item.icon"
[svgIcon]="item.svgIcon"
[label]="item.label"
[showLabels]="showText()"
[tourClass]="item.tourClass"
(clicked)="onItemClick(item)"
></nav-item>
}

View file

@ -216,6 +216,10 @@ export class MagicSideNavComponent implements OnInit, OnDestroy {
item.action?.();
}
if (item.type === 'plugin') {
item.action?.();
}
// Handle via service for actions/hrefs
this._sideNavConfigService.onNavItemClick(item);

View file

@ -10,13 +10,15 @@ export type NavItem =
| NavHrefItem
| NavActionItem
| NavGroupItem
| NavMenuItem;
| NavMenuItem
| NavPluginItem;
export interface NavBaseItem {
id: string;
label?: string;
icon?: string;
svgIcon?: string;
tourClass?: string;
}
export interface NavSeparatorItem extends NavBaseItem {
@ -80,6 +82,14 @@ export interface NavMenuItem extends NavBaseItem {
children: NavItem[];
}
export interface NavPluginItem extends NavBaseItem {
type: 'plugin';
label: string;
icon: string;
pluginId: string;
action: () => void;
}
export interface NavAdditionalButton {
id: string;
icon: string;

View file

@ -59,6 +59,7 @@
mat-menu-item
class="nav-link"
[class.expanded]="expanded()"
[class]="tourClass()"
(click)="clicked.emit()"
>
@if (svgIcon()) {
@ -131,6 +132,7 @@
[attr.aria-expanded]="container() === 'group' ? expanded() : null"
[attr.aria-controls]="container() === 'group' ? ariaControls() : null"
[matMenuTriggerFor]="menuTriggerFor()"
[class]="tourClass()"
(click)="clicked.emit()"
>
@if (svgIcon()) {

View file

@ -87,6 +87,9 @@ export class NavItemComponent {
// Optional: menu trigger for dropdown
menuTriggerFor = input<any | null>(null);
// Tour class for Shepherd.js guide
tourClass = input<string | null>(null);
// Events
clicked = output<void>();