mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 11:46:42 +00:00
Allow to convert a view to sections view (#22594)
* Add imported cards in section view * Add convert logic * Improve editor * Fix type * Use imported container for individual card move * Fix type import * Add missing translations * Feedback
This commit is contained in:
parent
3c8da03d66
commit
29d9b61319
@ -34,6 +34,7 @@ export interface LovelaceSectionElement extends HTMLElement {
|
|||||||
index?: number;
|
index?: number;
|
||||||
cards?: HuiCard[];
|
cards?: HuiCard[];
|
||||||
isStrategy: boolean;
|
isStrategy: boolean;
|
||||||
|
importOnly?: boolean;
|
||||||
setConfig(config: LovelaceSectionConfig): void;
|
setConfig(config: LovelaceSectionConfig): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import type { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
|
||||||
import {
|
import {
|
||||||
mdiContentCopy,
|
mdiContentCopy,
|
||||||
mdiContentCut,
|
mdiContentCut,
|
||||||
|
mdiCursorMove,
|
||||||
mdiDelete,
|
mdiDelete,
|
||||||
mdiDotsVertical,
|
mdiDotsVertical,
|
||||||
mdiPencil,
|
mdiPencil,
|
||||||
@ -10,7 +10,7 @@ import {
|
|||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import deepClone from "deep-clone-simple";
|
import deepClone from "deep-clone-simple";
|
||||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||||
import { LitElement, css, html } from "lit";
|
import { LitElement, css, html, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import { storage } from "../../../common/decorators/storage";
|
import { storage } from "../../../common/decorators/storage";
|
||||||
@ -39,7 +39,14 @@ export class HuiCardEditMode extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Array }) public path!: LovelaceCardPath;
|
@property({ type: Array }) public path!: LovelaceCardPath;
|
||||||
|
|
||||||
@property({ type: Boolean }) public hiddenOverlay = false;
|
@property({ type: Boolean, attribute: "hidden-overlay" })
|
||||||
|
public hiddenOverlay = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "no-edit" })
|
||||||
|
public noEdit = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "no-duplicate" })
|
||||||
|
public noDuplicate = false;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
public _menuOpened: boolean = false;
|
public _menuOpened: boolean = false;
|
||||||
@ -110,15 +117,24 @@ export class HuiCardEditMode extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div class="card-wrapper" inert><slot></slot></div>
|
<div class="card-wrapper" inert><slot></slot></div>
|
||||||
<div class="card-overlay ${classMap({ visible: showOverlay })}">
|
<div class="card-overlay ${classMap({ visible: showOverlay })}">
|
||||||
<div
|
${this.noEdit
|
||||||
class="edit"
|
? html`
|
||||||
@click=${this._handleOverlayClick}
|
<div class="control">
|
||||||
@keydown=${this._handleOverlayClick}
|
<div class="control-overlay"></div>
|
||||||
tabindex="0"
|
<ha-svg-icon .path=${mdiCursorMove}> </ha-svg-icon>
|
||||||
>
|
</div>
|
||||||
<div class="edit-overlay"></div>
|
`
|
||||||
<ha-svg-icon class="edit" .path=${mdiPencil}> </ha-svg-icon>
|
: html`
|
||||||
</div>
|
<div
|
||||||
|
class="control"
|
||||||
|
@click=${this._handleOverlayClick}
|
||||||
|
@keydown=${this._handleOverlayClick}
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div class="control-overlay"></div>
|
||||||
|
<ha-svg-icon .path=${mdiPencil}> </ha-svg-icon>
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
<ha-button-menu
|
<ha-button-menu
|
||||||
class="more"
|
class="more"
|
||||||
corner="BOTTOM_END"
|
corner="BOTTOM_END"
|
||||||
@ -130,29 +146,60 @@ export class HuiCardEditMode extends LitElement {
|
|||||||
>
|
>
|
||||||
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
|
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
|
||||||
</ha-icon-button>
|
</ha-icon-button>
|
||||||
<ha-list-item graphic="icon">
|
${this.noEdit
|
||||||
<ha-svg-icon slot="graphic" .path=${mdiPencil}></ha-svg-icon>
|
? nothing
|
||||||
${this.hass.localize("ui.panel.lovelace.editor.edit_card.edit")}
|
: html`
|
||||||
</ha-list-item>
|
<ha-list-item
|
||||||
<ha-list-item graphic="icon">
|
graphic="icon"
|
||||||
<ha-svg-icon
|
@click=${this._handleAction}
|
||||||
slot="graphic"
|
.action=${"edit"}
|
||||||
.path=${mdiPlusCircleMultipleOutline}
|
>
|
||||||
></ha-svg-icon>
|
<ha-svg-icon slot="graphic" .path=${mdiPencil}></ha-svg-icon>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.lovelace.editor.edit_card.duplicate"
|
"ui.panel.lovelace.editor.edit_card.edit"
|
||||||
)}
|
)}
|
||||||
</ha-list-item>
|
</ha-list-item>
|
||||||
<ha-list-item graphic="icon">
|
`}
|
||||||
|
${this.noDuplicate
|
||||||
|
? nothing
|
||||||
|
: html`
|
||||||
|
<ha-list-item
|
||||||
|
graphic="icon"
|
||||||
|
@click=${this._handleAction}
|
||||||
|
.action=${"duplicate"}
|
||||||
|
>
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiPlusCircleMultipleOutline}
|
||||||
|
></ha-svg-icon>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_card.duplicate"
|
||||||
|
)}
|
||||||
|
</ha-list-item>
|
||||||
|
`}
|
||||||
|
<ha-list-item
|
||||||
|
graphic="icon"
|
||||||
|
@click=${this._handleAction}
|
||||||
|
.action=${"copy"}
|
||||||
|
>
|
||||||
<ha-svg-icon slot="graphic" .path=${mdiContentCopy}></ha-svg-icon>
|
<ha-svg-icon slot="graphic" .path=${mdiContentCopy}></ha-svg-icon>
|
||||||
${this.hass.localize("ui.panel.lovelace.editor.edit_card.copy")}
|
${this.hass.localize("ui.panel.lovelace.editor.edit_card.copy")}
|
||||||
</ha-list-item>
|
</ha-list-item>
|
||||||
<ha-list-item graphic="icon">
|
<ha-list-item
|
||||||
|
graphic="icon"
|
||||||
|
@click=${this._handleAction}
|
||||||
|
.action=${"cut"}
|
||||||
|
>
|
||||||
<ha-svg-icon slot="graphic" .path=${mdiContentCut}></ha-svg-icon>
|
<ha-svg-icon slot="graphic" .path=${mdiContentCut}></ha-svg-icon>
|
||||||
${this.hass.localize("ui.panel.lovelace.editor.edit_card.cut")}
|
${this.hass.localize("ui.panel.lovelace.editor.edit_card.cut")}
|
||||||
</ha-list-item>
|
</ha-list-item>
|
||||||
<li divider role="separator"></li>
|
<li divider role="separator"></li>
|
||||||
<ha-list-item graphic="icon" class="warning">
|
<ha-list-item
|
||||||
|
graphic="icon"
|
||||||
|
class="warning"
|
||||||
|
@click=${this._handleAction}
|
||||||
|
.action=${"delete"}
|
||||||
|
>
|
||||||
${this.hass.localize("ui.panel.lovelace.editor.edit_card.delete")}
|
${this.hass.localize("ui.panel.lovelace.editor.edit_card.delete")}
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
class="warning"
|
class="warning"
|
||||||
@ -185,21 +232,21 @@ export class HuiCardEditMode extends LitElement {
|
|||||||
this._editCard();
|
this._editCard();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
private _handleAction(ev) {
|
||||||
switch (ev.detail.index) {
|
switch (ev.target.action) {
|
||||||
case 0:
|
case "edit":
|
||||||
this._editCard();
|
this._editCard();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case "duplicate":
|
||||||
this._duplicateCard();
|
this._duplicateCard();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case "copy":
|
||||||
this._copyCard();
|
this._copyCard();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case "cut":
|
||||||
this._cutCard();
|
this._cutCard();
|
||||||
break;
|
break;
|
||||||
case 4:
|
case "delete":
|
||||||
this._deleteCard();
|
this._deleteCard();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -262,7 +309,7 @@ export class HuiCardEditMode extends LitElement {
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit {
|
.control {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -273,7 +320,7 @@ export class HuiCardEditMode extends LitElement {
|
|||||||
border-radius: var(--ha-card-border-radius, 12px);
|
border-radius: var(--ha-card-border-radius, 12px);
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
.edit-overlay {
|
.control-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
@ -282,7 +329,7 @@ export class HuiCardEditMode extends LitElement {
|
|||||||
border-radius: var(--ha-card-border-radius, 12px);
|
border-radius: var(--ha-card-border-radius, 12px);
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
.edit ha-svg-icon {
|
.control ha-svg-icon {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
|
@ -21,22 +21,17 @@ import "../../../components/ha-icon-button";
|
|||||||
import "../../../components/ha-list-item";
|
import "../../../components/ha-list-item";
|
||||||
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
import { saveConfig } from "../../../data/lovelace/config/types";
|
import { saveConfig } from "../../../data/lovelace/config/types";
|
||||||
import {
|
import { isStrategyView } from "../../../data/lovelace/config/view";
|
||||||
isStrategyView,
|
|
||||||
type LovelaceViewConfig,
|
|
||||||
} from "../../../data/lovelace/config/view";
|
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
showPromptDialog,
|
showPromptDialog,
|
||||||
} from "../../../dialogs/generic/show-dialog-box";
|
} from "../../../dialogs/generic/show-dialog-box";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import { showSaveSuccessToast } from "../../../util/toast-saved-success";
|
|
||||||
import { computeCardSize } from "../common/compute-card-size";
|
import { computeCardSize } from "../common/compute-card-size";
|
||||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||||
import {
|
import {
|
||||||
addCard,
|
addCard,
|
||||||
addSection,
|
|
||||||
deleteCard,
|
deleteCard,
|
||||||
moveCardToContainer,
|
moveCardToContainer,
|
||||||
moveCardToIndex,
|
moveCardToIndex,
|
||||||
@ -50,8 +45,6 @@ import {
|
|||||||
} from "../editor/lovelace-path";
|
} from "../editor/lovelace-path";
|
||||||
import { showSelectViewDialog } from "../editor/select-view/show-select-view-dialog";
|
import { showSelectViewDialog } from "../editor/select-view/show-select-view-dialog";
|
||||||
import type { Lovelace, LovelaceCard } from "../types";
|
import type { Lovelace, LovelaceCard } from "../types";
|
||||||
import { SECTIONS_VIEW_LAYOUT } from "../views/const";
|
|
||||||
import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
|
|
||||||
|
|
||||||
@customElement("hui-card-options")
|
@customElement("hui-card-options")
|
||||||
export class HuiCardOptions extends LitElement {
|
export class HuiCardOptions extends LitElement {
|
||||||
@ -352,9 +345,13 @@ export class HuiCardOptions extends LitElement {
|
|||||||
allowDashboardChange: true,
|
allowDashboardChange: true,
|
||||||
header: this.hass!.localize("ui.panel.lovelace.editor.move_card.header"),
|
header: this.hass!.localize("ui.panel.lovelace.editor.move_card.header"),
|
||||||
viewSelectedCallback: async (urlPath, selectedDashConfig, viewIndex) => {
|
viewSelectedCallback: async (urlPath, selectedDashConfig, viewIndex) => {
|
||||||
const fromView = selectedDashConfig.views[this.path![0]];
|
if (!this.lovelace) return;
|
||||||
let toView = selectedDashConfig.views[viewIndex];
|
const toView = selectedDashConfig.views[viewIndex];
|
||||||
let newConfig = selectedDashConfig;
|
const newConfig = selectedDashConfig;
|
||||||
|
|
||||||
|
const undoAction = async () => {
|
||||||
|
this.lovelace!.saveConfig(selectedDashConfig);
|
||||||
|
};
|
||||||
|
|
||||||
if (isStrategyView(toView)) {
|
if (isStrategyView(toView)) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
@ -369,53 +366,22 @@ export class HuiCardOptions extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSectionsView = toView.type === SECTIONS_VIEW_LAYOUT;
|
const toPath: LovelaceContainerPath = [viewIndex];
|
||||||
|
|
||||||
let toPath: LovelaceContainerPath = [viewIndex];
|
|
||||||
|
|
||||||
// If the view is a section view and has no "imported cards" section, adds a default section.
|
|
||||||
if (isSectionsView) {
|
|
||||||
const importedCardHeading = fromView.title
|
|
||||||
? this.hass!.localize(
|
|
||||||
"ui.panel.lovelace.editor.section.imported_card_section_title_view",
|
|
||||||
{ view_title: fromView.title }
|
|
||||||
)
|
|
||||||
: this.hass!.localize(
|
|
||||||
"ui.panel.lovelace.editor.section.imported_card_section_title_default"
|
|
||||||
);
|
|
||||||
|
|
||||||
let sectionIndex = toView.sections
|
|
||||||
? toView.sections.findIndex(
|
|
||||||
(s) =>
|
|
||||||
"cards" in s &&
|
|
||||||
s.cards?.some(
|
|
||||||
(c) =>
|
|
||||||
c.type === "heading" && c.heading === importedCardHeading
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: -1;
|
|
||||||
if (sectionIndex === -1) {
|
|
||||||
const newSection: LovelaceSectionConfig = {
|
|
||||||
type: "grid",
|
|
||||||
cards: [
|
|
||||||
{
|
|
||||||
type: "heading",
|
|
||||||
heading: importedCardHeading,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
newConfig = addSection(selectedDashConfig, viewIndex, newSection);
|
|
||||||
toView = newConfig.views[viewIndex] as LovelaceViewConfig;
|
|
||||||
sectionIndex = toView.sections!.length - 1;
|
|
||||||
}
|
|
||||||
toPath = [viewIndex, sectionIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (urlPath === this.lovelace!.urlPath) {
|
if (urlPath === this.lovelace!.urlPath) {
|
||||||
this.lovelace!.saveConfig(
|
this.lovelace!.saveConfig(
|
||||||
moveCardToContainer(newConfig, this.path!, toPath)
|
moveCardToContainer(newConfig, this.path!, toPath)
|
||||||
);
|
);
|
||||||
showSaveSuccessToast(this, this.hass!);
|
this.lovelace.showToast({
|
||||||
|
message: this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.move_card.success"
|
||||||
|
),
|
||||||
|
duration: 4000,
|
||||||
|
action: {
|
||||||
|
action: undoAction,
|
||||||
|
text: this.hass!.localize("ui.common.undo"),
|
||||||
|
},
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -429,10 +395,22 @@ export class HuiCardOptions extends LitElement {
|
|||||||
this.lovelace!.saveConfig(
|
this.lovelace!.saveConfig(
|
||||||
deleteCard(this.lovelace!.config, this.path!)
|
deleteCard(this.lovelace!.config, this.path!)
|
||||||
);
|
);
|
||||||
showSaveSuccessToast(this, this.hass!);
|
|
||||||
|
this.lovelace.showToast({
|
||||||
|
message: this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.move_card.success"
|
||||||
|
),
|
||||||
|
duration: 4000,
|
||||||
|
action: {
|
||||||
|
action: undoAction,
|
||||||
|
text: this.hass!.localize("ui.common.undo"),
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
showAlertDialog(this, {
|
this.lovelace.showToast({
|
||||||
text: `Moving failed: ${err.message}`,
|
message: this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.move_card.error"
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -13,6 +13,7 @@ import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
|||||||
import { navigate } from "../../../../common/navigate";
|
import { navigate } from "../../../../common/navigate";
|
||||||
import { deepEqual } from "../../../../common/util/deep-equal";
|
import { deepEqual } from "../../../../common/util/deep-equal";
|
||||||
import "../../../../components/ha-alert";
|
import "../../../../components/ha-alert";
|
||||||
|
import "../../../../components/ha-button";
|
||||||
import "../../../../components/ha-circular-progress";
|
import "../../../../components/ha-circular-progress";
|
||||||
import "../../../../components/ha-dialog";
|
import "../../../../components/ha-dialog";
|
||||||
import "../../../../components/ha-dialog-header";
|
import "../../../../components/ha-dialog-header";
|
||||||
@ -57,8 +58,10 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
|
|
||||||
@query("ha-yaml-editor") private _editor?: HaYamlEditor;
|
@query("ha-yaml-editor") private _editor?: HaYamlEditor;
|
||||||
|
|
||||||
|
@state() private _currentType = getViewType();
|
||||||
|
|
||||||
get _type(): string {
|
get _type(): string {
|
||||||
return getViewType(this._config!);
|
return getViewType(this._config);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProperties: PropertyValues) {
|
protected updated(changedProperties: PropertyValues) {
|
||||||
@ -76,7 +79,6 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
if (this._params.viewIndex === undefined) {
|
if (this._params.viewIndex === undefined) {
|
||||||
this._config = {
|
this._config = {
|
||||||
type: SECTIONS_VIEW_LAYOUT,
|
type: SECTIONS_VIEW_LAYOUT,
|
||||||
sections: [generateDefaultSection(this.hass!.localize)],
|
|
||||||
};
|
};
|
||||||
this._dirty = false;
|
this._dirty = false;
|
||||||
return;
|
return;
|
||||||
@ -89,6 +91,7 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._config = view;
|
this._config = view;
|
||||||
|
this._currentType = this._type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog(): void {
|
public closeDialog(): void {
|
||||||
@ -159,12 +162,14 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isCompatibleViewType =
|
const convertToSection =
|
||||||
this._config?.type === SECTIONS_VIEW_LAYOUT
|
this._type === SECTIONS_VIEW_LAYOUT &&
|
||||||
? this._config?.type === SECTIONS_VIEW_LAYOUT &&
|
this._currentType !== SECTIONS_VIEW_LAYOUT &&
|
||||||
!this._config?.cards?.length
|
this._config?.cards?.length;
|
||||||
: this._config?.type !== SECTIONS_VIEW_LAYOUT &&
|
const convertNotSupported =
|
||||||
!this._config?.sections?.length;
|
this._type !== SECTIONS_VIEW_LAYOUT &&
|
||||||
|
this._currentType === SECTIONS_VIEW_LAYOUT &&
|
||||||
|
this._config?.sections?.length;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-dialog
|
<ha-dialog
|
||||||
@ -224,16 +229,29 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
: ``}
|
: ``}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
${!isCompatibleViewType
|
${convertToSection
|
||||||
? html`
|
? html`
|
||||||
<ha-alert class="incompatible" alert-type="warning">
|
<ha-alert alert-type="info">
|
||||||
${this._config?.type === SECTIONS_VIEW_LAYOUT
|
${this.hass!.localize(
|
||||||
? this.hass!.localize(
|
"ui.panel.lovelace.editor.edit_view.card_to_section_convert"
|
||||||
"ui.panel.lovelace.editor.edit_view.type_warning_sections"
|
)}
|
||||||
)
|
<ha-button
|
||||||
: this.hass!.localize(
|
slot="action"
|
||||||
"ui.panel.lovelace.editor.edit_view.type_warning_others"
|
.label=${this.hass!.localize(
|
||||||
)}
|
"ui.panel.lovelace.editor.edit_view.convert_view"
|
||||||
|
)}
|
||||||
|
@click=${this._convertToSection}
|
||||||
|
>
|
||||||
|
</ha-button>
|
||||||
|
</ha-alert>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
|
${convertNotSupported
|
||||||
|
? html`
|
||||||
|
<ha-alert alert-type="warning">
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.section_to_card_not_supported"
|
||||||
|
)}
|
||||||
</ha-alert>
|
</ha-alert>
|
||||||
`
|
`
|
||||||
: nothing}
|
: nothing}
|
||||||
@ -258,7 +276,7 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
${content}
|
${content}
|
||||||
${this._params.viewIndex !== undefined
|
${this._params.viewIndex !== undefined
|
||||||
? html`
|
? html`
|
||||||
<mwc-button
|
<ha-button
|
||||||
class="warning"
|
class="warning"
|
||||||
slot="secondaryAction"
|
slot="secondaryAction"
|
||||||
@click=${this._deleteConfirm}
|
@click=${this._deleteConfirm}
|
||||||
@ -266,15 +284,16 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
${this.hass!.localize(
|
${this.hass!.localize(
|
||||||
"ui.panel.lovelace.editor.edit_view.delete"
|
"ui.panel.lovelace.editor.edit_view.delete"
|
||||||
)}
|
)}
|
||||||
</mwc-button>
|
</ha-button>
|
||||||
`
|
`
|
||||||
: nothing}
|
: nothing}
|
||||||
<mwc-button
|
<ha-button
|
||||||
slot="primaryAction"
|
slot="primaryAction"
|
||||||
?disabled=${!this._config ||
|
?disabled=${!this._config ||
|
||||||
this._saving ||
|
this._saving ||
|
||||||
!this._dirty ||
|
!this._dirty ||
|
||||||
!isCompatibleViewType}
|
convertToSection ||
|
||||||
|
convertNotSupported}
|
||||||
@click=${this._save}
|
@click=${this._save}
|
||||||
>
|
>
|
||||||
${this._saving
|
${this._saving
|
||||||
@ -284,7 +303,7 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
aria-label="Saving"
|
aria-label="Saving"
|
||||||
></ha-circular-progress>`
|
></ha-circular-progress>`
|
||||||
: nothing}
|
: nothing}
|
||||||
${this.hass!.localize("ui.common.save")}</mwc-button
|
${this.hass!.localize("ui.common.save")}</ha-button
|
||||||
>
|
>
|
||||||
</ha-dialog>
|
</ha-dialog>
|
||||||
`;
|
`;
|
||||||
@ -303,6 +322,54 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _convertToSection() {
|
||||||
|
if (!this._params || !this._config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const confirm = await showConfirmationDialog(this, {
|
||||||
|
title: this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.convert_view_title"
|
||||||
|
),
|
||||||
|
text: this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.convert_view_text"
|
||||||
|
),
|
||||||
|
confirmText: this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.convert_view_action"
|
||||||
|
),
|
||||||
|
dismissText: this.hass!.localize("ui.common.cancel"),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirm) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newConfig = {
|
||||||
|
...this._config,
|
||||||
|
};
|
||||||
|
newConfig.type = SECTIONS_VIEW_LAYOUT;
|
||||||
|
newConfig.sections = [generateDefaultSection(this.hass!.localize)];
|
||||||
|
newConfig.path = undefined;
|
||||||
|
const lovelace = this._params!.lovelace!;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await lovelace.saveConfig(
|
||||||
|
addView(this.hass!, lovelace.config, newConfig)
|
||||||
|
);
|
||||||
|
if (this._params.saveCallback) {
|
||||||
|
this._params.saveCallback(lovelace.config.views.length, newConfig);
|
||||||
|
}
|
||||||
|
this.closeDialog();
|
||||||
|
} catch (err: any) {
|
||||||
|
showAlertDialog(this, {
|
||||||
|
text: `${this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.saving_failed"
|
||||||
|
)}: ${err.message}`,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
this._saving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async _delete(): Promise<void> {
|
private async _delete(): Promise<void> {
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return;
|
return;
|
||||||
@ -366,7 +433,7 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
const viewConf = {
|
const viewConf = {
|
||||||
...this._config,
|
...this._config,
|
||||||
};
|
};
|
||||||
|
// Ensure we have at least one section if we are in sections view
|
||||||
if (viewConf.type === SECTIONS_VIEW_LAYOUT && !viewConf.sections?.length) {
|
if (viewConf.type === SECTIONS_VIEW_LAYOUT && !viewConf.sections?.length) {
|
||||||
viewConf.sections = [generateDefaultSection(this.hass!.localize)];
|
viewConf.sections = [generateDefaultSection(this.hass!.localize)];
|
||||||
} else if (!viewConf.cards?.length) {
|
} else if (!viewConf.cards?.length) {
|
||||||
@ -386,7 +453,7 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
viewConf
|
viewConf
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (this._params.saveCallback) {
|
if (this._params.saveCallback && this._creatingView) {
|
||||||
this._params.saveCallback(
|
this._params.saveCallback(
|
||||||
this._params.viewIndex || lovelace.config.views.length,
|
this._params.viewIndex || lovelace.config.views.length,
|
||||||
viewConf
|
viewConf
|
||||||
@ -479,7 +546,7 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
mwc-button.warning {
|
ha-button.warning {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-inline-end: auto;
|
margin-inline-end: auto;
|
||||||
margin-inline-start: initial;
|
margin-inline-start: initial;
|
||||||
@ -494,7 +561,10 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
border-bottom: 1px solid var(--error-color);
|
border-bottom: 1px solid var(--error-color);
|
||||||
}
|
}
|
||||||
.incompatible {
|
ha-alert {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
ha-alert ha-button {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,26 @@ export class HuiViewEditor extends LitElement {
|
|||||||
private _schema = memoizeOne(
|
private _schema = memoizeOne(
|
||||||
(localize: LocalizeFunc, viewType: string) =>
|
(localize: LocalizeFunc, viewType: string) =>
|
||||||
[
|
[
|
||||||
|
{
|
||||||
|
name: "type",
|
||||||
|
selector: {
|
||||||
|
select: {
|
||||||
|
options: (
|
||||||
|
[
|
||||||
|
SECTIONS_VIEW_LAYOUT,
|
||||||
|
MASONRY_VIEW_LAYOUT,
|
||||||
|
SIDEBAR_VIEW_LAYOUT,
|
||||||
|
PANEL_VIEW_LAYOUT,
|
||||||
|
] as const
|
||||||
|
).map((type) => ({
|
||||||
|
value: type,
|
||||||
|
label: localize(
|
||||||
|
`ui.panel.lovelace.editor.edit_view.types.${type}`
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{ name: "title", selector: { text: {} } },
|
{ name: "title", selector: { text: {} } },
|
||||||
{
|
{
|
||||||
name: "icon",
|
name: "icon",
|
||||||
@ -55,26 +75,6 @@ export class HuiViewEditor extends LitElement {
|
|||||||
boolean: {},
|
boolean: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "type",
|
|
||||||
selector: {
|
|
||||||
select: {
|
|
||||||
options: (
|
|
||||||
[
|
|
||||||
SECTIONS_VIEW_LAYOUT,
|
|
||||||
SIDEBAR_VIEW_LAYOUT,
|
|
||||||
PANEL_VIEW_LAYOUT,
|
|
||||||
MASONRY_VIEW_LAYOUT,
|
|
||||||
] as const
|
|
||||||
).map((type) => ({
|
|
||||||
value: type,
|
|
||||||
label: localize(
|
|
||||||
`ui.panel.lovelace.editor.edit_view.types.${type}`
|
|
||||||
),
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
...(viewType === SECTIONS_VIEW_LAYOUT
|
...(viewType === SECTIONS_VIEW_LAYOUT
|
||||||
? ([
|
? ([
|
||||||
{
|
{
|
||||||
|
@ -833,6 +833,10 @@ class HUIRoot extends LitElement {
|
|||||||
showEditViewDialog(this, {
|
showEditViewDialog(this, {
|
||||||
lovelace: this.lovelace!,
|
lovelace: this.lovelace!,
|
||||||
viewIndex: this._curView as number,
|
viewIndex: this._curView as number,
|
||||||
|
saveCallback: (viewIndex: number, viewConfig: LovelaceViewConfig) => {
|
||||||
|
const path = viewConfig.path || viewIndex;
|
||||||
|
this._navigateToView(path);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,18 @@ const CARD_SORTABLE_OPTIONS: HaSortableOptions = {
|
|||||||
delayOnTouchOnly: true,
|
delayOnTouchOnly: true,
|
||||||
direction: "vertical",
|
direction: "vertical",
|
||||||
invertedSwapThreshold: 0.7,
|
invertedSwapThreshold: 0.7,
|
||||||
|
group: "card",
|
||||||
} as HaSortableOptions;
|
} as HaSortableOptions;
|
||||||
|
|
||||||
|
const IMPORT_MODE_CARD_SORTABLE_OPTIONS: HaSortableOptions = {
|
||||||
|
...CARD_SORTABLE_OPTIONS,
|
||||||
|
sort: false,
|
||||||
|
group: {
|
||||||
|
name: "card",
|
||||||
|
put: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export class GridSection extends LitElement implements LovelaceSectionElement {
|
export class GridSection extends LitElement implements LovelaceSectionElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@ -40,6 +50,8 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public cards: HuiCard[] = [];
|
@property({ attribute: false }) public cards: HuiCard[] = [];
|
||||||
|
|
||||||
|
@property({ attribute: false }) public importOnly = false;
|
||||||
|
|
||||||
@state() _config?: LovelaceSectionConfig;
|
@state() _config?: LovelaceSectionConfig;
|
||||||
|
|
||||||
@state() _dragging = false;
|
@state() _dragging = false;
|
||||||
@ -67,21 +79,29 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
|||||||
|
|
||||||
const editMode = Boolean(this.lovelace?.editMode && !this.isStrategy);
|
const editMode = Boolean(this.lovelace?.editMode && !this.isStrategy);
|
||||||
|
|
||||||
|
const sortableOptions = this.importOnly
|
||||||
|
? IMPORT_MODE_CARD_SORTABLE_OPTIONS
|
||||||
|
: CARD_SORTABLE_OPTIONS;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-sortable
|
<ha-sortable
|
||||||
.disabled=${!editMode}
|
.disabled=${!editMode}
|
||||||
@drag-start=${this._dragStart}
|
@drag-start=${this._dragStart}
|
||||||
@drag-end=${this._dragEnd}
|
@drag-end=${this._dragEnd}
|
||||||
group="card"
|
|
||||||
draggable-selector=".card"
|
draggable-selector=".card"
|
||||||
.rollback=${false}
|
.rollback=${false}
|
||||||
.options=${CARD_SORTABLE_OPTIONS}
|
.options=${sortableOptions}
|
||||||
@item-moved=${this._cardMoved}
|
@item-moved=${this._cardMoved}
|
||||||
@item-added=${this._cardAdded}
|
@item-added=${this._cardAdded}
|
||||||
@item-removed=${this._cardRemoved}
|
@item-removed=${this._cardRemoved}
|
||||||
invert-swap
|
invert-swap
|
||||||
>
|
>
|
||||||
<div class="container ${classMap({ "edit-mode": editMode })}">
|
<div
|
||||||
|
class="container ${classMap({
|
||||||
|
"edit-mode": editMode,
|
||||||
|
"import-only": this.importOnly,
|
||||||
|
})}"
|
||||||
|
>
|
||||||
${repeat(
|
${repeat(
|
||||||
cardsConfig,
|
cardsConfig,
|
||||||
(cardConfig) => this._getKey(cardConfig),
|
(cardConfig) => this._getKey(cardConfig),
|
||||||
@ -117,6 +137,8 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
|||||||
.lovelace=${this.lovelace!}
|
.lovelace=${this.lovelace!}
|
||||||
.path=${cardPath}
|
.path=${cardPath}
|
||||||
.hiddenOverlay=${this._dragging}
|
.hiddenOverlay=${this._dragging}
|
||||||
|
.noEdit=${this.importOnly}
|
||||||
|
.noDuplicate=${this.importOnly}
|
||||||
>
|
>
|
||||||
${card}
|
${card}
|
||||||
</hui-card-edit-mode>
|
</hui-card-edit-mode>
|
||||||
@ -126,7 +148,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
${editMode
|
${editMode && !this.importOnly
|
||||||
? html`
|
? html`
|
||||||
<button
|
<button
|
||||||
class="add"
|
class="add"
|
||||||
@ -216,11 +238,14 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
|||||||
.container.edit-mode {
|
.container.edit-mode {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-radius: var(--ha-card-border-radius, 12px);
|
border-radius: var(--ha-card-border-radius, 12px);
|
||||||
border-start-end-radius: 0px;
|
|
||||||
border: 2px dashed var(--divider-color);
|
border: 2px dashed var(--divider-color);
|
||||||
min-height: var(--row-height);
|
min-height: var(--row-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container.edit-mode:not(.import-only) {
|
||||||
|
border-start-end-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
border-radius: var(--ha-card-border-radius, 12px);
|
border-radius: var(--ha-card-border-radius, 12px);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -43,6 +43,9 @@ export class HuiSection extends ReactiveElement {
|
|||||||
|
|
||||||
@property({ type: Boolean, reflect: true }) public preview = false;
|
@property({ type: Boolean, reflect: true }) public preview = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "import-only" })
|
||||||
|
public importOnly = false;
|
||||||
|
|
||||||
@property({ type: Number }) public index!: number;
|
@property({ type: Number }) public index!: number;
|
||||||
|
|
||||||
@property({ type: Number }) public viewIndex!: number;
|
@property({ type: Number }) public viewIndex!: number;
|
||||||
@ -128,6 +131,9 @@ export class HuiSection extends ReactiveElement {
|
|||||||
element.preview = this.preview;
|
element.preview = this.preview;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (changedProperties.has("importOnly")) {
|
||||||
|
this._layoutElement.importOnly = this.importOnly;
|
||||||
|
}
|
||||||
if (changedProperties.has("_cards")) {
|
if (changedProperties.has("_cards")) {
|
||||||
this._layoutElement.cards = this._cards;
|
this._layoutElement.cards = this._cards;
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,20 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import { repeat } from "lit/directives/repeat";
|
import { repeat } from "lit/directives/repeat";
|
||||||
import { styleMap } from "lit/directives/style-map";
|
import { styleMap } from "lit/directives/style-map";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { clamp } from "../../../common/number/clamp";
|
import { clamp } from "../../../common/number/clamp";
|
||||||
import "../../../components/ha-icon-button";
|
import "../../../components/ha-icon-button";
|
||||||
|
import "../../../components/ha-ripple";
|
||||||
import "../../../components/ha-sortable";
|
import "../../../components/ha-sortable";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
import "../../../components/ha-ripple";
|
|
||||||
import type { LovelaceViewElement } from "../../../data/lovelace";
|
import type { LovelaceViewElement } from "../../../data/lovelace";
|
||||||
|
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||||
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
|
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import type { HuiBadge } from "../badges/hui-badge";
|
import type { HuiBadge } from "../badges/hui-badge";
|
||||||
import "../badges/hui-view-badges";
|
import "../badges/hui-view-badges";
|
||||||
|
import type { HuiCard } from "../cards/hui-card";
|
||||||
import "../components/hui-badge-edit-mode";
|
import "../components/hui-badge-edit-mode";
|
||||||
import { addSection, deleteSection, moveSection } from "../editor/config-util";
|
import { addSection, deleteSection, moveSection } from "../editor/config-util";
|
||||||
import { findLovelaceContainer } from "../editor/lovelace-path";
|
import { findLovelaceContainer } from "../editor/lovelace-path";
|
||||||
@ -42,6 +45,8 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public badges: HuiBadge[] = [];
|
@property({ attribute: false }) public badges: HuiBadge[] = [];
|
||||||
|
|
||||||
|
@property({ attribute: false }) public cards: HuiCard[] = [];
|
||||||
|
|
||||||
@state() private _config?: LovelaceViewConfig;
|
@state() private _config?: LovelaceViewConfig;
|
||||||
|
|
||||||
@state() private _sectionColumnCount = 0;
|
@state() private _sectionColumnCount = 0;
|
||||||
@ -235,11 +240,46 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
|||||||
</button>
|
</button>
|
||||||
`
|
`
|
||||||
: nothing}
|
: nothing}
|
||||||
|
${editMode && this._config?.cards?.length
|
||||||
|
? html`
|
||||||
|
<div class="section imported-cards">
|
||||||
|
<div class="imported-card-header">
|
||||||
|
<p class="title">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.section.imported_cards_title"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p class="subtitle">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.section.imported_cards_description"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<hui-section
|
||||||
|
.lovelace=${this.lovelace}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.config=${this._importedCardSectionConfig(
|
||||||
|
this._config.cards
|
||||||
|
)}
|
||||||
|
.viewIndex=${this.index}
|
||||||
|
preview
|
||||||
|
import-only
|
||||||
|
></hui-section>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
</ha-sortable>
|
</ha-sortable>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _importedCardSectionConfig = memoizeOne(
|
||||||
|
(cards: LovelaceCardConfig[]) => ({
|
||||||
|
type: "grid",
|
||||||
|
cards,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
private _createSection(): void {
|
private _createSection(): void {
|
||||||
const newConfig = addSection(this.lovelace!.config, this.index!, {
|
const newConfig = addSection(this.lovelace!.config, this.index!, {
|
||||||
type: "grid",
|
type: "grid",
|
||||||
@ -432,6 +472,33 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
|||||||
--mdc-icon-size: 20px;
|
--mdc-icon-size: 20px;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.imported-cards {
|
||||||
|
--column-span: var(--column-count);
|
||||||
|
--row-span: 1;
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imported-card-header {
|
||||||
|
margin-top: 24px;
|
||||||
|
padding: 16px 8px;
|
||||||
|
border-top: 2px dashed var(--divider-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.imported-card-header .title {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
.imported-card-header .subtitle {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5611,14 +5611,18 @@
|
|||||||
"visibility": {
|
"visibility": {
|
||||||
"select_users": "Select which users should see this view in the navigation"
|
"select_users": "Select which users should see this view in the navigation"
|
||||||
},
|
},
|
||||||
"type": "View type",
|
"type": "Layout",
|
||||||
"type_warning_sections": "You can not change your view to use the 'sections' view type because migration is not supported yet. Start from scratch with a new view if you want to experiment with the 'sections' view.",
|
"convert_view": "Convert",
|
||||||
"type_warning_others": "You can not change your view to an other type because migration is not supported yet. Start from scratch with a new view if you want to use another view type.",
|
"convert_view_title": "Convert view layout",
|
||||||
|
"convert_view_text": "It will create a new view using sections. This current view will stay untouched. All your cards will be imported so you can rearrange them freely.",
|
||||||
|
"convert_view_action": "Create",
|
||||||
|
"card_to_section_convert": "Convert your view to a section view.",
|
||||||
|
"section_to_card_not_supported": "You can not change your section view to an other type. Start from scratch with a new view if you want to use another view type.",
|
||||||
"types": {
|
"types": {
|
||||||
|
"sections": "Sections (default)",
|
||||||
"masonry": "Masonry",
|
"masonry": "Masonry",
|
||||||
"sidebar": "Sidebar",
|
"sidebar": "Sidebar",
|
||||||
"panel": "Panel (single card)",
|
"panel": "Panel (single card)"
|
||||||
"sections": "Sections"
|
|
||||||
},
|
},
|
||||||
"subview": "Subview",
|
"subview": "Subview",
|
||||||
"max_columns": "Max number of sections wide",
|
"max_columns": "Max number of sections wide",
|
||||||
@ -5704,7 +5708,9 @@
|
|||||||
"move_card": {
|
"move_card": {
|
||||||
"header": "Choose a view to move the card to",
|
"header": "Choose a view to move the card to",
|
||||||
"strategy_error_title": "Impossible to move the card",
|
"strategy_error_title": "Impossible to move the card",
|
||||||
"strategy_error_text_strategy": "Moving a card to an auto generated view is not supported."
|
"strategy_error_text_strategy": "Moving a card to an auto generated view is not supported.",
|
||||||
|
"success": "Card moved successfully",
|
||||||
|
"error": "Error while moving card"
|
||||||
},
|
},
|
||||||
"change_position": {
|
"change_position": {
|
||||||
"title": "Change card position",
|
"title": "Change card position",
|
||||||
@ -5723,8 +5729,8 @@
|
|||||||
"add_card": "[%key:ui::panel::lovelace::editor::edit_card::add%]",
|
"add_card": "[%key:ui::panel::lovelace::editor::edit_card::add%]",
|
||||||
"create_section": "Create section",
|
"create_section": "Create section",
|
||||||
"default_section_title": "New section",
|
"default_section_title": "New section",
|
||||||
"imported_card_section_title_view": "Imported cards from ''{view_title}'' view",
|
"imported_cards_title": "Imported cards",
|
||||||
"imported_card_section_title_default": "Imported cards from another view"
|
"imported_cards_description": "These cards are imported from another view. They will only be displayed in edit mode. Move them into sections to display them in your view."
|
||||||
},
|
},
|
||||||
"delete_section": {
|
"delete_section": {
|
||||||
"title": "Delete section",
|
"title": "Delete section",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user