Initial editor support.

This commit is contained in:
Dermot Duffy
2022-01-14 21:31:16 -08:00
parent b03c8b4020
commit c40c63862e
10 changed files with 417 additions and 120 deletions
+105 -28
View File
@@ -1,14 +1,16 @@
import delve from 'dlv';
import { dset } from 'dset';
import {
CONF_CAMERAS,
CONF_CAMERAS_ARRAY_CAMERA_ENTITY,
CONF_CAMERAS_ARRAY_CAMERA_NAME,
CONF_CAMERAS_ARRAY_CLIENT_ID,
CONF_CAMERAS_ARRAY_LABEL,
CONF_CAMERAS_ARRAY_URL,
CONF_CAMERAS_ARRAY_ZONE,
CONF_EVENT_VIEWER_AUTOPLAY_CLIP,
CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE,
CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE,
CONF_FRIGATE_CAMERA_NAME,
CONF_FRIGATE_CLIENT_ID,
CONF_FRIGATE_LABEL,
CONF_FRIGATE_URL,
CONF_FRIGATE_ZONE,
CONF_IMAGE_SRC,
CONF_LIVE_PRELOAD,
CONF_LIVE_PROVIDER,
@@ -18,7 +20,7 @@ import {
CONF_VIEW_TIMEOUT,
CONF_VIEW_UPDATE_ENTITIES,
} from './const';
import { RawFrigateCardConfig } from './types';
import { RawFrigateCardConfig, RawFrigateCardConfigArray } from './types';
/**
* Set a configuration value.
@@ -26,12 +28,13 @@ import { RawFrigateCardConfig } from './types';
* @param key The key to the property to set.
* @param value The value to set.
*/
export const setConfigValue = (
obj: RawFrigateCardConfig,
key: string,
keys: string | (string|number)[],
value: unknown,
): void => {
dset(obj, key, value);
dset(obj, keys, value);
};
/**
@@ -42,10 +45,14 @@ export const setConfigValue = (
*/
export const getConfigValue = (
obj: RawFrigateCardConfig,
key: string,
keys: string | (string|number)[],
def?: unknown,
): unknown => {
return delve(obj, key, def);
// Need to manually split the key apart to use delve array accesses by number.
if (typeof(keys) === 'string') {
keys = keys.split('.');
}
return delve(obj, keys, def);
};
/**
@@ -93,19 +100,23 @@ export const isConfigUpgradeable = function (obj: RawFrigateCardConfig): boolean
/**
* Remove empty sections from a configuration.
* @param obj Configuration object.
* @returns `true` if the configuration was modified.
*/
export const trimConfig = function (obj: RawFrigateCardConfig): void {
export const trimConfig = function (obj: RawFrigateCardConfig): boolean {
const keys = Object.keys(obj);
let modified = false;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (typeof obj[key] === 'object' && obj[key] != null) {
trimConfig(obj[key] as RawFrigateCardConfig);
modified ||= trimConfig(obj[key] as RawFrigateCardConfig);
if (!Object.keys(obj[key] as RawFrigateCardConfig).length) {
delete obj[key];
modified = true;
}
}
}
return modified;
};
/**
@@ -128,6 +139,32 @@ const isNotObject = function (value: unknown) {
/**
* Move a property from one location to another.
* @param obj The configuration object in which the property resides.
* @param oldPath The old property path.
* @param newPath The new property path.
* @param transform An optional transform for the value.
* @returns `true` if the configuration was modified.
*/
export const moveConfigValue = (
obj: RawFrigateCardConfig,
oldPath: string,
newPath: string,
transform?: (valueIn: unknown) => (unknown),
): boolean => {
let value = getConfigValue(obj, oldPath);
if (transform) {
value = transform(value);
}
if (typeof value !== 'undefined') {
deleteConfigValue(obj, oldPath);
setConfigValue(obj, newPath, value);
return true;
}
return false;
};
/**
* Upgrade by moving a property from one location to another.
* @param oldPath The old property path.
* @param newPath The new property path.
* @param transform An optional transform for the value.
@@ -136,29 +173,66 @@ const isNotObject = function (value: unknown) {
const upgradeMoveTo = function (
oldPath: string,
newPath: string,
transform?: (valueIn: unknown) => unknown,
transform?: (valueIn: unknown) => (unknown),
): (obj: RawFrigateCardConfig) => boolean {
return function (obj: RawFrigateCardConfig): boolean {
let value = getConfigValue(obj, oldPath);
if (transform) {
value = transform(value);
}
if (typeof value !== 'undefined') {
deleteConfigValue(obj, oldPath);
setConfigValue(obj, newPath, value);
return true;
}
return false;
return moveConfigValue(obj, oldPath, newPath, transform);
};
};
/**
* Sanitize a potentially-unsafe key segment.
* @param key A string key.
* @returns A safe key.
*/
// const sanitizeKeySegment = (key: string): string => {
// return key.replace(/\.+/g, '_');
// }
const upgradeToMultipleCameras = (): ((obj: RawFrigateCardConfig) => boolean) => {
return function (obj: RawFrigateCardConfig): boolean {
let modified = false;
const camera = {}
const imports = {
'camera_entity': CONF_CAMERAS_ARRAY_CAMERA_ENTITY,
'frigate.camera_name': CONF_CAMERAS_ARRAY_CAMERA_NAME,
'frigate.client_id': CONF_CAMERAS_ARRAY_CLIENT_ID,
'frigate.label': CONF_CAMERAS_ARRAY_LABEL,
'frigate.url': CONF_CAMERAS_ARRAY_URL,
'frigate.zone': CONF_CAMERAS_ARRAY_ZONE,
}
Object.keys(imports).forEach((key) => {
const oldValue = getConfigValue(obj, key);
if (oldValue !== undefined) {
camera[imports[key]] = oldValue;
deleteConfigValue(obj, key)
modified = true;
}
})
if (modified) {
let cameras = getConfigValue(obj, CONF_CAMERAS) as RawFrigateCardConfigArray;
if (!Array.isArray(cameras)) {
// Note: This will replace `cameras` if it already exists and isn't an
// array.
cameras = []
}
cameras.push(camera);
setConfigValue(obj, CONF_CAMERAS, cameras)
trimConfig(obj);
}
return modified;
}
}
const UPGRADES = [
// v1.2.1 -> v2.0.0
upgradeMoveTo('frigate_url', CONF_FRIGATE_URL),
upgradeMoveTo('frigate_client_id', CONF_FRIGATE_CLIENT_ID),
upgradeMoveTo('frigate_camera_name', CONF_FRIGATE_CAMERA_NAME),
upgradeMoveTo('label', CONF_FRIGATE_LABEL),
upgradeMoveTo('zone', CONF_FRIGATE_ZONE),
upgradeMoveTo('frigate_url', 'frigate.url'),
upgradeMoveTo('frigate_client_id', 'frigate.client_id'),
upgradeMoveTo('frigate_camera_name', 'frigate.camera_name'),
upgradeMoveTo('label', 'frigate.label'),
upgradeMoveTo('zone', 'frigate.zone'),
upgradeMoveTo('view_default', CONF_VIEW_DEFAULT),
upgradeMoveTo('view_timeout', CONF_VIEW_TIMEOUT),
upgradeMoveTo('live_provider', CONF_LIVE_PROVIDER),
@@ -174,4 +248,7 @@ const UPGRADES = [
// v2.0.0 -> v2.1.0
upgradeMoveTo('update_entities', CONF_VIEW_UPDATE_ENTITIES),
// v2.1.0 -> v3.0.0
upgradeToMultipleCameras(),
];