From 1f41781a847a565174f0b4ef8b0fefa496456296 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Tue, 14 Oct 2025 07:37:50 -0700 Subject: [PATCH] feat: Add custom `reload` action to reload dashboard (#2217) - Closes: #2215 --------- Co-authored-by: Felipe Santos --- docs/configuration/actions/custom/README.md | 15 ++++++++++ src/card-controller/actions/actions/reload.ts | 11 +++++++ src/card-controller/actions/factory.ts | 3 ++ src/config/schema/actions/custom/general.ts | 1 + .../actions/actions/reload.test.ts | 29 +++++++++++++++++++ tests/card-controller/actions/factory.test.ts | 2 ++ 6 files changed, 61 insertions(+) create mode 100644 src/card-controller/actions/actions/reload.ts create mode 100644 tests/card-controller/actions/actions/reload.test.ts diff --git a/docs/configuration/actions/custom/README.md b/docs/configuration/actions/custom/README.md index cda0e199..be269947 100644 --- a/docs/configuration/actions/custom/README.md +++ b/docs/configuration/actions/custom/README.md @@ -434,6 +434,15 @@ action: custom:advanced-camera-card-action advanced_camera_card_action: recordings ``` +## `reload` + +Reload the entire dashboard. + +```yaml +action: custom:advanced-camera-card-action +advanced_camera_card_action: reload +``` + ## `screenshot` Take a screenshot of the selected media (e.g. a still from a video). @@ -854,4 +863,10 @@ elements: - action: custom:advanced-camera-card-action advanced_camera_card_action: folders folder: my-folder + - type: custom:advanced-camera-card-menu-icon + icon: mdi:reload + title: Reload + tap_action: + - action: custom:advanced-camera-card-action + advanced_camera_card_action: reload ``` diff --git a/src/card-controller/actions/actions/reload.ts b/src/card-controller/actions/actions/reload.ts new file mode 100644 index 00000000..b66a8701 --- /dev/null +++ b/src/card-controller/actions/actions/reload.ts @@ -0,0 +1,11 @@ +import { GeneralActionConfig } from '../../../config/schema/actions/custom/general'; +import { CardActionsAPI } from '../../types'; +import { AdvancedCameraCardAction } from './base'; + +export class ReloadAction extends AdvancedCameraCardAction { + public async execute(api: CardActionsAPI): Promise { + await super.execute(api); + + window.location.reload(); + } +} diff --git a/src/card-controller/actions/factory.ts b/src/card-controller/actions/factory.ts index 64860d3a..7194ba57 100644 --- a/src/card-controller/actions/factory.ts +++ b/src/card-controller/actions/factory.ts @@ -30,6 +30,7 @@ import { PTZAction } from './actions/ptz'; import { PTZControlsAction } from './actions/ptz-controls'; import { PTZDigitalAction } from './actions/ptz-digital'; import { PTZMultiAction } from './actions/ptz-multi'; +import { ReloadAction } from './actions/reload'; import { ScreenshotAction } from './actions/screenshot'; import { SleepAction } from './actions/sleep'; import { StatusBarAction } from './actions/status-bar'; @@ -150,6 +151,8 @@ export class ActionFactory { return new LogAction(context, action, options?.config); case 'status_bar': return new StatusBarAction(context, action, options?.config); + case 'reload': + return new ReloadAction(context, action, options?.config); case INTERNAL_CALLBACK_ACTION: return new InternalCallbackAction(context, action, options?.config); } diff --git a/src/config/schema/actions/custom/general.ts b/src/config/schema/actions/custom/general.ts index 1cf9b914..1ed41d86 100644 --- a/src/config/schema/actions/custom/general.ts +++ b/src/config/schema/actions/custom/general.ts @@ -17,6 +17,7 @@ const GENERAL_ACTIONS = [ 'mute', 'pause', 'play', + 'reload', 'screenshot', 'unmute', ] as const; diff --git a/tests/card-controller/actions/actions/reload.test.ts b/tests/card-controller/actions/actions/reload.test.ts new file mode 100644 index 00000000..a761317e --- /dev/null +++ b/tests/card-controller/actions/actions/reload.test.ts @@ -0,0 +1,29 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { mock } from 'vitest-mock-extended'; +import { ReloadAction } from '../../../../src/card-controller/actions/actions/reload'; +import { createCardAPI } from '../../../test-utils'; + +// @vitest-environment jsdom +describe('should handle reload action', async () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should handle reload action', async () => { + const api = createCardAPI(); + const action = new ReloadAction( + {}, + { + action: 'fire-dom-event', + advanced_camera_card_action: 'reload', + }, + ); + + const location: Location & { origin: string } = mock(); + vi.spyOn(window, 'location', 'get').mockReturnValue(location); + + await action.execute(api); + + expect(location.reload).toBeCalledTimes(1); + }); +}); diff --git a/tests/card-controller/actions/factory.test.ts b/tests/card-controller/actions/factory.test.ts index 3703e944..2699a745 100644 --- a/tests/card-controller/actions/factory.test.ts +++ b/tests/card-controller/actions/factory.test.ts @@ -27,6 +27,7 @@ import { PTZAction } from '../../../src/card-controller/actions/actions/ptz'; import { PTZControlsAction } from '../../../src/card-controller/actions/actions/ptz-controls'; import { PTZDigitalAction } from '../../../src/card-controller/actions/actions/ptz-digital'; import { PTZMultiAction } from '../../../src/card-controller/actions/actions/ptz-multi'; +import { ReloadAction } from '../../../src/card-controller/actions/actions/reload'; import { ScreenshotAction } from '../../../src/card-controller/actions/actions/screenshot'; import { SleepAction } from '../../../src/card-controller/actions/actions/sleep'; import { StatusBarAction } from '../../../src/card-controller/actions/actions/status-bar'; @@ -186,6 +187,7 @@ describe('ActionFactory', () => { }, InternalCallbackAction, ], + [{ advanced_camera_card_action: 'reload' as const }, ReloadAction], ])( 'advanced_camera_card_action: $advanced_camera_card_action', (action: Partial, classObject: object) => {