var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { Component, ChangeDetectionStrategy, ViewChild } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
import { Metadata, CompositeKey } from '@memberjunction/core';
import { BaseResourceComponent } from '@memberjunction/ng-shared';
import { DashboardEngine } from '@memberjunction/core-entities';
import { createDefaultDashboardConfig } from '@memberjunction/ng-dashboard-viewer';
import * as i0 from "@angular/core";
import * as i1 from "@angular/router";
import * as i2 from "@memberjunction/ng-shared";
import * as i3 from "@angular/forms";
import * as i4 from "@memberjunction/ng-dashboard-viewer";
import * as i5 from "./dashboard-share-dialog.component";
const _c0 = ["dashboardViewer"];
function DashboardBrowserResourceComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
    const _r1 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "mj-dashboard-browser", 3);
    i0.ɵɵlistener("DashboardOpen", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_DashboardOpen_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDashboardOpen($event)); })("DashboardEdit", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_DashboardEdit_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDashboardEdit($event)); })("DashboardDelete", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_DashboardDelete_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDashboardDelete($event)); })("DashboardMove", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_DashboardMove_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDashboardMove($event)); })("DashboardCreate", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_DashboardCreate_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDashboardCreate($event)); })("CategoryCreate", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_CategoryCreate_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCategoryCreate($event)); })("CategoryDelete", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_CategoryDelete_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCategoryDelete($event)); })("CategoryChange", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_CategoryChange_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCategoryChange($event)); })("ViewPreferenceChange", function DashboardBrowserResourceComponent_Conditional_1_Template_mj_dashboard_browser_ViewPreferenceChange_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onViewPreferenceChange($event)); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵproperty("Dashboards", ctx_r1.dashboards)("Categories", ctx_r1.categories)("SelectedCategoryId", ctx_r1.selectedCategoryId)("ViewMode", ctx_r1.viewMode)("IsLoading", ctx_r1.isLoading)("ShowCreateButton", true)("AllowMultiSelect", true)("AllowDragDrop", true)("DashboardPermissions", ctx_r1.dashboardPermissionsMap)("EffectiveCategoryMap", ctx_r1.effectiveCategoryMap);
} }
function DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Conditional_3_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "span", 14);
    i0.ɵɵelement(1, "i", 19);
    i0.ɵɵtext(2, " Shared with you ");
    i0.ɵɵelementEnd();
} }
function DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Conditional_6_Template(rf, ctx) { if (rf & 1) {
    const _r5 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "button", 20);
    i0.ɵɵlistener("click", function DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openShareDialog()); });
    i0.ɵɵelement(1, "i", 21);
    i0.ɵɵelementEnd();
} }
function DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Conditional_7_Template(rf, ctx) { if (rf & 1) {
    const _r6 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "button", 22);
    i0.ɵɵlistener("click", function DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleEditMode()); });
    i0.ɵɵelement(1, "i", 23);
    i0.ɵɵelementEnd();
} }
function DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
    const _r4 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 4)(1, "mj-dashboard-breadcrumb", 12);
    i0.ɵɵlistener("Navigate", function DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Template_mj_dashboard_breadcrumb_Navigate_1_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onBreadcrumbNavigate($event)); });
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(2, "div", 13);
    i0.ɵɵconditionalCreate(3, DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Conditional_3_Template, 3, 0, "span", 14);
    i0.ɵɵelementStart(4, "button", 15);
    i0.ɵɵlistener("click", function DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openInNewTab()); });
    i0.ɵɵelement(5, "i", 16);
    i0.ɵɵelementEnd();
    i0.ɵɵconditionalCreate(6, DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Conditional_6_Template, 2, 0, "button", 17);
    i0.ɵɵconditionalCreate(7, DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Conditional_7_Template, 2, 0, "button", 18);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance();
    i0.ɵɵproperty("Categories", ctx_r1.categories)("CurrentCategoryId", (ctx_r1.selectedDashboard == null ? null : ctx_r1.selectedDashboard.CategoryID) || null)("CurrentDashboard", ctx_r1.selectedDashboard)("ShowDashboardName", true)("AllowDragDrop", false);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(!ctx_r1.selectedDashboardPermissions.IsOwner && ctx_r1.selectedDashboardPermissions.CanRead ? 3 : -1);
    i0.ɵɵadvance(3);
    i0.ɵɵconditional(ctx_r1.selectedDashboardPermissions.CanShare ? 6 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r1.selectedDashboardPermissions.CanEdit ? 7 : -1);
} }
function DashboardBrowserResourceComponent_Conditional_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
    const _r7 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 5)(1, "div", 24)(2, "button", 25);
    i0.ɵɵlistener("click", function DashboardBrowserResourceComponent_Conditional_2_Conditional_1_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openAddPartDialog()); });
    i0.ɵɵelement(3, "i", 26);
    i0.ɵɵtext(4, " Add Part ");
    i0.ɵɵelementEnd();
    i0.ɵɵelement(5, "div", 27);
    i0.ɵɵelementStart(6, "div", 28)(7, "input", 29);
    i0.ɵɵtwoWayListener("ngModelChange", function DashboardBrowserResourceComponent_Conditional_2_Conditional_1_Template_input_ngModelChange_7_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.editingName, $event) || (ctx_r1.editingName = $event); return i0.ɵɵresetView($event); });
    i0.ɵɵlistener("blur", function DashboardBrowserResourceComponent_Conditional_2_Conditional_1_Template_input_blur_7_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onNameBlur()); });
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(8, "input", 30);
    i0.ɵɵtwoWayListener("ngModelChange", function DashboardBrowserResourceComponent_Conditional_2_Conditional_1_Template_input_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.editingDescription, $event) || (ctx_r1.editingDescription = $event); return i0.ɵɵresetView($event); });
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(9, "div", 31)(10, "button", 32);
    i0.ɵɵlistener("click", function DashboardBrowserResourceComponent_Conditional_2_Conditional_1_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.saveDashboard()); });
    i0.ɵɵelement(11, "i", 33);
    i0.ɵɵtext(12, " Save ");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(13, "button", 34);
    i0.ɵɵlistener("click", function DashboardBrowserResourceComponent_Conditional_2_Conditional_1_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.cancelEdit()); });
    i0.ɵɵtext(14, " Cancel ");
    i0.ɵɵelementEnd()()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(7);
    i0.ɵɵtwoWayProperty("ngModel", ctx_r1.editingName);
    i0.ɵɵadvance();
    i0.ɵɵtwoWayProperty("ngModel", ctx_r1.editingDescription);
} }
function DashboardBrowserResourceComponent_Conditional_2_Conditional_5_Template(rf, ctx) { if (rf & 1) {
    const _r8 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "mj-add-panel-dialog", 35);
    i0.ɵɵlistener("panelAdded", function DashboardBrowserResourceComponent_Conditional_2_Conditional_5_Template_mj_add_panel_dialog_panelAdded_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onPanelAdded($event)); })("cancelled", function DashboardBrowserResourceComponent_Conditional_2_Conditional_5_Template_mj_add_panel_dialog_cancelled_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onAddPanelCancelled()); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    i0.ɵɵnextContext();
    const dashboardViewer_r9 = i0.ɵɵreference(4);
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵproperty("visible", ctx_r1.showAddPanelDialog)("partTypes", dashboardViewer_r9.getPartTypes());
} }
function DashboardBrowserResourceComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
    const _r3 = i0.ɵɵgetCurrentView();
    i0.ɵɵconditionalCreate(0, DashboardBrowserResourceComponent_Conditional_2_Conditional_0_Template, 8, 8, "div", 4);
    i0.ɵɵconditionalCreate(1, DashboardBrowserResourceComponent_Conditional_2_Conditional_1_Template, 15, 2, "div", 5);
    i0.ɵɵelementStart(2, "div", 6)(3, "mj-dashboard-viewer", 7, 0);
    i0.ɵɵlistener("panelInteraction", function DashboardBrowserResourceComponent_Conditional_2_Template_mj_dashboard_viewer_panelInteraction_3_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onPanelInteraction($event)); })("navigationRequested", function DashboardBrowserResourceComponent_Conditional_2_Template_mj_dashboard_viewer_navigationRequested_3_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onNavigationRequested($event)); });
    i0.ɵɵelementEnd()();
    i0.ɵɵconditionalCreate(5, DashboardBrowserResourceComponent_Conditional_2_Conditional_5_Template, 1, 2, "mj-add-panel-dialog", 8);
    i0.ɵɵelementStart(6, "mj-edit-part-dialog", 9);
    i0.ɵɵlistener("Saved", function DashboardBrowserResourceComponent_Conditional_2_Template_mj_edit_part_dialog_Saved_6_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfigDialogSaved($event)); })("Cancelled", function DashboardBrowserResourceComponent_Conditional_2_Template_mj_edit_part_dialog_Cancelled_6_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfigDialogCancelled()); });
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(7, "mj-confirm-dialog", 10);
    i0.ɵɵlistener("confirmed", function DashboardBrowserResourceComponent_Conditional_2_Template_mj_confirm_dialog_confirmed_7_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onRemoveConfirmed()); })("cancelled", function DashboardBrowserResourceComponent_Conditional_2_Template_mj_confirm_dialog_cancelled_7_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onRemoveCancelled()); });
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(8, "mj-dashboard-share-dialog", 11);
    i0.ɵɵlistener("Result", function DashboardBrowserResourceComponent_Conditional_2_Template_mj_dashboard_share_dialog_Result_8_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onShareDialogResult($event)); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const dashboardViewer_r9 = i0.ɵɵreference(4);
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵconditional(ctx_r1.mode === "view" ? 0 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r1.mode === "edit" ? 1 : -1);
    i0.ɵɵadvance(2);
    i0.ɵɵproperty("dashboard", ctx_r1.selectedDashboard)("isEditing", ctx_r1.mode === "edit")("showToolbar", false)("showBreadcrumb", false);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(dashboardViewer_r9 ? 5 : -1);
    i0.ɵɵadvance();
    i0.ɵɵproperty("Visible", ctx_r1.showConfigDialog)("PartType", ctx_r1.configDialogPartType)("Panel", ctx_r1.configDialogPanel)("Config", (ctx_r1.configDialogPanel == null ? null : ctx_r1.configDialogPanel.config) || null);
    i0.ɵɵadvance();
    i0.ɵɵproperty("visible", ctx_r1.showConfirmDialog)("message", "Are you sure you want to remove '" + ctx_r1.confirmPanelTitle + "' from this dashboard?");
    i0.ɵɵadvance();
    i0.ɵɵproperty("Visible", ctx_r1.showShareDialog)("Dashboard", ctx_r1.selectedDashboard);
} }
/**
 * Resource component for browsing, creating, and editing dashboards.
 * Uses the generic DashboardBrowserComponent for list mode and handles
 * view/edit mode internally with routing integration.
 */
