mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 19:26:36 +00:00
Migrate title section to heading (#22017)
* Remove title from UI * Migrate section title to heading card * Remove title from edit section dialog * Update src/panels/lovelace/views/hui-sections-view.ts * Simplify delete section dialog
This commit is contained in:
parent
0840d8a10e
commit
d25f72524b
@ -36,6 +36,7 @@ import { HassElement } from "../../../../src/state/hass-element";
|
||||
import { castContext } from "../cast_context";
|
||||
import "./hc-launch-screen";
|
||||
import { getPanelTitleFromUrlPath } from "../../../../src/data/panel";
|
||||
import { checkLovelaceConfig } from "../../../../src/panels/lovelace/common/check-lovelace-config";
|
||||
|
||||
const DEFAULT_CONFIG: LovelaceDashboardStrategyConfig = {
|
||||
strategy: {
|
||||
@ -365,7 +366,9 @@ export class HcMain extends HassElement {
|
||||
this._urlPath || "lovelace"
|
||||
);
|
||||
castContext.setApplicationState(title || "");
|
||||
this._lovelaceConfig = lovelaceConfig;
|
||||
this._lovelaceConfig = checkLovelaceConfig(
|
||||
lovelaceConfig
|
||||
) as LovelaceConfig;
|
||||
}
|
||||
|
||||
private _handleShowDemo(_msg: ShowDemoMessage) {
|
||||
|
@ -3,10 +3,13 @@ import type { LovelaceCardConfig } from "./card";
|
||||
import type { LovelaceStrategyConfig } from "./strategy";
|
||||
|
||||
export interface LovelaceBaseSectionConfig {
|
||||
title?: string;
|
||||
visibility?: Condition[];
|
||||
column_span?: number;
|
||||
row_span?: number;
|
||||
/**
|
||||
* @deprecated Use heading card instead.
|
||||
*/
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export interface LovelaceSectionConfig extends LovelaceBaseSectionConfig {
|
||||
|
68
src/panels/lovelace/common/check-lovelace-config.ts
Normal file
68
src/panels/lovelace/common/check-lovelace-config.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import {
|
||||
isStrategySection,
|
||||
LovelaceSectionRawConfig,
|
||||
} from "../../../data/lovelace/config/section";
|
||||
import {
|
||||
isStrategyDashboard,
|
||||
LovelaceRawConfig,
|
||||
} from "../../../data/lovelace/config/types";
|
||||
import {
|
||||
isStrategyView,
|
||||
LovelaceViewRawConfig,
|
||||
} from "../../../data/lovelace/config/view";
|
||||
|
||||
export const checkLovelaceConfig = (
|
||||
config: LovelaceRawConfig
|
||||
): LovelaceRawConfig => {
|
||||
if (isStrategyDashboard(config)) {
|
||||
return config;
|
||||
}
|
||||
|
||||
const updatedConfig = { ...config };
|
||||
|
||||
if (updatedConfig.views) {
|
||||
updatedConfig.views = updatedConfig.views.map(checkViewConfig);
|
||||
}
|
||||
|
||||
return updatedConfig;
|
||||
};
|
||||
|
||||
export const checkViewConfig = (
|
||||
view: LovelaceViewRawConfig
|
||||
): LovelaceViewRawConfig => {
|
||||
if (isStrategyView(view)) {
|
||||
return view;
|
||||
}
|
||||
|
||||
const updatedView = { ...view };
|
||||
|
||||
// Remove empty badges
|
||||
if (updatedView.badges && !updatedView.badges.every(Boolean)) {
|
||||
updatedView.badges = updatedView.badges!.filter(Boolean);
|
||||
}
|
||||
|
||||
// Migrate sections
|
||||
if (updatedView.sections) {
|
||||
updatedView.sections = updatedView.sections!.map(checkSectionConfig);
|
||||
}
|
||||
|
||||
return updatedView;
|
||||
};
|
||||
|
||||
export const checkSectionConfig = (
|
||||
section: LovelaceSectionRawConfig
|
||||
): LovelaceSectionRawConfig => {
|
||||
const updatedSection = { ...section };
|
||||
|
||||
// Move title to a heading card
|
||||
if (section.title) {
|
||||
// Only add card if it's not a strategy section
|
||||
if (!isStrategySection(updatedSection)) {
|
||||
const card = { type: "heading", heading: updatedSection.title };
|
||||
updatedSection.cards = [card, ...(updatedSection.cards || [])];
|
||||
}
|
||||
|
||||
delete updatedSection.title;
|
||||
}
|
||||
return updatedSection;
|
||||
};
|
@ -11,7 +11,6 @@ import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
|
||||
type SettingsData = {
|
||||
title: string;
|
||||
column_span?: number;
|
||||
};
|
||||
|
||||
@ -26,10 +25,6 @@ export class HuiDialogEditSection extends LitElement {
|
||||
private _schema = memoizeOne(
|
||||
(maxColumns: number) =>
|
||||
[
|
||||
{
|
||||
name: "title",
|
||||
selector: { text: {} },
|
||||
},
|
||||
{
|
||||
name: "column_span",
|
||||
selector: {
|
||||
@ -45,7 +40,6 @@ export class HuiDialogEditSection extends LitElement {
|
||||
|
||||
render() {
|
||||
const data: SettingsData = {
|
||||
title: this.config.title || "",
|
||||
column_span: this.config.column_span || 1,
|
||||
};
|
||||
|
||||
@ -83,14 +77,9 @@ export class HuiDialogEditSection extends LitElement {
|
||||
|
||||
const newConfig: LovelaceSectionRawConfig = {
|
||||
...this.config,
|
||||
title: newData.title,
|
||||
column_span: newData.column_span,
|
||||
};
|
||||
|
||||
if (!newConfig.title) {
|
||||
delete newConfig.title;
|
||||
}
|
||||
|
||||
fireEvent(this, "value-changed", { value: newConfig });
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,6 @@ import {
|
||||
LovelaceRawConfig,
|
||||
saveConfig,
|
||||
} from "../../data/lovelace/config/types";
|
||||
import {
|
||||
isStrategyView,
|
||||
LovelaceViewConfig,
|
||||
} from "../../data/lovelace/config/view";
|
||||
import { fetchResources } from "../../data/lovelace/resource";
|
||||
import { WindowWithPreloads } from "../../data/preloads";
|
||||
import "../../layouts/hass-error-screen";
|
||||
@ -30,6 +26,7 @@ import "../../layouts/hass-loading-screen";
|
||||
import { HomeAssistant, PanelInfo, Route } from "../../types";
|
||||
import { showToast } from "../../util/toast";
|
||||
import { loadLovelaceResources } from "./common/load-resources";
|
||||
import { checkLovelaceConfig } from "./common/check-lovelace-config";
|
||||
import { showSaveDialog } from "./editor/show-save-config-dialog";
|
||||
import "./hui-root";
|
||||
import { generateLovelaceDashboardStrategy } from "./strategies/get-strategy";
|
||||
@ -321,26 +318,8 @@ export class LovelacePanel extends LitElement {
|
||||
}
|
||||
|
||||
private _checkLovelaceConfig(config: LovelaceRawConfig) {
|
||||
// Somehow there can be badges with value null, we remove those
|
||||
if (isStrategyDashboard(config)) {
|
||||
return config;
|
||||
}
|
||||
let checkedConfig = !Object.isFrozen(config) ? config : undefined;
|
||||
config.views.forEach((view, index) => {
|
||||
if (isStrategyView(view)) {
|
||||
return;
|
||||
}
|
||||
if (view.badges && !view.badges.every(Boolean)) {
|
||||
checkedConfig = checkedConfig || {
|
||||
...config,
|
||||
views: [...config.views],
|
||||
};
|
||||
const updatedView = { ...view } as LovelaceViewConfig;
|
||||
updatedView.badges = view.badges.filter(Boolean);
|
||||
checkedConfig.views[index] = updatedView;
|
||||
}
|
||||
});
|
||||
return checkedConfig ? deepFreeze(checkedConfig) : config;
|
||||
const checkedConfig = checkLovelaceConfig(config);
|
||||
return deepFreeze(checkedConfig);
|
||||
}
|
||||
|
||||
private _setLovelaceConfig(
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ResizeController } from "@lit-labs/observers/resize-controller";
|
||||
import { mdiArrowAll, mdiDelete, mdiPencil, mdiViewGridPlus } from "@mdi/js";
|
||||
import { mdiDelete, mdiDrag, mdiPencil, mdiViewGridPlus } from "@mdi/js";
|
||||
import {
|
||||
CSSResultGroup,
|
||||
LitElement,
|
||||
@ -182,26 +182,16 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
})}
|
||||
>
|
||||
${
|
||||
sectionConfig?.title || this.lovelace?.editMode
|
||||
this.lovelace?.editMode
|
||||
? html`
|
||||
<div class="section-header">
|
||||
<h2
|
||||
class="section-title ${classMap({
|
||||
placeholder: !sectionConfig?.title,
|
||||
})}"
|
||||
>
|
||||
${sectionConfig?.title ||
|
||||
this.hass.localize(
|
||||
"ui.panel.lovelace.editor.section.unnamed_section"
|
||||
)}
|
||||
</h2>
|
||||
${editMode
|
||||
? html`
|
||||
<div class="section-actions">
|
||||
<ha-svg-icon
|
||||
aria-hidden="true"
|
||||
class="handle"
|
||||
.path=${mdiArrowAll}
|
||||
.path=${mdiDrag}
|
||||
></ha-svg-icon>
|
||||
<ha-icon-button
|
||||
.label=${this.hass.localize(
|
||||
@ -256,7 +246,12 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
private _createSection(): void {
|
||||
const newConfig = addSection(this.lovelace!.config, this.index!, {
|
||||
type: "grid",
|
||||
cards: [],
|
||||
cards: [
|
||||
{
|
||||
type: "heading",
|
||||
heading: "New Section",
|
||||
},
|
||||
],
|
||||
});
|
||||
this.lovelace!.saveConfig(newConfig);
|
||||
}
|
||||
@ -281,20 +276,15 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
|
||||
const section = findLovelaceContainer(this.lovelace!.config, path);
|
||||
|
||||
const title = section.title?.trim();
|
||||
const cardCount = "cards" in section && section.cards?.length;
|
||||
|
||||
if (title || cardCount) {
|
||||
const named = title ? "named" : "unnamed";
|
||||
const type = cardCount ? "cards" : "only";
|
||||
|
||||
if (cardCount) {
|
||||
const confirm = await showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.lovelace.editor.delete_section.title"
|
||||
),
|
||||
text: this.hass.localize(
|
||||
`ui.panel.lovelace.editor.delete_section.text_${named}_section_${type}`,
|
||||
{ name: title }
|
||||
`ui.panel.lovelace.editor.delete_section.text`
|
||||
),
|
||||
confirmText: this.hass.localize("ui.common.delete"),
|
||||
destructive: true,
|
||||
@ -380,7 +370,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
}
|
||||
|
||||
.create-section {
|
||||
margin-top: calc(var(--row-height) + var(--row-gap));
|
||||
margin-top: 36px;
|
||||
outline: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
@ -408,35 +398,16 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
|
||||
.section-header {
|
||||
position: relative;
|
||||
height: var(--row-height);
|
||||
margin-bottom: var(--row-gap);
|
||||
height: 34px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
color: var(--primary-text-color);
|
||||
font-size: 20px;
|
||||
font-weight: normal;
|
||||
margin: 0px;
|
||||
letter-spacing: 0.1px;
|
||||
line-height: 32px;
|
||||
text-align: var(--ha-view-sections-title-text-align, start);
|
||||
min-height: 32px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10px 10px;
|
||||
}
|
||||
|
||||
.section-title.placeholder {
|
||||
color: var(--secondary-text-color);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.section-actions {
|
||||
position: absolute;
|
||||
height: 36px;
|
||||
bottom: calc(-1 * var(--row-gap) - 2px);
|
||||
bottom: -2px;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: initial;
|
||||
@ -445,7 +416,6 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
background-color: rgba(var(--rgb-card-background-color), 0.3);
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
border-bottom-left-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
|
@ -5655,17 +5655,13 @@
|
||||
"strategy_type": "strategy"
|
||||
},
|
||||
"section": {
|
||||
"unnamed_section": "Unnamed section",
|
||||
"add_badge": "Add badge",
|
||||
"add_card": "[%key:ui::panel::lovelace::editor::edit_card::add%]",
|
||||
"create_section": "Create section"
|
||||
},
|
||||
"delete_section": {
|
||||
"title": "Delete section",
|
||||
"text_named_section_only": "''{name}'' section will be deleted.",
|
||||
"text_unnamed_section_only": "This section will be deleted.",
|
||||
"text_named_section_cards": "''{name}'' section and all its cards will be deleted.",
|
||||
"text_unnamed_section_cards": "This section and all its cards will be deleted."
|
||||
"text": "This section and all its cards will be deleted."
|
||||
},
|
||||
"edit_section": {
|
||||
"header": "Edit section",
|
||||
|
Loading…
x
Reference in New Issue
Block a user