mirror of
https://github.com/home-assistant/frontend.git
synced 2026-10-22 05:34:15 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
638bd6d740 | ||
|
|
3c2acdb1a2 | ||
|
|
328629441b |
No files matched your search
@@ -0,0 +1,153 @@
|
||||
import type { ContextType } from "@lit/context";
|
||||
import { mdiAutoFix, mdiContentPaste, mdiViewGridPlusOutline } from "@mdi/js";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import deepClone from "deep-clone-simple";
|
||||
import { consume } from "../../../../common/decorators/consume";
|
||||
import { storage } from "../../../../common/decorators/storage";
|
||||
import "../../../../components/ha-adaptive-dialog";
|
||||
import "../../../../components/ha-icon-next";
|
||||
import "../../../../components/ha-svg-icon";
|
||||
import "../../../../components/item/ha-list-item-button";
|
||||
import "../../../../components/list/ha-list-base";
|
||||
import { internationalizationContext } from "../../../../data/context";
|
||||
import type { LovelaceSectionRawConfig } from "../../../../data/lovelace/config/section";
|
||||
import { DialogMixin } from "../../../../dialogs/dialog-mixin";
|
||||
import { generateDefaultSection } from "../../views/default-section";
|
||||
import { addSection } from "../config-util";
|
||||
import type { CreateSectionDialogParams } from "./show-create-section-dialog";
|
||||
import { showSelectSectionStrategyDialog } from "./show-create-section-dialog";
|
||||
|
||||
@customElement("hui-dialog-create-section")
|
||||
export class HuiDialogCreateSection extends DialogMixin<CreateSectionDialogParams>(
|
||||
LitElement
|
||||
) {
|
||||
@state()
|
||||
@consume({ context: internationalizationContext, subscribe: true })
|
||||
private _i18n!: ContextType<typeof internationalizationContext>;
|
||||
|
||||
@state()
|
||||
@storage({
|
||||
key: "dashboardSectionClipboard",
|
||||
state: true,
|
||||
subscribe: true,
|
||||
storage: "sessionStorage",
|
||||
})
|
||||
private _clipboard?: LovelaceSectionRawConfig;
|
||||
|
||||
protected render() {
|
||||
if (!this.params) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const localize = this._i18n.localize;
|
||||
|
||||
return html`
|
||||
<ha-adaptive-dialog
|
||||
open
|
||||
header-title=${localize("ui.panel.lovelace.editor.create_section.header")}
|
||||
>
|
||||
<ha-list-base>
|
||||
<ha-list-item-button @click=${this._createManual}>
|
||||
<ha-svg-icon
|
||||
slot="start"
|
||||
.path=${mdiViewGridPlusOutline}
|
||||
></ha-svg-icon>
|
||||
<span slot="headline">
|
||||
${localize("ui.panel.lovelace.editor.create_section.manual")}
|
||||
</span>
|
||||
<span slot="supporting-text">
|
||||
${localize(
|
||||
"ui.panel.lovelace.editor.create_section.manual_description"
|
||||
)}
|
||||
</span>
|
||||
</ha-list-item-button>
|
||||
<ha-list-item-button @click=${this._pickStrategy}>
|
||||
<ha-svg-icon slot="start" .path=${mdiAutoFix}></ha-svg-icon>
|
||||
<span slot="headline">
|
||||
${localize("ui.panel.lovelace.editor.create_section.automatic")}
|
||||
</span>
|
||||
<span slot="supporting-text">
|
||||
${localize(
|
||||
"ui.panel.lovelace.editor.create_section.automatic_description"
|
||||
)}
|
||||
</span>
|
||||
<ha-icon-next slot="end"></ha-icon-next>
|
||||
</ha-list-item-button>
|
||||
${
|
||||
this._clipboard
|
||||
? html`
|
||||
<ha-list-item-button @click=${this._paste}>
|
||||
<ha-svg-icon
|
||||
slot="start"
|
||||
.path=${mdiContentPaste}
|
||||
></ha-svg-icon>
|
||||
<span slot="headline">
|
||||
${localize("ui.panel.lovelace.editor.create_section.paste")}
|
||||
</span>
|
||||
<span slot="supporting-text">
|
||||
${localize(
|
||||
"ui.panel.lovelace.editor.create_section.paste_description"
|
||||
)}
|
||||
</span>
|
||||
</ha-list-item-button>
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
</ha-list-base>
|
||||
</ha-adaptive-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _createManual() {
|
||||
const { lovelace, containerPath } = this.params!;
|
||||
this.closeDialog();
|
||||
lovelace.saveConfig(
|
||||
addSection(
|
||||
lovelace.config,
|
||||
containerPath,
|
||||
generateDefaultSection(this._i18n.localize, true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private _pickStrategy() {
|
||||
showSelectSectionStrategyDialog(this, this.params!);
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
private async _paste() {
|
||||
if (!this._clipboard) {
|
||||
return;
|
||||
}
|
||||
const { lovelace, containerPath } = this.params!;
|
||||
const section = deepClone(this._clipboard);
|
||||
this.closeDialog();
|
||||
try {
|
||||
await lovelace.saveConfig(
|
||||
addSection(lovelace.config, containerPath, section)
|
||||
);
|
||||
} catch (_err: unknown) {
|
||||
lovelace.showToast({
|
||||
message: this._i18n.localize(
|
||||
"ui.panel.lovelace.editor.section.paste_error"
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
ha-adaptive-dialog {
|
||||
--dialog-content-padding: 0;
|
||||
}
|
||||
ha-list-base {
|
||||
--ha-list-padding: 0 0 var(--ha-space-3);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-dialog-create-section": HuiDialogCreateSection;
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ import {
|
||||
deleteAtPath,
|
||||
getAtPath,
|
||||
getViewPath,
|
||||
insertAtPath,
|
||||
moveAtPath,
|
||||
setAtPath,
|
||||
} from "../lovelace-path";
|
||||
@@ -138,10 +139,9 @@ export class HuiDialogEditSection
|
||||
|
||||
this.lovelace = params.lovelace;
|
||||
|
||||
this._config = getAtPath<LovelaceSectionRawConfig>(
|
||||
params.lovelaceConfig,
|
||||
params.path
|
||||
);
|
||||
this._config =
|
||||
params.newSection ??
|
||||
getAtPath<LovelaceSectionRawConfig>(params.lovelaceConfig, params.path);
|
||||
this._currTab =
|
||||
this._config && isStrategySection(this._config)
|
||||
? "tab-strategy"
|
||||
@@ -151,7 +151,12 @@ export class HuiDialogEditSection
|
||||
params.lovelaceConfig,
|
||||
viewPath
|
||||
);
|
||||
this._initDirtyTracking({ type: "deep" }, this._config);
|
||||
if (params.newSection) {
|
||||
this._initDirtyTracking({ type: "deep" }, {});
|
||||
this._updateDirtyState(params.newSection);
|
||||
} else {
|
||||
this._initDirtyTracking({ type: "deep" }, this._config);
|
||||
}
|
||||
this._defaultPreviewMode =
|
||||
window.innerWidth >= TWO_COLUMNS_MIN_WIDTH ? "desktop" : "mobile";
|
||||
}
|
||||
@@ -173,6 +178,7 @@ export class HuiDialogEditSection
|
||||
this._currTab = TABS[0];
|
||||
this._strategyError = false;
|
||||
this._yamlError = false;
|
||||
this._discardDirtyStateChanges();
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
@@ -264,24 +270,33 @@ export class HuiDialogEditSection
|
||||
@click=${this._enlarge}
|
||||
>${heading}</span
|
||||
>
|
||||
<ha-dropdown
|
||||
slot="headerActionItems"
|
||||
placement="bottom-end"
|
||||
@closed=${stopPropagation}
|
||||
@wa-select=${this._handleAction}
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass!.localize("ui.common.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
<ha-dropdown-item value="move-to-view">
|
||||
<ha-svg-icon slot="icon" .path=${mdiFileMoveOutline}></ha-svg-icon>
|
||||
${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_view.move_to_view"
|
||||
)}
|
||||
</ha-dropdown-item>
|
||||
</ha-dropdown>
|
||||
${
|
||||
this._params.newSection
|
||||
? nothing
|
||||
: html`
|
||||
<ha-dropdown
|
||||
slot="headerActionItems"
|
||||
placement="bottom-end"
|
||||
@closed=${stopPropagation}
|
||||
@wa-select=${this._handleAction}
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass!.localize("ui.common.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
<ha-dropdown-item value="move-to-view">
|
||||
<ha-svg-icon
|
||||
slot="icon"
|
||||
.path=${mdiFileMoveOutline}
|
||||
></ha-svg-icon>
|
||||
${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_view.move_to_view"
|
||||
)}
|
||||
</ha-dropdown-item>
|
||||
</ha-dropdown>
|
||||
`
|
||||
}
|
||||
<div class="content">
|
||||
<div class="element-editor ha-scrollbar">
|
||||
${
|
||||
@@ -674,11 +689,13 @@ export class HuiDialogEditSection
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const newConfig = setAtPath(
|
||||
this._params.lovelaceConfig,
|
||||
this._params.path,
|
||||
this._config
|
||||
);
|
||||
const newConfig = this._params.newSection
|
||||
? insertAtPath(
|
||||
this._params.lovelaceConfig,
|
||||
this._params.path,
|
||||
this._config
|
||||
)
|
||||
: setAtPath(this._params.lovelaceConfig, this._params.path, this._config);
|
||||
|
||||
this._params.saveConfig(newConfig);
|
||||
this._markDirtyStateClean();
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { isComponentLoaded } from "../../../../common/config/is_component_loaded";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import "../../../../components/ha-adaptive-dialog";
|
||||
import "../../../../components/ha-icon-button-arrow-prev";
|
||||
import "../../../../components/ha-ripple";
|
||||
import type { LovelaceStrategySectionConfig } from "../../../../data/lovelace/config/section";
|
||||
import { CUSTOM_TYPE_PREFIX } from "../../../../data/lovelace_custom_cards";
|
||||
import { getCustomStrategiesForType } from "../../../../data/lovelace_custom_strategies";
|
||||
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import "../../sections/hui-section";
|
||||
import { getLovelaceStrategy } from "../../strategies/get-strategy";
|
||||
import type { LovelaceSectionStrategy } from "../../strategies/types";
|
||||
import { getAtPath } from "../lovelace-path";
|
||||
import type { CreateSectionDialogParams } from "./show-create-section-dialog";
|
||||
import { showCreateSectionDialog } from "./show-create-section-dialog";
|
||||
import { showEditSectionDialog } from "./show-edit-section-dialog";
|
||||
|
||||
interface BuiltInSectionStrategy {
|
||||
type: "common-controls";
|
||||
isAvailable?: (hass: HomeAssistant) => boolean;
|
||||
}
|
||||
|
||||
const BUILT_IN_SECTION_STRATEGIES: BuiltInSectionStrategy[] = [
|
||||
{
|
||||
type: "common-controls",
|
||||
isAvailable: (hass) => isComponentLoaded(hass.config, "usage_prediction"),
|
||||
},
|
||||
];
|
||||
|
||||
interface StrategyOption {
|
||||
type: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
@customElement("hui-dialog-select-section-strategy")
|
||||
export class HuiDialogSelectSectionStrategy
|
||||
extends LitElement
|
||||
implements HassDialog<CreateSectionDialogParams>
|
||||
{
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _params?: CreateSectionDialogParams;
|
||||
|
||||
@state() private _open = false;
|
||||
|
||||
@state() private _previews: Record<string, LovelaceStrategySectionConfig> =
|
||||
{};
|
||||
|
||||
public showDialog(params: CreateSectionDialogParams): void {
|
||||
this._params = params;
|
||||
this._open = true;
|
||||
this._previews = {};
|
||||
this._loadPreviews(params);
|
||||
}
|
||||
|
||||
public closeDialog(): boolean {
|
||||
this._open = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private _dialogClosed(): void {
|
||||
this._params = undefined;
|
||||
this._previews = {};
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
private _availableBuiltInTypes() {
|
||||
return BUILT_IN_SECTION_STRATEGIES.filter(
|
||||
(strategy) => strategy.isAvailable?.(this.hass) ?? true
|
||||
).map((strategy) => strategy.type);
|
||||
}
|
||||
|
||||
private _builtInOptions(): StrategyOption[] {
|
||||
return this._availableBuiltInTypes().map((type) => ({
|
||||
type,
|
||||
name: this.hass.localize(
|
||||
`ui.panel.lovelace.editor.section_strategy.${type}.name`
|
||||
),
|
||||
description: this.hass.localize(
|
||||
`ui.panel.lovelace.editor.section_strategy.${type}.description`
|
||||
),
|
||||
}));
|
||||
}
|
||||
|
||||
private _customOptions(): StrategyOption[] {
|
||||
return getCustomStrategiesForType("section").map((strategy) => ({
|
||||
type: CUSTOM_TYPE_PREFIX + strategy.type,
|
||||
name: strategy.name || strategy.type,
|
||||
description: strategy.description || "",
|
||||
}));
|
||||
}
|
||||
|
||||
private async _loadPreviews(params: CreateSectionDialogParams) {
|
||||
const types = [
|
||||
...this._availableBuiltInTypes(),
|
||||
...getCustomStrategiesForType("section").map(
|
||||
(strategy) => CUSTOM_TYPE_PREFIX + strategy.type
|
||||
),
|
||||
];
|
||||
await Promise.all(
|
||||
types.map(async (type) => {
|
||||
try {
|
||||
const strategy = (await getLovelaceStrategy(
|
||||
"section",
|
||||
type
|
||||
)) as LovelaceSectionStrategy;
|
||||
const stubConfig = await strategy.getStubConfig?.(this.hass);
|
||||
if (!stubConfig || this._params !== params) {
|
||||
return;
|
||||
}
|
||||
this._previews = {
|
||||
...this._previews,
|
||||
[type]: { strategy: stubConfig },
|
||||
};
|
||||
} catch (_err: unknown) {
|
||||
// The tile is shown without a preview
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._params) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const customOptions = this._customOptions();
|
||||
|
||||
return html`
|
||||
<ha-adaptive-dialog
|
||||
.open=${this._open}
|
||||
width="large"
|
||||
@closed=${this._dialogClosed}
|
||||
header-title=${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.select_section_strategy.header"
|
||||
)}
|
||||
>
|
||||
<ha-icon-button-arrow-prev
|
||||
slot="headerNavigationIcon"
|
||||
@click=${this._back}
|
||||
></ha-icon-button-arrow-prev>
|
||||
${
|
||||
customOptions.length
|
||||
? html`
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.select_section_strategy.built_in"
|
||||
)}
|
||||
</h3>
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
<div class="options">
|
||||
${this._builtInOptions().map((option) => this._renderOption(option))}
|
||||
</div>
|
||||
${
|
||||
customOptions.length
|
||||
? html`
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.select_section_strategy.custom"
|
||||
)}
|
||||
</h3>
|
||||
<div class="options">
|
||||
${customOptions.map((option) => this._renderOption(option))}
|
||||
</div>
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
</ha-adaptive-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _renderOption(option: StrategyOption) {
|
||||
const preview = this._previews[option.type];
|
||||
return html`
|
||||
<div
|
||||
class="option"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label=${option.name}
|
||||
data-type=${option.type}
|
||||
@click=${this._strategyPicked}
|
||||
@keydown=${this._handleKeyDown}
|
||||
>
|
||||
<div class="header">
|
||||
<h4>${option.name}</h4>
|
||||
<p>${option.description}</p>
|
||||
</div>
|
||||
${
|
||||
preview
|
||||
? html`
|
||||
<div class="preview" inert>
|
||||
<hui-section
|
||||
.hass=${this.hass}
|
||||
.config=${preview}
|
||||
preview
|
||||
></hui-section>
|
||||
</div>
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
<ha-ripple></ha-ripple>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleKeyDown(ev: KeyboardEvent) {
|
||||
if (ev.key === "Enter" || ev.key === " ") {
|
||||
ev.preventDefault();
|
||||
(ev.currentTarget as HTMLElement).click();
|
||||
}
|
||||
}
|
||||
|
||||
private _back() {
|
||||
showCreateSectionDialog(this, this._params!);
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
private _strategyPicked(ev: Event) {
|
||||
const type = (ev.currentTarget as HTMLElement).dataset.type!;
|
||||
const { lovelace, containerPath } = this._params!;
|
||||
const sectionsPath = [...containerPath, "sections"];
|
||||
const sectionCount =
|
||||
getAtPath<unknown[]>(lovelace.config, sectionsPath)?.length ?? 0;
|
||||
|
||||
showEditSectionDialog(this, {
|
||||
lovelace,
|
||||
lovelaceConfig: lovelace.config,
|
||||
saveConfig: (newConfig) => {
|
||||
lovelace.saveConfig(newConfig);
|
||||
},
|
||||
path: [...sectionsPath, sectionCount],
|
||||
newSection: this._previews[type] ?? { strategy: { type } },
|
||||
});
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
h3 {
|
||||
margin: 0 0 var(--ha-space-3) 0;
|
||||
font-size: var(--ha-font-size-l);
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
}
|
||||
.options + h3 {
|
||||
margin-top: var(--ha-space-6);
|
||||
}
|
||||
.options {
|
||||
display: grid;
|
||||
gap: var(--ha-space-4);
|
||||
grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
|
||||
}
|
||||
.option {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--divider-color);
|
||||
border-radius: var(--ha-border-radius-lg);
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
.option:focus-visible {
|
||||
outline: 2px solid var(--primary-color);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.header {
|
||||
flex: 1;
|
||||
padding: var(--ha-space-3) var(--ha-space-4);
|
||||
}
|
||||
h4 {
|
||||
margin: 0 0 var(--ha-space-1) 0;
|
||||
font-size: var(--ha-font-size-l);
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
p {
|
||||
margin: 0;
|
||||
font-size: var(--ha-font-size-m);
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.preview {
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
padding: var(--ha-space-3);
|
||||
background: var(--primary-background-color);
|
||||
pointer-events: none;
|
||||
mask-image: linear-gradient(to bottom, black 75%, transparent);
|
||||
}
|
||||
hui-section {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-dialog-select-section-strategy": HuiDialogSelectSectionStrategy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import type { Lovelace } from "../../types";
|
||||
import type { LovelacePath } from "../lovelace-path";
|
||||
|
||||
export interface CreateSectionDialogParams {
|
||||
lovelace: Lovelace;
|
||||
containerPath: LovelacePath;
|
||||
}
|
||||
|
||||
export const showCreateSectionDialog = (
|
||||
element: HTMLElement,
|
||||
params: CreateSectionDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "hui-dialog-create-section",
|
||||
dialogImport: () => import("./hui-dialog-create-section"),
|
||||
dialogParams: params,
|
||||
});
|
||||
};
|
||||
|
||||
export const showSelectSectionStrategyDialog = (
|
||||
element: HTMLElement,
|
||||
params: CreateSectionDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "hui-dialog-select-section-strategy",
|
||||
dialogImport: () => import("./hui-dialog-select-section-strategy"),
|
||||
dialogParams: params,
|
||||
});
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import type { LovelaceSectionRawConfig } from "../../../../data/lovelace/config/section";
|
||||
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
||||
import type { Lovelace } from "../../types";
|
||||
import type { LovelacePath } from "../lovelace-path";
|
||||
@@ -8,6 +9,7 @@ export interface EditSectionDialogParams {
|
||||
lovelaceConfig: LovelaceConfig;
|
||||
saveConfig: (config: LovelaceConfig) => void;
|
||||
path: LovelacePath;
|
||||
newSection?: LovelaceSectionRawConfig;
|
||||
}
|
||||
|
||||
const importEditSectionDialog = () => import("./hui-dialog-edit-section");
|
||||
|
||||
@@ -35,7 +35,11 @@ export type LovelaceDashboardStrategyGetCreateSuggestions = (
|
||||
|
||||
export interface LovelaceViewStrategy extends LovelaceStrategy<LovelaceViewConfig> {}
|
||||
|
||||
export interface LovelaceSectionStrategy extends LovelaceStrategy<LovelaceSectionConfig> {}
|
||||
export interface LovelaceSectionStrategy extends LovelaceStrategy<LovelaceSectionConfig> {
|
||||
getStubConfig?(
|
||||
hass: HomeAssistant
|
||||
): LovelaceStrategyConfig | Promise<LovelaceStrategyConfig>;
|
||||
}
|
||||
|
||||
export interface LovelaceStrategyEditor extends LovelaceGenericElementEditor {
|
||||
setConfig(config: LovelaceStrategyConfig): void;
|
||||
|
||||
@@ -40,6 +40,10 @@ export class CommonControlsSectionStrategy extends ReactiveElement {
|
||||
);
|
||||
}
|
||||
|
||||
public static getStubConfig(): CommonControlsSectionStrategyConfig {
|
||||
return { type: "common-controls" };
|
||||
}
|
||||
|
||||
static async generate(
|
||||
config: CommonControlsSectionStrategyConfig,
|
||||
hass: HomeAssistant
|
||||
|
||||
@@ -30,6 +30,7 @@ import "../components/hui-section-edit-mode";
|
||||
import { addSection } from "../editor/config-util";
|
||||
import type { LovelacePath } from "../editor/lovelace-path";
|
||||
import { getAtPath, moveAtPath } from "../editor/lovelace-path";
|
||||
import { showCreateSectionDialog } from "../editor/section-editor/show-create-section-dialog";
|
||||
import type { HuiSection } from "../sections/hui-section";
|
||||
import "../sections/hui-section-background";
|
||||
import type { Lovelace } from "../types";
|
||||
@@ -474,12 +475,10 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
}
|
||||
|
||||
private _createSection(): void {
|
||||
const newConfig = addSection(
|
||||
this.lovelace!.config,
|
||||
this.path!,
|
||||
generateDefaultSection(this.hass.localize, true)
|
||||
);
|
||||
this.lovelace!.saveConfig(newConfig);
|
||||
showCreateSectionDialog(this, {
|
||||
lovelace: this.lovelace!,
|
||||
containerPath: this.path!,
|
||||
});
|
||||
}
|
||||
|
||||
private _sectionMoved(ev: CustomEvent) {
|
||||
|
||||
@@ -10169,9 +10169,24 @@
|
||||
},
|
||||
"section_strategy": {
|
||||
"common-controls": {
|
||||
"name": "Common controls"
|
||||
"name": "Common controls",
|
||||
"description": "Shows the entities you use most, based on your activity."
|
||||
}
|
||||
},
|
||||
"create_section": {
|
||||
"header": "Create section",
|
||||
"manual": "Manual section",
|
||||
"manual_description": "Start empty and add your own cards.",
|
||||
"automatic": "[%key:ui::panel::lovelace::editor::section::automatic%]",
|
||||
"automatic_description": "Fills itself with cards and stays up to date.",
|
||||
"paste": "Paste section",
|
||||
"paste_description": "Add the section you copied."
|
||||
},
|
||||
"select_section_strategy": {
|
||||
"header": "Choose an automatic section",
|
||||
"built_in": "Built-in sections",
|
||||
"custom": "Community sections"
|
||||
},
|
||||
"edit_section": {
|
||||
"header": "Section configuration",
|
||||
"typed_header": "{type} section configuration",
|
||||
|
||||
Reference in new issue
Block a user