Initial editor support.
This commit is contained in:
+105
-28
@@ -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(),
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user