let DashboardBrowserResourceComponent = class DashboardBrowserResourceComponent extends BaseResourceComponent {
    cdr;
    route;
    navigationService;
    // ========================================
    // State
    // ========================================
    mode = 'list';
    isLoading = false;
    dashboards = [];
    categories = [];
    selectedDashboard = null;
    selectedCategoryId = null;
    viewMode = 'cards';
    showAddPanelDialog = false;
    // Config dialog state
    showConfigDialog = false;
    configDialogPanel = null;
    configDialogPartType = null;
    configDialogClass = '';
    // Confirm dialog state
    showConfirmDialog = false;
    confirmPanelId = '';
    confirmPanelTitle = '';
    // Share dialog state
    showShareDialog = false;
    // Edit mode state for name/description
    editingName = '';
    editingDescription = '';
    originalName = '';
    originalDescription = '';
    originalConfig = '';
    // Permission state for selected dashboard
    selectedDashboardPermissions = {
        DashboardID: '',
        CanRead: true,
        CanEdit: true,
        CanDelete: true,
        CanShare: true,
        IsOwner: true,
        PermissionSource: 'owner'
    };
    // Permission map for all dashboards (used by browser component)
    dashboardPermissionsMap = new Map();
    // Effective category map for shared dashboards (maps dashboard ID to effective category for display)
    effectiveCategoryMap = new Map();
    _destroy$ = new Subject();
    dashboardViewer;
    // ========================================
    // Constructor
    // ========================================
    constructor(cdr, route, navigationService) {
        super();
        this.cdr = cdr;
        this.route = route;
        this.navigationService = navigationService;
    }
    // ========================================
    // Lifecycle
    // ========================================
    ngOnInit() {
        this.loadDashboards();
        this.subscribeToQueryParams();
        this.loadViewPreference();
    }
    ngOnDestroy() {
        this._destroy$.next();
        this._destroy$.complete();
    }
    // ========================================
    // BaseResourceComponent Implementation
    // ========================================
    async GetResourceDisplayName(data) {
        return 'Dashboards';
    }
    async GetResourceIconClass(data) {
        return 'fa-solid fa-gauge-high';
    }
    // ========================================
    // Event Handlers from Generic Browser
    // ========================================
    /**
     * Handle dashboard open request from generic browser
     */
    onDashboardOpen(event) {
        if (event.OpenInNewTab) {
            // Open in a dedicated Explorer tab via NavigationService
            this.navigationService.OpenDashboard(event.Dashboard.ID, event.Dashboard.Name, { forceNewTab: true });
        }
        else {
            // Open inline in the browser's view pane
            this.openDashboard(event.Dashboard);
        }
    }
    /**
     * Open the current dashboard in its own dedicated Explorer tab
     */
    openInNewTab() {
        if (this.selectedDashboard) {
            this.navigationService.OpenDashboard(this.selectedDashboard.ID, this.selectedDashboard.Name, { forceNewTab: true });
        }
    }
    /**
     * Handle dashboard edit request from generic browser
     */
    onDashboardEdit(event) {
        this.editDashboard(event.Dashboard);
    }
    /**
     * Handle dashboard delete request from generic browser
     */
    async onDashboardDelete(event) {
        // The generic browser handles the confirmation dialog
        // We just need to perform the actual deletion
        try {
            this.isLoading = true;
            this.cdr.detectChanges();
            for (const dashboard of event.Dashboards) {
                const deleted = await dashboard.Delete();
                if (deleted) {
                    const index = this.dashboards.findIndex(d => UUIDsEqual(d.ID, dashboard.ID));
                    if (index >= 0) {
                        this.dashboards.splice(index, 1);
                    }
                }
            }
            // Create new array reference to trigger change detection
            this.dashboards = [...this.dashboards];
        }
        catch (err) {
            console.error('Failed to delete dashboards:', err);
        }
        finally {
            this.isLoading = false;
            this.cdr.detectChanges();
        }
    }
    /**
     * Handle dashboard move request from generic browser.
     * For owned dashboards: updates the dashboard's CategoryID directly.
     * For shared dashboards: creates/updates a DashboardCategoryLink to organize without modifying the original.
     */
    async onDashboardMove(event) {
        try {
            this.isLoading = true;
            this.cdr.detectChanges();
            const md = new Metadata();
            const currentUserId = md.CurrentUser.ID;
            for (const dashboard of event.Dashboards) {
                const permissions = DashboardEngine.Instance.GetDashboardPermissions(dashboard.ID, currentUserId);
                if (permissions.IsOwner) {
                    // Owner can modify the dashboard directly
                    dashboard.CategoryID = event.TargetCategoryId;
                    await dashboard.Save();
                }
                else {
                    // Non-owner: create or update a category link instead
                    await this.createOrUpdateCategoryLink(dashboard.ID, currentUserId, event.TargetCategoryId);
                    // Update the effective category map immediately for UI refresh
                    this.effectiveCategoryMap.set(dashboard.ID, event.TargetCategoryId);
                }
            }
            // Create new map reference to trigger change detection
            this.effectiveCategoryMap = new Map(this.effectiveCategoryMap);
            // Refresh the list
            this.dashboards = [...this.dashboards];
            // Navigate to the target category to follow the moved items
            this.selectedCategoryId = event.TargetCategoryId;
            this.updateUrlQueryParams();
        }
        catch (err) {
            console.error('Failed to move dashboards:', err);
        }
        finally {
            this.isLoading = false;
            this.cdr.detectChanges();
        }
    }
    /**
     * Creates or updates a DashboardCategoryLink for organizing a shared dashboard.
     * Ensures only one link exists per user/dashboard combination.
     * @param dashboardId - The ID of the shared dashboard
     * @param userId - The current user's ID
     * @param categoryId - The target category ID (null for root/uncategorized)
     */
    async createOrUpdateCategoryLink(dashboardId, userId, categoryId) {
        const md = new Metadata();
        // Check if a link already exists for this user/dashboard
        const existingLinks = DashboardEngine.Instance.DashboardCategoryLinks.filter(link => UUIDsEqual(link.DashboardID, dashboardId) && UUIDsEqual(link.UserID, userId));
        let link;
        if (existingLinks.length > 0) {
            // Update existing link
            link = existingLinks[0];
            link.DashboardCategoryID = categoryId;
        }
        else {
            // Create new link
            link = await md.GetEntityObject('MJ: Dashboard Category Links');
            link.DashboardID = dashboardId;
            link.UserID = userId;
            link.DashboardCategoryID = categoryId;
        }
        const saved = await link.Save();
        if (!saved) {
            console.error('Failed to save dashboard category link:', link.LatestResult);
        }
    }
    /**
     * Handle create dashboard request from generic browser
     */
    async onDashboardCreate(event) {
        await this.createDashboard(event.CategoryId);
    }
    /**
     * Handle category change from generic browser - update URL
     */
    onCategoryChange(event) {
        this.selectedCategoryId = event.CategoryId;
        this.updateUrlQueryParams();
    }
    /**
     * Handle view preference change from generic browser - persist
     */
    onViewPreferenceChange(event) {
        this.viewMode = event.ViewMode;
        this.saveViewPreference(event.ViewMode);
    }
    /**
     * Handle category create request from generic browser
     * Includes extensive logging for debugging category creation issues
     */
    async onCategoryCreate(event) {
        console.debug('[DashboardBrowserResource] Category create requested:', {
            name: event.Name,
            parentCategoryId: event.ParentCategoryId
        });
        try {
            this.isLoading = true;
            this.cdr.detectChanges();
            const md = new Metadata();
            console.debug('[DashboardBrowserResource] Current user:', {
                userId: md.CurrentUser?.ID,
                userName: md.CurrentUser?.Name,
                email: md.CurrentUser?.Email
            });
            const category = await md.GetEntityObject('MJ: Dashboard Categories');
            console.debug('[DashboardBrowserResource] Created category entity object');
            // Set required fields
            category.Name = event.Name;
            category.UserID = md.CurrentUser.ID;
            if (event.ParentCategoryId) {
                category.ParentID = event.ParentCategoryId;
            }
            console.debug('[DashboardBrowserResource] Category fields before save:', {
                name: category.Name,
                userId: category.UserID,
                parentId: category.ParentID,
                allFields: category.Fields.map(f => ({ name: f.Name, value: f.Value, dirty: f.Dirty }))
            });
            const saved = await category.Save();
            console.debug('[DashboardBrowserResource] Save result:', {
                success: saved,
                latestResult: category.LatestResult,
                message: category.LatestResult?.Message,
                success2: category.LatestResult?.Success,
                id: category.ID
            });
            if (saved) {
                console.debug('[DashboardBrowserResource] Category saved successfully, ID:', category.ID);
                // Add to local array - engine will self-update
                this.categories.push(category);
                this.categories = [...this.categories].sort((a, b) => a.Name.localeCompare(b.Name));
            }
            else {
                const errorMessage = category.LatestResult?.Message || 'Unknown error saving category';
                console.error('[DashboardBrowserResource] Failed to save category:', errorMessage);
                console.error('[DashboardBrowserResource] Full LatestResult:', JSON.stringify(category.LatestResult, null, 2));
                // Show toast or alert for user
                alert(`Failed to create category: ${errorMessage}`);
            }
        }
        catch (err) {
            console.error('[DashboardBrowserResource] Exception creating category:', err);
            alert(`Error creating category: ${err instanceof Error ? err.message : String(err)}`);
        }
        finally {
            this.isLoading = false;
            this.cdr.detectChanges();
        }
    }
    /**
     * Handle category delete request from generic browser
     * Performs recursive deletion of category and all children
     */
    async onCategoryDelete(event) {
        console.debug('[DashboardBrowserResource] Category delete requested:', event.Category.Name);
        try {
            this.isLoading = true;
            this.cdr.detectChanges();
            // Get all child categories recursively
            const categoriesToDelete = this.getChildCategoriesRecursive(event.Category.ID);
            categoriesToDelete.push(event.Category);
            console.debug('[DashboardBrowserResource] Deleting categories:', categoriesToDelete.map(c => c.Name));
            // Delete in reverse order (children first)
            for (const cat of categoriesToDelete.reverse()) {
                // First, move any dashboards in this category to uncategorized
                const dashboardsInCategory = this.dashboards.filter(d => UUIDsEqual(d.CategoryID, cat.ID));
                for (const dashboard of dashboardsInCategory) {
                    dashboard.CategoryID = null;
                    await dashboard.Save();
                }
                // Then delete the category
                const deleted = await cat.Delete();
                if (deleted) {
                    const index = this.categories.findIndex(c => UUIDsEqual(c.ID, cat.ID));
                    if (index >= 0) {
                        this.categories.splice(index, 1);
                    }
                }
                else {
                    console.error('[DashboardBrowserResource] Failed to delete category:', cat.Name, cat.LatestResult);
                }
            }
            // Refresh arrays
            this.categories = [...this.categories];
            this.dashboards = [...this.dashboards];
        }
        catch (err) {
            console.error('[DashboardBrowserResource] Exception deleting category:', err);
        }
        finally {
            this.isLoading = false;
            this.cdr.detectChanges();
        }
    }
    /**
     * Handle breadcrumb navigation event
     * Navigates back to list view with optional category selection
     */
    onBreadcrumbNavigate(event) {
        console.debug('[DashboardBrowserResource] Breadcrumb navigate:', event);
        // CategoryId is null for root, or a category ID string
        this.selectedCategoryId = event.CategoryId;
        this.backToList();
        this.updateUrlQueryParams();
    }
    // ========================================
    // Public Methods - Navigation
    // ========================================
    /**
     * Open a dashboard for viewing
     */
    openDashboard(dashboard) {
        this.selectedDashboard = dashboard;
        this.mode = 'view';
        // Compute permissions for the selected dashboard
        const md = new Metadata();
        this.selectedDashboardPermissions = DashboardEngine.Instance.GetDashboardPermissions(dashboard.ID, md.CurrentUser.ID);
        this.updateUrlQueryParams();
        this.NotifyDisplayNameChanged(dashboard.Name || 'Dashboard');
        this.cdr.detectChanges();
    }
    /**
     * Open a dashboard for editing
     */
    editDashboard(dashboard) {
        // Check if user has edit permission
        const md = new Metadata();
        const permissions = DashboardEngine.Instance.GetDashboardPermissions(dashboard.ID, md.CurrentUser.ID);
        if (!permissions.CanEdit) {
            console.warn('User does not have permission to edit this dashboard');
            return;
        }
        this.selectedDashboard = dashboard;
        this.selectedDashboardPermissions = permissions;
        this.mode = 'edit';
        // Initialize editing fields
        this.editingName = dashboard.Name;
        this.editingDescription = dashboard.Description || '';
        // Store originals for cancel
        this.originalName = dashboard.Name;
        this.originalDescription = dashboard.Description || '';
        this.originalConfig = dashboard.UIConfigDetails || '';
        this.cdr.detectChanges();
    }
    /**
     * Go back to list view
     */
    backToList() {
        this.selectedDashboard = null;
        this.mode = 'list';
        this.updateUrlQueryParams();
        this.NotifyDisplayNameChanged('Dashboards');
        this.cdr.detectChanges();
    }
    /**
     * Toggle edit mode for current dashboard
     */
    toggleEditMode() {
        if (this.mode === 'view' && this.selectedDashboard) {
            this.editDashboard(this.selectedDashboard);
        }
        else if (this.mode === 'edit') {
            this.mode = 'view';
            this.cdr.detectChanges();
        }
    }
    /**
     * Open the share dialog for the current dashboard
     */
    openShareDialog() {
        if (!this.selectedDashboard)
            return;
        // Verify user has share permission
        if (!this.selectedDashboardPermissions.CanShare) {
            console.warn('User does not have permission to share this dashboard');
            return;
        }
        this.showShareDialog = true;
        this.cdr.detectChanges();
    }
    /**
     * Close the share dialog
     */
    closeShareDialog() {
        this.showShareDialog = false;
        this.cdr.detectChanges();
    }
    /**
     * Handle share dialog result
     */
    onShareDialogResult(result) {
        this.showShareDialog = false;
        if (result.Action === 'save' && this.selectedDashboard) {
            // Recompute permissions after sharing changes
            const md = new Metadata();
            this.selectedDashboardPermissions = DashboardEngine.Instance.GetDashboardPermissions(this.selectedDashboard.ID, md.CurrentUser.ID);
        }
        this.cdr.detectChanges();
    }
    // ========================================
    // Public Methods - Dashboard CRUD
    // ========================================
    /**
     * Create a new dashboard
     */
    async createDashboard(categoryId) {
        try {
            this.isLoading = true;
            this.cdr.detectChanges();
            const md = new Metadata();
            const dashboard = await md.GetEntityObject('MJ: Dashboards');
            dashboard.Name = 'New Dashboard';
            dashboard.Description = '';
            dashboard.UserID = md.CurrentUser.ID;
            dashboard.UIConfigDetails = JSON.stringify(createDefaultDashboardConfig());
            if (categoryId) {
                dashboard.CategoryID = categoryId;
            }
            else if (this.selectedCategoryId) {
                dashboard.CategoryID = this.selectedCategoryId;
            }
            const saved = await dashboard.Save();
            if (saved) {
                this.dashboards.unshift(dashboard);
                this.dashboards = [...this.dashboards];
                this.editDashboard(dashboard);
            }
            else {
                console.error('Failed to save dashboard:', dashboard.LatestResult);
            }
        }
        catch (err) {
            console.error('Failed to create dashboard:', err);
        }
        finally {
            this.isLoading = false;
            this.cdr.detectChanges();
        }
    }
    /**
     * Save the current dashboard
     */
    async saveDashboard() {
        if (!this.selectedDashboard)
            return;
        try {
            this.isLoading = true;
            this.cdr.detectChanges();
            this.selectedDashboard.Name = this.editingName;
            this.selectedDashboard.Description = this.editingDescription;
            if (this.dashboardViewer) {
                await this.dashboardViewer.save();
            }
            this.originalName = this.editingName;
            this.originalDescription = this.editingDescription;
            this.originalConfig = this.selectedDashboard.UIConfigDetails || '';
            // Update the dashboard in the list
            this.dashboards = [...this.dashboards];
            this.mode = 'view';
        }
        catch (err) {
            console.error('Failed to save dashboard:', err);
        }
        finally {
            this.isLoading = false;
            this.cdr.detectChanges();
        }
    }
    /**
     * Cancel editing and revert changes
     */
    cancelEdit() {
        if (!this.selectedDashboard) {
            this.backToList();
            return;
        }
        this.selectedDashboard.Name = this.originalName;
        this.selectedDashboard.Description = this.originalDescription;
        this.selectedDashboard.UIConfigDetails = this.originalConfig;
        this.editingName = '';
        this.editingDescription = '';
        this.mode = 'view';
        this.cdr.detectChanges();
    }
    /**
     * Handle name input blur - validate name is not empty
     */
    onNameBlur() {
        if (!this.editingName.trim()) {
            this.editingName = this.originalName || 'Untitled Dashboard';
        }
    }
    // ========================================
    // Public Methods - Part Management
    // ========================================
    /**
     * Open the Add Part dialog
     */
    openAddPartDialog() {
        this.showAddPanelDialog = true;
        this.cdr.detectChanges();
    }
    /**
     * Handle panel interaction events from the viewer
     */
    onPanelInteraction(event) {
        if (event.interactionType !== 'custom')
            return;
        const action = event.payload?.['action'];
        switch (action) {
            case 'add-panel-requested':
                this.openAddPartDialog();
                break;
            case 'configure-part-requested':
                this.openConfigDialog(event.panelId);
                break;
            case 'remove-part-requested':
                this.openRemoveConfirmDialog(event.panelId, event.payload?.['panelTitle'] || 'this part');
                break;
        }
    }
    /**
     * Handle navigation events from panels
     */
    onNavigationRequested(event) {
        const request = event.request;
        const openInNewTab = request.openInNewTab || false;
        switch (request.type) {
            case 'OpenEntityRecord': {
                // Navigate to entity record
                const compositeKey = new CompositeKey();
                compositeKey.SimpleLoadFromURLSegment(request.recordId);
                // If simple load didn't work (single ID without field name), look up actual PK field
                if (compositeKey.KeyValuePairs.length === 0) {
                    const md = new Metadata();
                    const entity = md.Entities.find(e => e.Name === request.entityName);
                    const pkFieldName = entity?.FirstPrimaryKey?.Name || 'ID';
                    compositeKey.LoadFromSingleKeyValuePair(pkFieldName, request.recordId);
                }
                this.navigationService.OpenEntityRecord(request.entityName, compositeKey, { forceNewTab: openInNewTab });
                break;
            }
            case 'OpenDashboard': {
                // Navigate to another dashboard
                const targetDashboard = this.dashboards.find(d => UUIDsEqual(d.ID, request.dashboardId));
                if (targetDashboard) {
                    if (openInNewTab) {
                        this.navigationService.OpenDashboard(targetDashboard.ID, targetDashboard.Name, { forceNewTab: true });
                    }
                    else {
                        this.openDashboard(targetDashboard);
                    }
                }
                break;
            }
            case 'OpenQuery': {
                // Navigate to query viewer
                const md = new Metadata();
                const queryInfo = md.Queries.find(q => UUIDsEqual(q.ID, request.queryId));
                if (queryInfo) {
                    this.navigationService.OpenQuery(request.queryId, queryInfo.Name, { forceNewTab: openInNewTab });
                }
                break;
            }
            case 'OpenNavItem': {
                // Navigate to a specific nav item within an application
                const appId = request.appName ? this.resolveAppId(request.appName) : undefined;
                this.navigationService.OpenNavItemByName(request.navItemName, undefined, appId, {
                    queryParams: request.queryParams
                });
                break;
            }
        }
    }
    /**
     * Resolve an application name to its ID
     */
    resolveAppId(appName) {
        const md = new Metadata();
        const app = md.Applications.find(a => a.Name.toLowerCase() === appName.toLowerCase());
        return app?.ID;
    }
    /**
     * Handle add panel dialog result
     */
    onPanelAdded(result) {
        if (this.dashboardViewer) {
            this.dashboardViewer.addPanel(result.PartType.ID, result.Config, result.Title, result.Icon);
        }
        this.showAddPanelDialog = false;
        this.cdr.detectChanges();
    }
    /**
     * Handle add panel dialog cancel
     */
    onAddPanelCancelled() {
        this.showAddPanelDialog = false;
        this.cdr.detectChanges();
    }
    // ========================================
    // Public Methods - Config Dialog
    // ========================================
    /**
     * Open the config dialog for a panel
     */
    openConfigDialog(panelId) {
        if (!this.dashboardViewer)
            return;
        const panel = this.dashboardViewer.getPanel(panelId);
        const partType = this.dashboardViewer.getPartTypeForPanel(panelId);
        if (!panel || !partType) {
            console.warn('Could not find panel or part type for config dialog');
            return;
        }
        this.configDialogPanel = panel;
        this.configDialogPartType = partType;
        this.configDialogClass = partType.ConfigDialogClass || '';
        this.showConfigDialog = true;
        this.cdr.detectChanges();
    }
    /**
     * Handle config dialog save
     */
    onConfigDialogSaved(result) {
        if (this.dashboardViewer && this.configDialogPanel) {
            this.dashboardViewer.updatePanelConfig(this.configDialogPanel.id, result.Config, result.Title, result.Icon);
        }
        this.closeConfigDialog();
    }
    /**
     * Handle config dialog cancel
     */
    onConfigDialogCancelled() {
        this.closeConfigDialog();
    }
    /**
     * Close the config dialog
     */
    closeConfigDialog() {
        this.showConfigDialog = false;
        this.configDialogPanel = null;
        this.configDialogPartType = null;
        this.configDialogClass = '';
        this.cdr.detectChanges();
    }
    // ========================================
    // Public Methods - Remove Confirm Dialog
    // ========================================
    /**
     * Open the remove confirmation dialog
     */
    openRemoveConfirmDialog(panelId, panelTitle) {
        this.confirmPanelId = panelId;
        this.confirmPanelTitle = panelTitle;
        this.showConfirmDialog = true;
        this.cdr.detectChanges();
    }
    /**
     * Handle remove confirmation
     */
    onRemoveConfirmed() {
        if (this.dashboardViewer && this.confirmPanelId) {
            this.dashboardViewer.confirmRemovePanel(this.confirmPanelId);
        }
        this.closeRemoveConfirmDialog();
    }
    /**
     * Handle remove cancel
     */
    onRemoveCancelled() {
        this.closeRemoveConfirmDialog();
    }
    /**
     * Close the remove confirm dialog
     */
    closeRemoveConfirmDialog() {
        this.showConfirmDialog = false;
        this.confirmPanelId = '';
        this.confirmPanelTitle = '';
        this.cdr.detectChanges();
    }
    // ========================================
    // Private Methods - Data Loading
    // ========================================
    async loadDashboards() {
        try {
            this.isLoading = true;
            this.cdr.detectChanges();
            // Use DashboardEngine for consistent cached data
            const engine = DashboardEngine.Instance;
            await engine.Config(false); // Wait for engine to load data
            const md = new Metadata();
            const currentUserId = md.CurrentUser.ID;
            // Get data from engine - sort dashboards by updated date, categories by name
            // Filter dashboards to only those accessible to the current user
            this.dashboards = [...engine.GetAccessibleDashboards(currentUserId)].sort((a, b) => new Date(b.__mj_UpdatedAt).getTime() - new Date(a.__mj_UpdatedAt).getTime());
            // Filter categories to only those owned by or shared with the current user
            this.categories = [...engine.GetAccessibleCategories(currentUserId)].sort((a, b) => a.Name.localeCompare(b.Name));
            // Build permissions map and effective category map for all dashboards
            this.dashboardPermissionsMap = new Map();
            this.effectiveCategoryMap = new Map();
            // Get category links for current user (from engine's cached data)
            const userCategoryLinks = engine.DashboardCategoryLinks.filter(link => UUIDsEqual(link.UserID, currentUserId));
            for (const dashboard of this.dashboards) {
                const perms = engine.GetDashboardPermissions(dashboard.ID, currentUserId);
                this.dashboardPermissionsMap.set(dashboard.ID, perms);
                // For shared dashboards (not owned), determine effective category
                if (!perms.IsOwner) {
                    // Look for a category link for this dashboard
                    const categoryLink = userCategoryLinks.find(link => UUIDsEqual(link.DashboardID, dashboard.ID));
                    if (categoryLink) {
                        // User has explicitly organized this shared dashboard
                        this.effectiveCategoryMap.set(dashboard.ID, categoryLink.DashboardCategoryID);
                    }
                    else {
                        // No link exists - show in root (null category)
                        this.effectiveCategoryMap.set(dashboard.ID, null);
                    }
                }
                // For owned dashboards, we don't add to effectiveCategoryMap
                // so the browser will use the dashboard's actual CategoryID
            }
            console.debug('[DashboardBrowserResource] Loaded from DashboardEngine:', {
                dashboardCount: this.dashboards.length,
                categoryCount: this.categories.length,
                sharedDashboardsInEffectiveMap: this.effectiveCategoryMap.size,
                categories: this.categories.map(c => ({ id: c.ID, name: c.Name, parentId: c.ParentID }))
            });
            // After dashboards are loaded, check for deep-link from configuration
            // (e.g., pin navigation passes dashboard ID via queryParams in config)
            this.applyConfigurationState();
            // Also watch for late-arriving query params from pin navigation
            this.watchForLateQueryParams();
            this.NotifyLoadComplete();
        }
        catch (err) {
            console.error('Failed to load dashboards:', err);
        }
        finally {
            this.isLoading = false;
            this.cdr.detectChanges();
        }
    }
    /**
     * Apply initial state from resource configuration (handles pin navigation
     * and other deep-link scenarios where ActivatedRoute may not fire).
     */
    applyConfigurationState() {
        const config = this.Data?.Configuration;
        if (!config)
            return;
        const qp = config['queryParams'];
        const dashboardId = qp?.['dashboard'] || config['dashboard'];
        const categoryId = qp?.['category'] || config['category'];
        if (categoryId && categoryId !== this.selectedCategoryId) {
            this.selectedCategoryId = categoryId;
        }
        if (dashboardId && !this.selectedDashboard) {
            const dashboard = this.dashboards.find(d => UUIDsEqual(d.ID, dashboardId));
            if (dashboard) {
                this.openDashboard(dashboard);
            }
        }
    }
    /**
     * Check for late-arriving query params (e.g., from pin navigation where
     * UpdateActiveTabQueryParams runs after the component has already loaded).
     * Polls briefly for queryParams to appear in the URL.
     */
    watchForLateQueryParams() {
        // Check every 200ms for up to 3 seconds for queryParams to appear
        // AND for dashboards to be loaded (both conditions must be met)
        let attempts = 0;
        const interval = setInterval(() => {
            attempts++;
            if (attempts > 15 || this.selectedDashboard) {
                clearInterval(interval);
                return;
            }
            // Re-check the URL directly since ActivatedRoute may not fire
            const url = window.location.href;
            const dashboardMatch = url.match(/[?&]dashboard=([^&]+)/);
            if (dashboardMatch && !this.selectedDashboard && this.dashboards.length > 0) {
                const dashboardId = decodeURIComponent(dashboardMatch[1]);
                const dashboard = this.dashboards.find(d => UUIDsEqual(d.ID, dashboardId));
                if (dashboard) {
                    this.openDashboard(dashboard);
                    this.cdr.detectChanges();
                    clearInterval(interval);
                }
            }
        }, 200);
    }
    // ========================================
    // Private Methods - URL Query Params
    // ========================================
    subscribeToQueryParams() {
        this.route.queryParams
            .pipe(takeUntil(this._destroy$))
            .subscribe(params => {
            const categoryId = params['category'] || null;
            const dashboardId = params['dashboard'] || null;
            // Handle category change
            if (categoryId !== this.selectedCategoryId) {
                this.selectedCategoryId = categoryId;
            }
            // Handle dashboard change (for browser back/forward)
            const currentDashboardId = this.selectedDashboard?.ID || null;
            if (dashboardId !== currentDashboardId) {
                if (dashboardId) {
                    // Find and open the dashboard
                    const dashboard = this.dashboards.find(d => UUIDsEqual(d.ID, dashboardId));
                    if (dashboard) {
                        this.selectedDashboard = dashboard;
                        this.mode = 'view';
                    }
                }
                else {
                    // Go back to list
                    this.selectedDashboard = null;
                    this.mode = 'list';
                }
            }
            this.cdr.detectChanges();
        });
    }
    /**
     * Update the URL query params for the current tab.
     * Uses NavigationService to update the tab configuration, which triggers
     * the shell's URL sync mechanism to update the browser URL properly
     * while respecting app-scoped routes.
     */
    updateUrlQueryParams() {
        const queryParams = {};
        // Track category
        if (this.selectedCategoryId) {
            queryParams['category'] = this.selectedCategoryId;
        }
        else {
            queryParams['category'] = null;
        }
        // Track dashboard (for browser back/forward support)
        if (this.selectedDashboard) {
            queryParams['dashboard'] = this.selectedDashboard.ID;
        }
        else {
            queryParams['dashboard'] = null;
        }
        // Use NavigationService to update query params properly
        // This ensures the URL update respects app-scoped routes
        this.navigationService.UpdateActiveTabQueryParams(queryParams);
    }
    // ========================================
    // Private Methods - Category Helpers
    // ========================================
    /**
     * Get all child categories of a parent category recursively
     */
    getChildCategoriesRecursive(parentId) {
        const children = [];
        const directChildren = this.categories.filter(c => UUIDsEqual(c.ParentID, parentId));
        for (const child of directChildren) {
            children.push(child);
            children.push(...this.getChildCategoriesRecursive(child.ID));
        }
        return children;
    }
    // ========================================
    // Private Methods - View Preference
    // ========================================
    loadViewPreference() {
        // TODO: Load from User Settings entity
        const stored = localStorage.getItem('dashboard-browser-view-mode');
        if (stored === 'cards' || stored === 'list') {
            this.viewMode = stored;
        }
    }
    saveViewPreference(mode) {
        // TODO: Save to User Settings entity
        localStorage.setItem('dashboard-browser-view-mode', mode);
    }
    static ɵfac = function DashboardBrowserResourceComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DashboardBrowserResourceComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.ActivatedRoute), i0.ɵɵdirectiveInject(i2.NavigationService)); };
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DashboardBrowserResourceComponent, selectors: [["mj-dashboard-browser-resource"]], viewQuery: function DashboardBrowserResourceComponent_Query(rf, ctx) { if (rf & 1) {
            i0.ɵɵviewQuery(_c0, 5);
        } if (rf & 2) {
            let _t;
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.dashboardViewer = _t.first);
        } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 3, vars: 2, consts: [["dashboardViewer", ""], [1, "dashboard-browser-resource"], [3, "Dashboards", "Categories", "SelectedCategoryId", "ViewMode", "IsLoading", "ShowCreateButton", "AllowMultiSelect", "AllowDragDrop", "DashboardPermissions", "EffectiveCategoryMap"], [3, "DashboardOpen", "DashboardEdit", "DashboardDelete", "DashboardMove", "DashboardCreate", "CategoryCreate", "CategoryDelete", "CategoryChange", "ViewPreferenceChange", "Dashboards", "Categories", "SelectedCategoryId", "ViewMode", "IsLoading", "ShowCreateButton", "AllowMultiSelect", "AllowDragDrop", "DashboardPermissions", "EffectiveCategoryMap"], [1, "viewer-toolbar"], [1, "viewer-header", "editing"], [1, "viewer-content"], [3, "panelInteraction", "navigationRequested", "dashboard", "isEditing", "showToolbar", "showBreadcrumb"], [3, "visible", "partTypes"], [3, "Saved", "Cancelled", "Visible", "PartType", "Panel", "Config"], ["type", "danger", "title", "Remove Part", "confirmText", "Remove", "cancelText", "Cancel", 3, "confirmed", "cancelled", "visible", "message"], [3, "Result", "Visible", "Dashboard"], ["Size", "large", "RootIcon", "fa-solid fa-gauge-high", "RootLabel", "Dashboards", 3, "Navigate", "Categories", "CurrentCategoryId", "CurrentDashboard", "ShowDashboardName", "AllowDragDrop"], [1, "toolbar-actions"], [1, "shared-indicator"], ["title", "Open in its own tab", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-up-right-from-square"], ["title", "Share Dashboard", 1, "btn-icon"], ["title", "Edit Dashboard", 1, "btn-icon"], [1, "fa-solid", "fa-share-nodes"], ["title", "Share Dashboard", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-user-plus"], ["title", "Edit Dashboard", 1, "btn-icon", 3, "click"], [1, "fa-solid", "fa-edit"], [1, "header-left"], [1, "btn-add-part", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "header-separator"], [1, "dashboard-info-edit"], ["type", "text", "placeholder", "Dashboard name", 1, "dashboard-name-input", 3, "ngModelChange", "blur", "ngModel"], ["type", "text", "placeholder", "Add a description...", 1, "dashboard-description-input", 3, "ngModelChange", "ngModel"], [1, "header-right"], [1, "btn-primary", 3, "click"], [1, "fa-solid", "fa-save"], [1, "btn-cancel", 3, "click"], [3, "panelAdded", "cancelled", "visible", "partTypes"]], template: function DashboardBrowserResourceComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵelementStart(0, "div", 1);
            i0.ɵɵconditionalCreate(1, DashboardBrowserResourceComponent_Conditional_1_Template, 1, 10, "mj-dashboard-browser", 2);
            i0.ɵɵconditionalCreate(2, DashboardBrowserResourceComponent_Conditional_2_Template, 9, 15);
            i0.ɵɵelementEnd();
        } if (rf & 2) {
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.mode === "list" ? 1 : -1);
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.mode === "view" || ctx.mode === "edit" ? 2 : -1);
        } }, dependencies: [i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, i4.DashboardViewerComponent, i4.DashboardBrowserComponent, i4.DashboardBreadcrumbComponent, i4.AddPanelDialogComponent, i4.EditPartDialogComponent, i4.ConfirmDialogComponent, i5.DashboardShareDialogComponent], styles: ["\n\n\n\n\n[_nghost-%COMP%] {\n    display: block;\n    height: 100%;\n    width: 100%;\n}\n\n.dashboard-browser-resource[_ngcontent-%COMP%] {\n    display: flex;\n    flex-direction: column;\n    height: 100%;\n    width: 100%;\n    background: var(--mj-bg-surface-card);\n    position: relative;\n}\n\n\n\n.dashboard-browser-resource[_ngcontent-%COMP%]   mj-dashboard-browser[_ngcontent-%COMP%] {\n    display: block;\n    height: 100%;\n    width: 100%;\n}\n\n\n\n\n\n\n.viewer-toolbar[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    padding: 0 24px 0 0;\n    background: var(--mj-bg-surface);\n    border-bottom: 1px solid var(--mj-border-default);\n    gap: 16px;\n}\n\n.viewer-toolbar[_ngcontent-%COMP%]   .toolbar-actions[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n}\n\n\n\n.shared-indicator[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    gap: 6px;\n    padding: 6px 12px;\n    background: var(--mj-bg-info);\n    border-radius: 16px;\n    font-size: 12px;\n    font-weight: 500;\n    color: var(--mj-brand-primary);\n    white-space: nowrap;\n}\n\n.shared-indicator[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n    font-size: 11px;\n}\n\n\n\n\n\n\n.viewer-header[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    padding: 12px 24px;\n    background: var(--mj-bg-surface);\n    border-bottom: 1px solid var(--mj-border-default);\n    transition: background 0.2s, border-color 0.2s;\n}\n\n\n\n.viewer-header.editing[_ngcontent-%COMP%] {\n    background: var(--mj-bg-brand);\n    border-bottom: 2px solid var(--mj-brand-primary);\n}\n\n.viewer-header[_ngcontent-%COMP%]   .header-left[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n    flex: 1;\n}\n\n.viewer-header[_ngcontent-%COMP%]   h2[_ngcontent-%COMP%] {\n    margin: 0;\n    font-size: 18px;\n    font-weight: 500;\n    color: var(--mj-text-primary);\n}\n\n.viewer-header[_ngcontent-%COMP%]   .header-right[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n}\n\n.back-btn[_ngcontent-%COMP%] {\n    width: 36px;\n    height: 36px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    border: none;\n    border-radius: 6px;\n    background: var(--mj-bg-surface-card);\n    color: var(--mj-text-secondary);\n    cursor: pointer;\n    transition: all 0.2s;\n}\n\n.back-btn[_ngcontent-%COMP%]:hover {\n    background: var(--mj-border-default);\n    color: var(--mj-text-primary);\n}\n\n\n\n.btn-add-part[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    padding: 8px 16px;\n    border: none;\n    border-radius: 6px;\n    background: var(--mj-brand-primary);\n    color: var(--mj-text-inverse);\n    font-size: 13px;\n    font-weight: 500;\n    cursor: pointer;\n    transition: background 0.2s, transform 0.1s;\n    box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.btn-add-part[_ngcontent-%COMP%]:hover {\n    background: var(--mj-brand-primary-hover);\n    transform: translateY(-1px);\n    box-shadow: 0 3px 6px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.btn-add-part[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n    font-size: 12px;\n}\n\n\n\n.header-separator[_ngcontent-%COMP%] {\n    width: 1px;\n    height: 28px;\n    background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n    margin: 0 4px;\n}\n\n\n\n\n\n\n.btn-primary[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    padding: 10px 18px;\n    border: none;\n    border-radius: 6px;\n    background: var(--mj-brand-primary);\n    color: var(--mj-text-inverse);\n    font-size: 14px;\n    font-weight: 500;\n    cursor: pointer;\n    transition: background 0.2s;\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n    background: var(--mj-brand-primary-hover);\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n    width: 36px;\n    height: 36px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    border: 1px solid var(--mj-border-default);\n    border-radius: 6px;\n    background: var(--mj-bg-surface);\n    color: var(--mj-text-secondary);\n    cursor: pointer;\n    transition: all 0.2s;\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n    background: var(--mj-bg-surface-card);\n}\n\n.btn-icon.active[_ngcontent-%COMP%] {\n    background: var(--mj-bg-info);\n    border-color: var(--mj-brand-primary);\n    color: var(--mj-brand-primary);\n}\n\n\n\n.btn-cancel[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    padding: 10px 18px;\n    border: 1px solid var(--mj-border-strong);\n    border-radius: 6px;\n    background: var(--mj-bg-surface);\n    color: var(--mj-text-secondary);\n    font-size: 14px;\n    cursor: pointer;\n    transition: all 0.2s;\n}\n\n.btn-cancel[_ngcontent-%COMP%]:hover {\n    background: var(--mj-bg-surface-card);\n    border-color: var(--mj-border-strong);\n    color: var(--mj-text-primary);\n}\n\n\n\n\n\n\n.dashboard-info-edit[_ngcontent-%COMP%] {\n    display: flex;\n    align-items: center;\n    gap: 16px;\n    flex: 1;\n}\n\n.dashboard-name-input[_ngcontent-%COMP%] {\n    border: 1px solid transparent;\n    border-radius: 4px;\n    padding: 6px 12px;\n    font-size: 16px;\n    font-weight: 500;\n    color: var(--mj-text-primary);\n    background: color-mix(in srgb, var(--mj-bg-surface) 70%, transparent);\n    outline: none;\n    min-width: 200px;\n    max-width: 300px;\n    transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;\n}\n\n.dashboard-name-input[_ngcontent-%COMP%]:hover {\n    background: color-mix(in srgb, var(--mj-bg-surface) 90%, transparent);\n}\n\n.dashboard-name-input[_ngcontent-%COMP%]:focus {\n    background: var(--mj-bg-surface);\n    border-color: var(--mj-brand-primary);\n    box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.dashboard-description-input[_ngcontent-%COMP%] {\n    border: 1px solid transparent;\n    border-radius: 4px;\n    padding: 6px 12px;\n    font-size: 13px;\n    color: var(--mj-text-secondary);\n    background: color-mix(in srgb, var(--mj-bg-surface) 50%, transparent);\n    outline: none;\n    flex: 1;\n    min-width: 150px;\n    max-width: 400px;\n    transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;\n}\n\n.dashboard-description-input[_ngcontent-%COMP%]:hover {\n    background: color-mix(in srgb, var(--mj-bg-surface) 80%, transparent);\n}\n\n.dashboard-description-input[_ngcontent-%COMP%]:focus {\n    background: var(--mj-bg-surface);\n    border-color: var(--mj-brand-primary);\n    box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.dashboard-description-input[_ngcontent-%COMP%]::placeholder {\n    color: var(--mj-text-disabled);\n    font-style: normal;\n}\n\n\n\n\n\n\n.viewer-content[_ngcontent-%COMP%] {\n    flex: 1;\n    overflow: hidden;\n    min-height: 0;\n}\n\n.viewer-content[_ngcontent-%COMP%]   mj-dashboard-viewer[_ngcontent-%COMP%] {\n    display: block;\n    width: 100%;\n    height: 100%;\n}\n\n\n\n\n\n\n@media (max-width: 768px) {\n    .viewer-header[_ngcontent-%COMP%] {\n        flex-direction: column;\n        gap: 12px;\n        align-items: stretch;\n    }\n\n    .viewer-header[_ngcontent-%COMP%]   .header-left[_ngcontent-%COMP%] {\n        flex-wrap: wrap;\n    }\n\n    .dashboard-info-edit[_ngcontent-%COMP%] {\n        flex-direction: column;\n        align-items: stretch;\n    }\n\n    .dashboard-name-input[_ngcontent-%COMP%], \n   .dashboard-description-input[_ngcontent-%COMP%] {\n        max-width: none;\n    }\n}"], changeDetection: 0 });
};
DashboardBrowserResourceComponent = __decorate([
    RegisterClass(BaseResourceComponent, 'DashboardBrowserResource')
], DashboardBrowserResourceComponent);
export { DashboardBrowserResourceComponent };
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DashboardBrowserResourceComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'mj-dashboard-browser-resource', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Dashboard Browser Resource -->\n<div class=\"dashboard-browser-resource\">\n  <!-- List Mode - Uses Generic DashboardBrowserComponent -->\n  @if (mode === 'list') {\n    <mj-dashboard-browser\n      [Dashboards]=\"dashboards\"\n      [Categories]=\"categories\"\n      [SelectedCategoryId]=\"selectedCategoryId\"\n      [ViewMode]=\"viewMode\"\n      [IsLoading]=\"isLoading\"\n      [ShowCreateButton]=\"true\"\n      [AllowMultiSelect]=\"true\"\n      [AllowDragDrop]=\"true\"\n      [DashboardPermissions]=\"dashboardPermissionsMap\"\n      [EffectiveCategoryMap]=\"effectiveCategoryMap\"\n      (DashboardOpen)=\"onDashboardOpen($event)\"\n      (DashboardEdit)=\"onDashboardEdit($event)\"\n      (DashboardDelete)=\"onDashboardDelete($event)\"\n      (DashboardMove)=\"onDashboardMove($event)\"\n      (DashboardCreate)=\"onDashboardCreate($event)\"\n      (CategoryCreate)=\"onCategoryCreate($event)\"\n      (CategoryDelete)=\"onCategoryDelete($event)\"\n      (CategoryChange)=\"onCategoryChange($event)\"\n      (ViewPreferenceChange)=\"onViewPreferenceChange($event)\">\n    </mj-dashboard-browser>\n  }\n\n  <!-- View/Edit Mode -->\n  @if (mode === 'view' || mode === 'edit') {\n    <!-- View Mode Toolbar - matches browser toolbar structure -->\n    @if (mode === 'view') {\n      <div class=\"viewer-toolbar\">\n        <!-- Breadcrumb navigation (includes its own padding/styling) -->\n        <mj-dashboard-breadcrumb\n          [Categories]=\"categories\"\n          [CurrentCategoryId]=\"selectedDashboard?.CategoryID || null\"\n          [CurrentDashboard]=\"selectedDashboard\"\n          [ShowDashboardName]=\"true\"\n          [AllowDragDrop]=\"false\"\n          Size=\"large\"\n          RootIcon=\"fa-solid fa-gauge-high\"\n          RootLabel=\"Dashboards\"\n          (Navigate)=\"onBreadcrumbNavigate($event)\">\n        </mj-dashboard-breadcrumb>\n        <!-- Right-side Actions -->\n        <div class=\"toolbar-actions\">\n          <!-- Shared indicator for non-owned dashboards -->\n          @if (!selectedDashboardPermissions.IsOwner && selectedDashboardPermissions.CanRead) {\n            <span class=\"shared-indicator\">\n              <i class=\"fa-solid fa-share-nodes\"></i>\n              Shared with you\n            </span>\n          }\n          <button\n            class=\"btn-icon\"\n            title=\"Open in its own tab\"\n            (click)=\"openInNewTab()\">\n            <i class=\"fa-solid fa-up-right-from-square\"></i>\n          </button>\n          <!-- Share button - only shown if user can share -->\n          @if (selectedDashboardPermissions.CanShare) {\n            <button\n              class=\"btn-icon\"\n              title=\"Share Dashboard\"\n              (click)=\"openShareDialog()\">\n              <i class=\"fa-solid fa-user-plus\"></i>\n            </button>\n          }\n          <!-- Edit button - only shown if user can edit -->\n          @if (selectedDashboardPermissions.CanEdit) {\n            <button\n              class=\"btn-icon\"\n              title=\"Edit Dashboard\"\n              (click)=\"toggleEditMode()\">\n              <i class=\"fa-solid fa-edit\"></i>\n            </button>\n          }\n        </div>\n      </div>\n    }\n    <!-- Edit Mode Header - different layout -->\n    @if (mode === 'edit') {\n      <div class=\"viewer-header editing\">\n        <div class=\"header-left\">\n          <!-- Add Part button on the left -->\n          <button\n            class=\"btn-add-part\"\n            (click)=\"openAddPartDialog()\">\n            <i class=\"fa-solid fa-plus\"></i>\n            Add Part\n          </button>\n          <!-- Separator -->\n          <div class=\"header-separator\"></div>\n          <!-- Editable name/description -->\n          <div class=\"dashboard-info-edit\">\n            <input\n              type=\"text\"\n              class=\"dashboard-name-input\"\n              [(ngModel)]=\"editingName\"\n              placeholder=\"Dashboard name\"\n              (blur)=\"onNameBlur()\">\n            <input\n              type=\"text\"\n              class=\"dashboard-description-input\"\n              [(ngModel)]=\"editingDescription\"\n              placeholder=\"Add a description...\">\n          </div>\n        </div>\n        <div class=\"header-right\">\n          <!-- Save, Cancel buttons -->\n          <button\n            class=\"btn-primary\"\n            (click)=\"saveDashboard()\">\n            <i class=\"fa-solid fa-save\"></i>\n            Save\n          </button>\n          <button\n            class=\"btn-cancel\"\n            (click)=\"cancelEdit()\">\n            Cancel\n          </button>\n        </div>\n      </div>\n    }\n    <!-- Dashboard Viewer -->\n    <div class=\"viewer-content\">\n      <mj-dashboard-viewer\n        #dashboardViewer\n        [dashboard]=\"selectedDashboard\"\n        [isEditing]=\"mode === 'edit'\"\n        [showToolbar]=\"false\"\n        [showBreadcrumb]=\"false\"\n        (panelInteraction)=\"onPanelInteraction($event)\"\n        (navigationRequested)=\"onNavigationRequested($event)\">\n      </mj-dashboard-viewer>\n    </div>\n    <!-- Add Panel Dialog -->\n    @if (dashboardViewer) {\n      <mj-add-panel-dialog\n        [visible]=\"showAddPanelDialog\"\n        [partTypes]=\"dashboardViewer.getPartTypes()\"\n        (panelAdded)=\"onPanelAdded($event)\"\n        (cancelled)=\"onAddPanelCancelled()\">\n      </mj-add-panel-dialog>\n    }\n    <!-- Generic Edit Part Dialog - dynamically loads config panels via ClassFactory -->\n    <mj-edit-part-dialog\n      [Visible]=\"showConfigDialog\"\n      [PartType]=\"configDialogPartType\"\n      [Panel]=\"configDialogPanel\"\n      [Config]=\"configDialogPanel?.config || null\"\n      (Saved)=\"onConfigDialogSaved($event)\"\n      (Cancelled)=\"onConfigDialogCancelled()\">\n    </mj-edit-part-dialog>\n    <!-- Remove Part Confirmation Dialog -->\n    <mj-confirm-dialog\n      [visible]=\"showConfirmDialog\"\n      type=\"danger\"\n      title=\"Remove Part\"\n      [message]=\"'Are you sure you want to remove \\'' + confirmPanelTitle + '\\' from this dashboard?'\"\n      confirmText=\"Remove\"\n      cancelText=\"Cancel\"\n      (confirmed)=\"onRemoveConfirmed()\"\n      (cancelled)=\"onRemoveCancelled()\">\n    </mj-confirm-dialog>\n    <!-- Share Dashboard Dialog -->\n    <mj-dashboard-share-dialog\n      [Visible]=\"showShareDialog\"\n      [Dashboard]=\"selectedDashboard\"\n      (Result)=\"onShareDialogResult($event)\">\n    </mj-dashboard-share-dialog>\n  }\n</div>\n", styles: ["/* Dashboard Browser Resource Styles */\n/* This is a thin wrapper - list mode styles are in the generic DashboardBrowserComponent */\n\n:host {\n    display: block;\n    height: 100%;\n    width: 100%;\n}\n\n.dashboard-browser-resource {\n    display: flex;\n    flex-direction: column;\n    height: 100%;\n    width: 100%;\n    background: var(--mj-bg-surface-card);\n    position: relative;\n}\n\n/* Generic browser fills the container in list mode */\n.dashboard-browser-resource mj-dashboard-browser {\n    display: block;\n    height: 100%;\n    width: 100%;\n}\n\n/* ========================================\n   Viewer Toolbar (View Mode) - Matches Browser Toolbar\n   ======================================== */\n\n.viewer-toolbar {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    padding: 0 24px 0 0;\n    background: var(--mj-bg-surface);\n    border-bottom: 1px solid var(--mj-border-default);\n    gap: 16px;\n}\n\n.viewer-toolbar .toolbar-actions {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n}\n\n/* Shared with you indicator */\n.shared-indicator {\n    display: flex;\n    align-items: center;\n    gap: 6px;\n    padding: 6px 12px;\n    background: var(--mj-bg-info);\n    border-radius: 16px;\n    font-size: 12px;\n    font-weight: 500;\n    color: var(--mj-brand-primary);\n    white-space: nowrap;\n}\n\n.shared-indicator i {\n    font-size: 11px;\n}\n\n/* ========================================\n   Viewer Header (Edit Mode)\n   ======================================== */\n\n.viewer-header {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    padding: 12px 24px;\n    background: var(--mj-bg-surface);\n    border-bottom: 1px solid var(--mj-border-default);\n    transition: background 0.2s, border-color 0.2s;\n}\n\n/* Edit mode header styling */\n.viewer-header.editing {\n    background: var(--mj-bg-brand);\n    border-bottom: 2px solid var(--mj-brand-primary);\n}\n\n.viewer-header .header-left {\n    display: flex;\n    align-items: center;\n    gap: 12px;\n    flex: 1;\n}\n\n.viewer-header h2 {\n    margin: 0;\n    font-size: 18px;\n    font-weight: 500;\n    color: var(--mj-text-primary);\n}\n\n.viewer-header .header-right {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n}\n\n.back-btn {\n    width: 36px;\n    height: 36px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    border: none;\n    border-radius: 6px;\n    background: var(--mj-bg-surface-card);\n    color: var(--mj-text-secondary);\n    cursor: pointer;\n    transition: all 0.2s;\n}\n\n.back-btn:hover {\n    background: var(--mj-border-default);\n    color: var(--mj-text-primary);\n}\n\n/* Add Part button (left side in edit mode) */\n.btn-add-part {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    padding: 8px 16px;\n    border: none;\n    border-radius: 6px;\n    background: var(--mj-brand-primary);\n    color: var(--mj-text-inverse);\n    font-size: 13px;\n    font-weight: 500;\n    cursor: pointer;\n    transition: background 0.2s, transform 0.1s;\n    box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.btn-add-part:hover {\n    background: var(--mj-brand-primary-hover);\n    transform: translateY(-1px);\n    box-shadow: 0 3px 6px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.btn-add-part i {\n    font-size: 12px;\n}\n\n/* Header separator */\n.header-separator {\n    width: 1px;\n    height: 28px;\n    background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n    margin: 0 4px;\n}\n\n/* ========================================\n   Buttons\n   ======================================== */\n\n.btn-primary {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    padding: 10px 18px;\n    border: none;\n    border-radius: 6px;\n    background: var(--mj-brand-primary);\n    color: var(--mj-text-inverse);\n    font-size: 14px;\n    font-weight: 500;\n    cursor: pointer;\n    transition: background 0.2s;\n}\n\n.btn-primary:hover {\n    background: var(--mj-brand-primary-hover);\n}\n\n.btn-icon {\n    width: 36px;\n    height: 36px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    border: 1px solid var(--mj-border-default);\n    border-radius: 6px;\n    background: var(--mj-bg-surface);\n    color: var(--mj-text-secondary);\n    cursor: pointer;\n    transition: all 0.2s;\n}\n\n.btn-icon:hover {\n    background: var(--mj-bg-surface-card);\n}\n\n.btn-icon.active {\n    background: var(--mj-bg-info);\n    border-color: var(--mj-brand-primary);\n    color: var(--mj-brand-primary);\n}\n\n/* Cancel button styling */\n.btn-cancel {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    padding: 10px 18px;\n    border: 1px solid var(--mj-border-strong);\n    border-radius: 6px;\n    background: var(--mj-bg-surface);\n    color: var(--mj-text-secondary);\n    font-size: 14px;\n    cursor: pointer;\n    transition: all 0.2s;\n}\n\n.btn-cancel:hover {\n    background: var(--mj-bg-surface-card);\n    border-color: var(--mj-border-strong);\n    color: var(--mj-text-primary);\n}\n\n/* ========================================\n   Dashboard Info Edit (Edit Mode)\n   ======================================== */\n\n.dashboard-info-edit {\n    display: flex;\n    align-items: center;\n    gap: 16px;\n    flex: 1;\n}\n\n.dashboard-name-input {\n    border: 1px solid transparent;\n    border-radius: 4px;\n    padding: 6px 12px;\n    font-size: 16px;\n    font-weight: 500;\n    color: var(--mj-text-primary);\n    background: color-mix(in srgb, var(--mj-bg-surface) 70%, transparent);\n    outline: none;\n    min-width: 200px;\n    max-width: 300px;\n    transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;\n}\n\n.dashboard-name-input:hover {\n    background: color-mix(in srgb, var(--mj-bg-surface) 90%, transparent);\n}\n\n.dashboard-name-input:focus {\n    background: var(--mj-bg-surface);\n    border-color: var(--mj-brand-primary);\n    box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.dashboard-description-input {\n    border: 1px solid transparent;\n    border-radius: 4px;\n    padding: 6px 12px;\n    font-size: 13px;\n    color: var(--mj-text-secondary);\n    background: color-mix(in srgb, var(--mj-bg-surface) 50%, transparent);\n    outline: none;\n    flex: 1;\n    min-width: 150px;\n    max-width: 400px;\n    transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;\n}\n\n.dashboard-description-input:hover {\n    background: color-mix(in srgb, var(--mj-bg-surface) 80%, transparent);\n}\n\n.dashboard-description-input:focus {\n    background: var(--mj-bg-surface);\n    border-color: var(--mj-brand-primary);\n    box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.dashboard-description-input::placeholder {\n    color: var(--mj-text-disabled);\n    font-style: normal;\n}\n\n/* ========================================\n   Viewer Content\n   ======================================== */\n\n.viewer-content {\n    flex: 1;\n    overflow: hidden;\n    min-height: 0;\n}\n\n.viewer-content mj-dashboard-viewer {\n    display: block;\n    width: 100%;\n    height: 100%;\n}\n\n/* ========================================\n   Responsive\n   ======================================== */\n\n@media (max-width: 768px) {\n    .viewer-header {\n        flex-direction: column;\n        gap: 12px;\n        align-items: stretch;\n    }\n\n    .viewer-header .header-left {\n        flex-wrap: wrap;\n    }\n\n    .dashboard-info-edit {\n        flex-direction: column;\n        align-items: stretch;\n    }\n\n    .dashboard-name-input,\n    .dashboard-description-input {\n        max-width: none;\n    }\n}\n"] }]
    }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.ActivatedRoute }, { type: i2.NavigationService }], { dashboardViewer: [{
            type: ViewChild,
            args: ['dashboardViewer']
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DashboardBrowserResourceComponent, { className: "DashboardBrowserResourceComponent", filePath: "src/DashboardBrowser/dashboard-browser-resource.component.ts", lineNumber: 49 }); })();
//# sourceMappingURL=dashboard-browser-resource.component.js.map