From e804e62e6698afa862721498ff5c34b347fe0601 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 27 Jun 2019 16:17:32 -0700 Subject: [PATCH] Add advanced mode (#3298) * Add advanced mode * Move advanced mode to profile * Add promo for advanced mode --- src/data/collection.ts | 74 ++++++++++ src/data/frontend.ts | 39 ++++- src/data/translation.ts | 4 +- src/panels/config/core/ha-config-core.js | 2 + .../config/core/ha-config-section-core.js | 139 +++++++++--------- .../config/dashboard/ha-config-dashboard.js | 21 ++- .../config/dashboard/ha-config-navigation.js | 87 ----------- .../config/dashboard/ha-config-navigation.ts | 82 +++++++++++ src/panels/config/ha-panel-config.ts | 18 ++- src/panels/profile/ha-advanced-mode-card.ts | 65 ++++++++ src/panels/profile/ha-panel-profile.js | 23 +++ src/state/translations-mixin.ts | 8 +- src/util/hass-translation.ts | 4 +- 13 files changed, 393 insertions(+), 173 deletions(-) create mode 100644 src/data/collection.ts delete mode 100644 src/panels/config/dashboard/ha-config-navigation.js create mode 100644 src/panels/config/dashboard/ha-config-navigation.ts create mode 100644 src/panels/profile/ha-advanced-mode-card.ts diff --git a/src/data/collection.ts b/src/data/collection.ts new file mode 100644 index 0000000000..a565d371f0 --- /dev/null +++ b/src/data/collection.ts @@ -0,0 +1,74 @@ +import { + Collection, + Connection, + getCollection, + UnsubscribeFunc, +} from "home-assistant-js-websocket"; +import { Store } from "home-assistant-js-websocket/dist/store"; + +interface OptimisticCollection extends Collection { + save(data: T): Promise; +} + +/** + * Create an optimistic collection that includes a save function. + * When the collection is saved, the collection is optimistically updated. + * The update is reversed when the update failed. + */ + +export const getOptimisticCollection = ( + saveCollection: (conn: Connection, data: StateType) => Promise, + conn: Connection, + key: string, + fetchCollection: (conn: Connection) => Promise, + subscribeUpdates?: ( + conn: Connection, + store: Store + ) => Promise +): OptimisticCollection => { + const updateKey = `${key}-optimistic`; + + const collection = getCollection( + conn, + key, + fetchCollection, + async (_conn, store) => { + // Subscribe to original updates + const subUpResult = subscribeUpdates + ? subscribeUpdates(conn, store) + : undefined; + // Store the store + conn[updateKey] = store; + + // Unsub function to undo both + return () => { + if (subUpResult) { + subUpResult.then((unsub) => unsub()); + } + conn[updateKey] = undefined; + }; + } + ); + return { + ...collection, + async save(data: StateType) { + const store: Store | undefined = conn[updateKey]; + let current; + + // Can be undefined if currently no subscribers + if (store) { + current = store.state; + store.setState(data, true); + } + + try { + return await saveCollection(conn, data); + } catch (err) { + if (store) { + store.setState(current as any, true); + } + throw err; + } + }, + }; +}; diff --git a/src/data/frontend.ts b/src/data/frontend.ts index 71c60d670f..83a2db1ac7 100644 --- a/src/data/frontend.ts +++ b/src/data/frontend.ts @@ -1,8 +1,14 @@ -import { HomeAssistant } from "../types"; +import { Connection } from "home-assistant-js-websocket"; +import { getOptimisticCollection } from "./collection"; + +export interface CoreFrontendUserData { + showAdvanced?: boolean; +} declare global { - // tslint:disable-next-line - interface FrontendUserData {} + interface FrontendUserData { + core: CoreFrontendUserData; + } } export type ValidUserDataKey = keyof FrontendUserData; @@ -10,10 +16,10 @@ export type ValidUserDataKey = keyof FrontendUserData; export const fetchFrontendUserData = async < UserDataKey extends ValidUserDataKey >( - hass: HomeAssistant, + conn: Connection, key: UserDataKey ): Promise => { - const result = await hass.callWS<{ + const result = await conn.sendMessagePromise<{ value: FrontendUserData[UserDataKey] | null; }>({ type: "frontend/get_user_data", @@ -25,12 +31,31 @@ export const fetchFrontendUserData = async < export const saveFrontendUserData = async < UserDataKey extends ValidUserDataKey >( - hass: HomeAssistant, + conn: Connection, key: UserDataKey, value: FrontendUserData[UserDataKey] ): Promise => - hass.callWS({ + conn.sendMessagePromise({ type: "frontend/set_user_data", key, value, }); + +export const getOptimisticFrontendUserDataCollection = < + UserDataKey extends ValidUserDataKey +>( + conn: Connection, + userDataKey: UserDataKey +) => + getOptimisticCollection( + (_conn, data) => + saveFrontendUserData( + conn, + userDataKey, + // @ts-ignore + data + ), + conn, + `_frontendUserData-${userDataKey}`, + () => fetchFrontendUserData(conn, userDataKey) + ); diff --git a/src/data/translation.ts b/src/data/translation.ts index 122ce344bd..f2ce1a7c1a 100644 --- a/src/data/translation.ts +++ b/src/data/translation.ts @@ -12,12 +12,12 @@ declare global { } export const fetchTranslationPreferences = (hass: HomeAssistant) => - fetchFrontendUserData(hass, "language"); + fetchFrontendUserData(hass.connection, "language"); export const saveTranslationPreferences = ( hass: HomeAssistant, data: FrontendTranslationData -) => saveFrontendUserData(hass, "language", data); +) => saveFrontendUserData(hass.connection, "language", data); export const getHassTranslations = async ( hass: HomeAssistant, diff --git a/src/panels/config/core/ha-config-core.js b/src/panels/config/core/ha-config-core.js index c53f7e9b6e..bcc71ca824 100644 --- a/src/panels/config/core/ha-config-core.js +++ b/src/panels/config/core/ha-config-core.js @@ -37,6 +37,7 @@ class HaConfigCore extends LocalizeMixin(PolymerElement) {
@@ -48,6 +49,7 @@ class HaConfigCore extends LocalizeMixin(PolymerElement) { return { hass: Object, isWide: Boolean, + showAdvanced: Boolean, }; } diff --git a/src/panels/config/core/ha-config-section-core.js b/src/panels/config/core/ha-config-section-core.js index 9b55d253a0..74cb573073 100644 --- a/src/panels/config/core/ha-config-section-core.js +++ b/src/panels/config/core/ha-config-section-core.js @@ -63,79 +63,80 @@ class HaConfigSectionCore extends LocalizeMixin(PolymerElement) { - -
- [[localize('ui.panel.config.core.section.core.validation.introduction')]] -