@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
169 lines (166 loc) • 7.67 kB
TypeScript
import * as _angular_core from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { InventoryService } from '@c8y/client';
/**
* Dashboard structure with embedded state at the c8y_Dashboard.dashboardState path.
*
* This interface defines the standard Cumulocity dashboard structure where custom
* state is stored in the c8y_Dashboard.dashboardState property. The actual state
* type is generic to support different dashboard implementations.
*
* @typeParam StateType - The type of state object stored in dashboardState
*/
interface DashboardWithState<StateType> {
/** Cumulocity dashboard configuration containing state and other dashboard properties */
c8y_Dashboard?: {
/** Custom state object specific to this dashboard's context */
dashboardState?: StateType;
[key: string]: any;
};
[key: string]: any;
}
/**
* Manages dashboard-level state with dirty tracking and persistence capabilities.
*
* This service provides a centralized state management system for context-aware dashboards.
* It tracks the original (default) state from the dashboard configuration, maintains a
* working copy of the state, and determines when changes need to be saved based on deep
* equality comparison.
*
* **Key responsibilities:**
* - Extract and store the dashboard's default state on selection
* - Maintain a mutable working state (globalState) that can be updated
* - Track whether current state differs from default (dirty tracking)
* - Enable/disable save functionality based on state changes
* - Persist state changes back to the dashboard via inventory API
*
* @typeParam StateType - The type of state object managed by this service
*
* @example
* ```ts
* // Dashboard with global time context state
* interface TimeContextState {
* dateFrom: string;
* dateTo: string;
* interval: string;
* }
*
* const stateService = inject(ContextDashboardStateService<TimeContextState>);
*
* // Set dashboard and extract its default state
* stateService.setSelectedDashboard(dashboard);
*
* // Update state (triggers dirty tracking)
* stateService.updateGlobalState({ dateFrom: '2024-01-01' });
*
* // Check if save is needed
* stateService.isSaveDisabled.subscribe(disabled => {
* if (!disabled) {
* // Save button enabled - state has changed
* }
* });
* ```
*/
declare class ContextDashboardStateService<StateType extends object> {
/** Currently selected dashboard object with its embedded state */
readonly selectedDashboard: _angular_core.WritableSignal<DashboardWithState<StateType>>;
/** Immutable snapshot of the dashboard's original state, used for comparison */
readonly dashboardDefaultState: _angular_core.WritableSignal<StateType>;
/** Current working state that can be modified, separate from the default state */
readonly globalState: _angular_core.WritableSignal<StateType>;
/** Observable for dashboard selection changes (legacy support) */
readonly selected$: BehaviorSubject<DashboardWithState<StateType>>;
/** Observable indicating whether save should be disabled (true when no changes detected) */
readonly isSaveDisabled: BehaviorSubject<boolean>;
/** Observable emitting the dashboard object after successful save operations */
readonly dashboardSaved: BehaviorSubject<any>;
readonly inventory: InventoryService;
/**
* Selects a dashboard and initializes state management for it.
*
* This method performs the complete initialization workflow when a dashboard is selected:
* 1. Extracts the dashboard's embedded state from c8y_Dashboard.dashboardState
* 2. Creates an immutable snapshot as the default state (for dirty tracking)
* 3. Creates a working copy as the current global state (for modifications)
* 4. Resets the save button state to disabled (no changes yet)
*
* **Deep cloning strategy:**
* Both default state and global state are deep cloned to ensure complete isolation.
* This prevents accidental mutations from affecting the comparison baseline.
*
* **Null handling:**
* When null/undefined is passed, all state is cleared and signals/observables are reset.
*
* @param dashboard - Dashboard object containing state at c8y_Dashboard.dashboardState,
* or null to clear the selection
*/
setSelectedDashboard(dashboard: DashboardWithState<StateType>): void;
/**
* Extracts state from the standard dashboard structure.
*
* Retrieves the state object stored at the conventional path:
* `dashboard.c8y_Dashboard.dashboardState`
*
* @param dashboard - Dashboard object with potential state at c8y_Dashboard.dashboardState
* @returns Extracted state object, or null if dashboard is null or has no state
*/
extractStateFromDashboard(dashboard: DashboardWithState<StateType> | null): StateType | null;
/**
* Merges partial state updates into the current working state with dirty tracking.
*
* This method applies partial updates to the global state using a shallow merge strategy,
* then performs deep equality comparison against the default state to determine if save
* should be enabled.
*
* @param newState - Partial state object with properties to merge into current state
*
* @example
* ```ts
* // Initial state: { dateFrom: '2024-01-01', dateTo: '2024-01-02' }
* stateService.updateGlobalState({ dateFrom: '2024-02-01' });
* // Result: { dateFrom: '2024-02-01', dateTo: '2024-01-02' }
* // isSaveDisabled = false (changed from default)
* ```
*/
updateGlobalState(newState: Partial<StateType>): void;
/**
* Returns a deep clone of the current working state.
*
* The returned object is a deep copy, so modifications won't affect the internal state.
* Use this when you need to read state without risking accidental mutations.
*
* @returns Deep cloned copy of current state, or null if no state exists
*/
getGlobalState(): StateType | null;
/**
* Reverts the working state back to the dashboard's original default state.
*
* This effectively discards all changes made since the dashboard was selected,
* resetting to the state that was extracted from c8y_Dashboard.dashboardState.
* Also disables the save button since state now matches the default.
*
* **Use case:**
* Called when user clicks "Cancel" or "Reset" to discard unsaved changes.
*/
resetGlobalState(): void;
/**
* Persists state changes to the dashboard via the Cumulocity inventory API.
*
* Updates the dashboard's c8y_Dashboard.dashboardState property with the provided
* state object and saves it to the backend. Creates the c8y_Dashboard object if
* it doesn't exist.
*
* **Note:** This method doesn't automatically update the local signals. After a
* successful save, you should emit to dashboardSaved to notify listeners.
*
* @param mo - Managed object (dashboard) to update
* @param state - State object to persist to c8y_Dashboard.dashboardState
* @returns Promise resolving to the updated dashboard object from the API
* @throws Error if the inventory update fails
*/
saveDashboardState(mo: any, state: Record<string, any>): Promise<any>;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContextDashboardStateService<any>, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<ContextDashboardStateService<any>>;
}
export { ContextDashboardStateService };
//# sourceMappingURL=index.d.ts.map