mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-02 14:07:55 +00:00
Use overflow menu for global toggle
This commit is contained in:
parent
b87f44ff74
commit
14308c9057
@ -1,4 +1,5 @@
|
|||||||
import { Button } from "@material/mwc-button";
|
import { Button } from "@material/mwc-button";
|
||||||
|
import { Corner } from "@material/web/menu/menu";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { customElement, property, query } from "lit/decorators";
|
||||||
import { FOCUS_TARGET } from "../dialogs/make-dialog-manager";
|
import { FOCUS_TARGET } from "../dialogs/make-dialog-manager";
|
||||||
@ -14,8 +15,20 @@ export class HaButtonMenuNew extends LitElement {
|
|||||||
|
|
||||||
@property() public positioning?: "fixed" | "absolute" | "popover";
|
@property() public positioning?: "fixed" | "absolute" | "popover";
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "has-overflow" }) public hasOverflow =
|
@property({ type: Boolean, attribute: "no-horizontal-flip" })
|
||||||
false;
|
public noHorizontalFlip = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "no-vertical-flip" })
|
||||||
|
public noVerticalFlip = false;
|
||||||
|
|
||||||
|
@property({ attribute: "anchor-corner" })
|
||||||
|
public anchorCorner: Corner = Corner.END_START;
|
||||||
|
|
||||||
|
@property({ attribute: "menu-corner" })
|
||||||
|
public menuCorner: Corner = Corner.START_START;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "has-overflow" })
|
||||||
|
public hasOverflow = false;
|
||||||
|
|
||||||
@query("ha-menu", true) private _menu!: HaMenu;
|
@query("ha-menu", true) private _menu!: HaMenu;
|
||||||
|
|
||||||
@ -39,6 +52,10 @@ export class HaButtonMenuNew extends LitElement {
|
|||||||
<ha-menu
|
<ha-menu
|
||||||
.positioning=${this.positioning}
|
.positioning=${this.positioning}
|
||||||
.hasOverflow=${this.hasOverflow}
|
.hasOverflow=${this.hasOverflow}
|
||||||
|
.anchorCorner=${this.anchorCorner}
|
||||||
|
.menuCorner=${this.menuCorner}
|
||||||
|
.noVerticalFlip=${this.noVerticalFlip}
|
||||||
|
.noHorizontalFlip=${this.noHorizontalFlip}
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</ha-menu>
|
</ha-menu>
|
||||||
|
25
src/panels/lovelace/common/compute-card-name.ts
Normal file
25
src/panels/lovelace/common/compute-card-name.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { LocalizeFunc } from "../../../common/translations/localize";
|
||||||
|
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
|
import {
|
||||||
|
getCustomCardEntry,
|
||||||
|
isCustomType,
|
||||||
|
stripCustomPrefix,
|
||||||
|
} from "../../../data/lovelace_custom_cards";
|
||||||
|
|
||||||
|
export const computeCardName = (
|
||||||
|
config: LovelaceCardConfig,
|
||||||
|
localize: LocalizeFunc
|
||||||
|
): string | undefined => {
|
||||||
|
if (isCustomType(config.type)) {
|
||||||
|
// prettier-ignore
|
||||||
|
let cardName = getCustomCardEntry(
|
||||||
|
stripCustomPrefix(config.type)
|
||||||
|
)?.name;
|
||||||
|
// Trim names that end in " Card" so as not to redundantly duplicate it
|
||||||
|
if (cardName?.toLowerCase().endsWith(" card")) {
|
||||||
|
cardName = cardName.substring(0, cardName.length - 5);
|
||||||
|
}
|
||||||
|
return cardName;
|
||||||
|
}
|
||||||
|
return localize(`ui.panel.lovelace.editor.card.${config.type}.name`);
|
||||||
|
};
|
@ -1,4 +1,12 @@
|
|||||||
import { mdiClose, mdiHelpCircle } from "@mdi/js";
|
import "@material/mwc-list";
|
||||||
|
import "@material/web/divider/divider";
|
||||||
|
import {
|
||||||
|
mdiCheck,
|
||||||
|
mdiClose,
|
||||||
|
mdiDotsVertical,
|
||||||
|
mdiHelpCircle,
|
||||||
|
mdiOpenInNew,
|
||||||
|
} from "@mdi/js";
|
||||||
import deepFreeze from "deep-freeze";
|
import deepFreeze from "deep-freeze";
|
||||||
import {
|
import {
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
@ -12,25 +20,23 @@ import { customElement, property, query, state } from "lit/decorators";
|
|||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
import "../../../../components/ha-button";
|
||||||
|
import "../../../../components/ha-button-menu-new";
|
||||||
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";
|
||||||
import "../../../../components/ha-icon-button";
|
import "../../../../components/ha-icon-button";
|
||||||
|
import "../../../../components/ha-menu-item";
|
||||||
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
||||||
import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
|
import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
|
||||||
import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
|
import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
|
||||||
import {
|
|
||||||
getCustomCardEntry,
|
|
||||||
isCustomType,
|
|
||||||
stripCustomPrefix,
|
|
||||||
} from "../../../../data/lovelace_custom_cards";
|
|
||||||
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||||
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
||||||
import { haStyleDialog } from "../../../../resources/styles";
|
import { haStyleDialog } from "../../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
|
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
|
||||||
import "../../cards/hui-card";
|
import "../../cards/hui-card";
|
||||||
|
import { computeCardName } from "../../common/compute-card-name";
|
||||||
import "../../sections/hui-section";
|
import "../../sections/hui-section";
|
||||||
import { addCard, replaceCard } from "../config-util";
|
import { addCard, replaceCard } from "../config-util";
|
||||||
import { getCardDocumentationURL } from "../get-dashboard-documentation-url";
|
import { getCardDocumentationURL } from "../get-dashboard-documentation-url";
|
||||||
@ -73,12 +79,10 @@ export class HuiDialogEditCard
|
|||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
@state() private _guiModeAvailable? = true;
|
|
||||||
|
|
||||||
@query("hui-card-editor")
|
@query("hui-card-editor")
|
||||||
private _cardEditorEl?: HuiCardElementEditor;
|
private _cardEditorEl?: HuiCardElementEditor;
|
||||||
|
|
||||||
@state() private _GUImode = true;
|
@state() private _yamlMode = true;
|
||||||
|
|
||||||
@state() private _documentationURL?: string;
|
@state() private _documentationURL?: string;
|
||||||
|
|
||||||
@ -88,7 +92,7 @@ export class HuiDialogEditCard
|
|||||||
|
|
||||||
public async showDialog(params: EditCardDialogParams): Promise<void> {
|
public async showDialog(params: EditCardDialogParams): Promise<void> {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._GUImode = true;
|
this._yamlMode = true;
|
||||||
this._guiModeAvailable = true;
|
this._guiModeAvailable = true;
|
||||||
|
|
||||||
const containerConfig = findLovelaceContainer(
|
const containerConfig = findLovelaceContainer(
|
||||||
@ -168,21 +172,7 @@ export class HuiDialogEditCard
|
|||||||
|
|
||||||
let heading: string;
|
let heading: string;
|
||||||
if (this._cardConfig && this._cardConfig.type) {
|
if (this._cardConfig && this._cardConfig.type) {
|
||||||
let cardName: string | undefined;
|
const cardName = computeCardName(this._cardConfig, this.hass!.localize);
|
||||||
if (isCustomType(this._cardConfig.type)) {
|
|
||||||
// prettier-ignore
|
|
||||||
cardName = getCustomCardEntry(
|
|
||||||
stripCustomPrefix(this._cardConfig.type)
|
|
||||||
)?.name;
|
|
||||||
// Trim names that end in " Card" so as not to redundantly duplicate it
|
|
||||||
if (cardName?.toLowerCase().endsWith(" card")) {
|
|
||||||
cardName = cardName.substring(0, cardName.length - 5);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cardName = this.hass!.localize(
|
|
||||||
`ui.panel.lovelace.editor.card.${this._cardConfig.type}.name`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
heading = this.hass!.localize(
|
heading = this.hass!.localize(
|
||||||
"ui.panel.lovelace.editor.edit_card.typed_header",
|
"ui.panel.lovelace.editor.edit_card.typed_header",
|
||||||
{ type: cardName }
|
{ type: cardName }
|
||||||
@ -218,20 +208,70 @@ export class HuiDialogEditCard
|
|||||||
.path=${mdiClose}
|
.path=${mdiClose}
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
<span slot="title" @click=${this._enlarge}>${heading}</span>
|
<span slot="title" @click=${this._enlarge}>${heading}</span>
|
||||||
${this._documentationURL !== undefined
|
<ha-button-menu-new
|
||||||
? html`
|
slot="actionItems"
|
||||||
<a
|
anchor-corner="end-end"
|
||||||
slot="actionItems"
|
menu-corner="start-end"
|
||||||
href=${this._documentationURL}
|
>
|
||||||
title=${this.hass!.localize("ui.panel.lovelace.menu.help")}
|
<ha-icon-button
|
||||||
target="_blank"
|
slot="trigger"
|
||||||
rel="noreferrer"
|
.label=${this.hass.localize("ui.common.menu")}
|
||||||
dir=${computeRTLDirection(this.hass)}
|
.path=${mdiDotsVertical}
|
||||||
>
|
>
|
||||||
<ha-icon-button .path=${mdiHelpCircle}></ha-icon-button>
|
</ha-icon-button>
|
||||||
</a>
|
<ha-menu-item @click=${this._enableGuiMode}>
|
||||||
`
|
${!this._yamlMode
|
||||||
: nothing}
|
? html`
|
||||||
|
<ha-svg-icon
|
||||||
|
class="selected_menu_item"
|
||||||
|
slot="start"
|
||||||
|
.path=${mdiCheck}
|
||||||
|
></ha-svg-icon>
|
||||||
|
`
|
||||||
|
: html`<span class="blank-icon" slot="start"></span>`}
|
||||||
|
<div slot="headline">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_card.edit_ui"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ha-menu-item>
|
||||||
|
<ha-menu-item @click=${this._enableYamlMode}>
|
||||||
|
${this._yamlMode
|
||||||
|
? html`
|
||||||
|
<ha-svg-icon
|
||||||
|
class="selected_menu_item"
|
||||||
|
slot="start"
|
||||||
|
.path=${mdiCheck}
|
||||||
|
></ha-svg-icon>
|
||||||
|
`
|
||||||
|
: html`<span class="blank-icon" slot="start"></span>`}
|
||||||
|
<div slot="headline">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_card.edit_yaml"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ha-menu-item>
|
||||||
|
${this._documentationURL !== undefined
|
||||||
|
? html`
|
||||||
|
<md-divider role="separator" tabindex="-1"></md-divider>
|
||||||
|
<ha-menu-item
|
||||||
|
type="link"
|
||||||
|
href=${this._documentationURL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="start"
|
||||||
|
.path=${mdiHelpCircle}
|
||||||
|
></ha-svg-icon>
|
||||||
|
<div slot="headline">
|
||||||
|
${this.hass!.localize("ui.panel.lovelace.menu.help")}
|
||||||
|
</div>
|
||||||
|
<ha-svg-icon slot="end" .path=${mdiOpenInNew}></ha-svg-icon>
|
||||||
|
</ha-menu-item>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
|
</ha-button-menu-new>
|
||||||
</ha-dialog-header>
|
</ha-dialog-header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="element-editor">
|
<div class="element-editor">
|
||||||
@ -275,49 +315,44 @@ export class HuiDialogEditCard
|
|||||||
: ``}
|
: ``}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
${this._cardConfig !== undefined
|
<ha-button
|
||||||
|
@click=${this._cancel}
|
||||||
|
slot="secondaryAction"
|
||||||
|
dialogInitialFocus
|
||||||
|
>
|
||||||
|
${this.hass!.localize("ui.common.cancel")}
|
||||||
|
</ha-button>
|
||||||
|
${this._cardConfig !== undefined && this._dirty
|
||||||
? html`
|
? html`
|
||||||
<mwc-button
|
<ha-button
|
||||||
slot="secondaryAction"
|
slot="primaryAction"
|
||||||
@click=${this._toggleMode}
|
?disabled=${!this._canSave || this._saving}
|
||||||
.disabled=${!this._guiModeAvailable}
|
@click=${this._save}
|
||||||
class="gui-mode-button"
|
|
||||||
>
|
>
|
||||||
${this.hass!.localize(
|
${this._saving
|
||||||
!this._cardEditorEl || this._GUImode
|
? html`
|
||||||
? "ui.panel.lovelace.editor.edit_card.show_code_editor"
|
<ha-circular-progress
|
||||||
: "ui.panel.lovelace.editor.edit_card.show_visual_editor"
|
indeterminate
|
||||||
)}
|
aria-label="Saving"
|
||||||
</mwc-button>
|
size="small"
|
||||||
|
></ha-circular-progress>
|
||||||
|
`
|
||||||
|
: this.hass!.localize("ui.common.save")}
|
||||||
|
</ha-button>
|
||||||
`
|
`
|
||||||
: ""}
|
: nothing}
|
||||||
<div slot="primaryAction" @click=${this._save}>
|
|
||||||
<mwc-button @click=${this._cancel} dialogInitialFocus>
|
|
||||||
${this.hass!.localize("ui.common.cancel")}
|
|
||||||
</mwc-button>
|
|
||||||
${this._cardConfig !== undefined && this._dirty
|
|
||||||
? html`
|
|
||||||
<mwc-button
|
|
||||||
?disabled=${!this._canSave || this._saving}
|
|
||||||
@click=${this._save}
|
|
||||||
>
|
|
||||||
${this._saving
|
|
||||||
? html`
|
|
||||||
<ha-circular-progress
|
|
||||||
indeterminate
|
|
||||||
aria-label="Saving"
|
|
||||||
size="small"
|
|
||||||
></ha-circular-progress>
|
|
||||||
`
|
|
||||||
: this.hass!.localize("ui.common.save")}
|
|
||||||
</mwc-button>
|
|
||||||
`
|
|
||||||
: ``}
|
|
||||||
</div>
|
|
||||||
</ha-dialog>
|
</ha-dialog>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _enableGuiMode() {
|
||||||
|
this._yamlMode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _enableYamlMode() {
|
||||||
|
this._yamlMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
private _enlarge() {
|
private _enlarge() {
|
||||||
this.large = !this.large;
|
this.large = !this.large;
|
||||||
}
|
}
|
||||||
@ -335,14 +370,10 @@ export class HuiDialogEditCard
|
|||||||
|
|
||||||
private _handleGUIModeChanged(ev: HASSDomEvent<GUIModeChangedEvent>): void {
|
private _handleGUIModeChanged(ev: HASSDomEvent<GUIModeChangedEvent>): void {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this._GUImode = ev.detail.guiMode;
|
this._yamlMode = ev.detail.guiMode;
|
||||||
this._guiModeAvailable = ev.detail.guiModeAvailable;
|
this._guiModeAvailable = ev.detail.guiModeAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _toggleMode(): void {
|
|
||||||
this._cardEditorEl?.toggleMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _opened() {
|
private _opened() {
|
||||||
window.addEventListener("dialog-closed", this._enableEscapeKeyClose);
|
window.addEventListener("dialog-closed", this._enableEscapeKeyClose);
|
||||||
window.addEventListener("hass-more-info", this._disableEscapeKeyClose);
|
window.addEventListener("hass-more-info", this._disableEscapeKeyClose);
|
||||||
@ -563,6 +594,12 @@ export class HuiDialogEditCard
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.selected_menu_item {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
.blank-icon {
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user