mirror of
https://github.com/home-assistant/frontend.git
synced 2025-10-16 15:19:51 +00:00
Compare commits
5 Commits
section-vi
...
target-pic
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0ae2dc28d2 | ||
![]() |
5000a207a1 | ||
![]() |
402dd5c71b | ||
![]() |
e35b155c66 | ||
![]() |
437d02c12f |
@@ -1,9 +1,9 @@
|
||||
import { styles as elevatedStyles } from "@material/web/chips/internal/elevated-styles";
|
||||
import { FilterChip } from "@material/web/chips/internal/filter-chip";
|
||||
import { styles } from "@material/web/chips/internal/filter-styles";
|
||||
import { styles as selectableStyles } from "@material/web/chips/internal/selectable-styles";
|
||||
import { styles as sharedStyles } from "@material/web/chips/internal/shared-styles";
|
||||
import { styles as trailingIconStyles } from "@material/web/chips/internal/trailing-icon-styles";
|
||||
import { styles as elevatedStyles } from "@material/web/chips/internal/elevated-styles";
|
||||
import { css, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
|
||||
@@ -30,6 +30,7 @@ export class HaFilterChip extends FilterChip {
|
||||
var(--rgb-primary-text-color),
|
||||
0.15
|
||||
);
|
||||
border-radius: var(--ha-border-radius-md);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -1,152 +0,0 @@
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import type { ImageSelector } from "../../data/selector";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import "../ha-icon-button";
|
||||
import "../ha-textarea";
|
||||
import "../ha-textfield";
|
||||
import "../ha-picture-upload";
|
||||
import "../ha-radio";
|
||||
import "../ha-formfield";
|
||||
import type { HaPictureUpload } from "../ha-picture-upload";
|
||||
import { URL_PREFIX } from "../../data/image_upload";
|
||||
|
||||
@customElement("ha-selector-image")
|
||||
export class HaImageSelector extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public value?: any;
|
||||
|
||||
@property() public name?: string;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@property() public placeholder?: string;
|
||||
|
||||
@property() public helper?: string;
|
||||
|
||||
@property({ attribute: false }) public selector!: ImageSelector;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@property({ type: Boolean }) public required = true;
|
||||
|
||||
@state() private showUpload = false;
|
||||
|
||||
protected firstUpdated(changedProps): void {
|
||||
super.firstUpdated(changedProps);
|
||||
|
||||
if (!this.value || this.value.startsWith(URL_PREFIX)) {
|
||||
this.showUpload = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<div>
|
||||
<label>
|
||||
${this.hass.localize(
|
||||
"ui.components.selectors.image.select_image_with_label",
|
||||
{
|
||||
label:
|
||||
this.label ||
|
||||
this.hass.localize("ui.components.selectors.image.image"),
|
||||
}
|
||||
)}
|
||||
<ha-formfield
|
||||
.label=${this.hass.localize("ui.components.selectors.image.upload")}
|
||||
>
|
||||
<ha-radio
|
||||
name="mode"
|
||||
value="upload"
|
||||
.checked=${this.showUpload}
|
||||
@change=${this._radioGroupPicked}
|
||||
></ha-radio>
|
||||
</ha-formfield>
|
||||
<ha-formfield
|
||||
.label=${this.hass.localize("ui.components.selectors.image.url")}
|
||||
>
|
||||
<ha-radio
|
||||
name="mode"
|
||||
value="url"
|
||||
.checked=${!this.showUpload}
|
||||
@change=${this._radioGroupPicked}
|
||||
></ha-radio>
|
||||
</ha-formfield>
|
||||
</label>
|
||||
${!this.showUpload
|
||||
? html`
|
||||
<ha-textfield
|
||||
.name=${this.name}
|
||||
.value=${this.value || ""}
|
||||
.placeholder=${this.placeholder || ""}
|
||||
.helper=${this.helper}
|
||||
helperPersistent
|
||||
.disabled=${this.disabled}
|
||||
@input=${this._handleChange}
|
||||
.label=${this.label || ""}
|
||||
.required=${this.required}
|
||||
></ha-textfield>
|
||||
`
|
||||
: html`
|
||||
<ha-picture-upload
|
||||
.hass=${this.hass}
|
||||
.value=${this.value?.startsWith(URL_PREFIX) ? this.value : null}
|
||||
.original=${this.selector.image?.original}
|
||||
.cropOptions=${this.selector.image?.crop}
|
||||
select-media
|
||||
@change=${this._pictureChanged}
|
||||
></ha-picture-upload>
|
||||
`}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _radioGroupPicked(ev): void {
|
||||
this.showUpload = ev.target.value === "upload";
|
||||
}
|
||||
|
||||
private _pictureChanged(ev) {
|
||||
const value = (ev.target as HaPictureUpload).value;
|
||||
|
||||
fireEvent(this, "value-changed", { value: value ?? undefined });
|
||||
}
|
||||
|
||||
private _handleChange(ev) {
|
||||
let value = ev.target.value;
|
||||
if (this.value === value) {
|
||||
return;
|
||||
}
|
||||
if (value === "" && !this.required) {
|
||||
value = undefined;
|
||||
}
|
||||
|
||||
fireEvent(this, "value-changed", { value });
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
ha-textarea,
|
||||
ha-textfield {
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-selector-image": HaImageSelector;
|
||||
}
|
||||
}
|
@@ -34,7 +34,6 @@ const LOAD_ELEMENTS = {
|
||||
file: () => import("./ha-selector-file"),
|
||||
floor: () => import("./ha-selector-floor"),
|
||||
label: () => import("./ha-selector-label"),
|
||||
image: () => import("./ha-selector-image"),
|
||||
background: () => import("./ha-selector-background"),
|
||||
language: () => import("./ha-selector-language"),
|
||||
navigation: () => import("./ha-selector-navigation"),
|
||||
|
@@ -76,7 +76,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _narrow = false;
|
||||
|
||||
@state() private _pickerFilters: TargetTypeFloorless[] = [];
|
||||
@state() private _pickerFilter?: TargetTypeFloorless;
|
||||
|
||||
@state() private _pickerWrapperOpen = false;
|
||||
|
||||
@@ -330,12 +330,16 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
||||
});
|
||||
};
|
||||
|
||||
private _handleUpdatePickerFilters(ev: CustomEvent<TargetTypeFloorless[]>) {
|
||||
this._updatePickerFilters(ev.detail);
|
||||
private _handleUpdatePickerFilter(
|
||||
ev: CustomEvent<TargetTypeFloorless | undefined>
|
||||
) {
|
||||
this._updatePickerFilter(
|
||||
typeof ev.detail === "string" ? ev.detail : undefined
|
||||
);
|
||||
}
|
||||
|
||||
private _updatePickerFilters = (filters: TargetTypeFloorless[]) => {
|
||||
this._pickerFilters = filters;
|
||||
private _updatePickerFilter = (filter?: TargetTypeFloorless) => {
|
||||
this._pickerFilter = filter;
|
||||
};
|
||||
|
||||
private _hidePicker() {
|
||||
@@ -355,8 +359,8 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
||||
return html`
|
||||
<ha-target-picker-selector
|
||||
.hass=${this.hass}
|
||||
@filter-types-changed=${this._handleUpdatePickerFilters}
|
||||
.filterTypes=${this._pickerFilters}
|
||||
@filter-type-changed=${this._handleUpdatePickerFilter}
|
||||
.filterType=${this._pickerFilter}
|
||||
@target-picked=${this._handleTargetPicked}
|
||||
@create-domain-picked=${this._handleCreateDomain}
|
||||
.targetValue=${this.value}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import type { LitVirtualizer } from "@lit-labs/virtualizer";
|
||||
import { consume } from "@lit/context";
|
||||
import { mdiCheck, mdiPlus, mdiTextureBox } from "@mdi/js";
|
||||
import { mdiPlus, mdiTextureBox } from "@mdi/js";
|
||||
import Fuse from "fuse.js";
|
||||
import type { HassServiceTarget } from "home-assistant-js-websocket";
|
||||
import { css, html, LitElement, nothing, type PropertyValues } from "lit";
|
||||
@@ -43,9 +43,10 @@ import { haStyleScrollbar } from "../../resources/styles";
|
||||
import { loadVirtualizer } from "../../resources/virtualizer";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import { brandsUrl } from "../../util/brands-url";
|
||||
import "../chips/ha-chip-set";
|
||||
import "../chips/ha-filter-chip";
|
||||
import type { HaDevicePickerDeviceFilterFunc } from "../device/ha-device-picker";
|
||||
import "../entity/state-badge";
|
||||
import "../ha-button";
|
||||
import "../ha-combo-box-item";
|
||||
import "../ha-floor-icon";
|
||||
import "../ha-md-list";
|
||||
@@ -63,8 +64,7 @@ const CREATE_ID = "___create-new-entity___";
|
||||
export class HaTargetPickerSelector extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public filterTypes: TargetTypeFloorless[] =
|
||||
[];
|
||||
@property({ attribute: false }) public filterType?: TargetTypeFloorless;
|
||||
|
||||
@property({ reflect: true }) public mode: "popover" | "dialog" = "popover";
|
||||
|
||||
@@ -159,11 +159,10 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
@input=${this._searchChanged}
|
||||
.value=${this._searchTerm}
|
||||
></ha-textfield>
|
||||
<div class="filter">${this._renderFilterButtons()}</div>
|
||||
<ha-chip-set class="filter">${this._renderFilterButtons()}</ha-chip-set>
|
||||
<div class="filter-header-wrapper">
|
||||
<div
|
||||
class="filter-header ${this.filterTypes.length !== 1 &&
|
||||
this._filterHeader
|
||||
class="filter-header ${!this.filterType && this._filterHeader
|
||||
? "show"
|
||||
: ""}"
|
||||
>
|
||||
@@ -175,7 +174,6 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
scroller
|
||||
.keyFunction=${this._keyFunction}
|
||||
.items=${this._getItems(
|
||||
this.filterTypes,
|
||||
this.entityFilter,
|
||||
this.deviceFilter,
|
||||
this.includeDomains,
|
||||
@@ -184,7 +182,8 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
this._searchTerm,
|
||||
this.createDomains,
|
||||
this._configEntryLookup,
|
||||
this.mode
|
||||
this.mode,
|
||||
this.filterType
|
||||
)}
|
||||
.renderItem=${this._renderRow}
|
||||
@scroll=${this._onScrollList}
|
||||
@@ -428,23 +427,17 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
return html`<div class="separator"></div>`;
|
||||
}
|
||||
|
||||
const selected = this.filterTypes.includes(filterType);
|
||||
const selected = this.filterType === filterType;
|
||||
return html`
|
||||
<ha-button
|
||||
<ha-filter-chip
|
||||
@click=${this._toggleFilter}
|
||||
.type=${filterType}
|
||||
size="small"
|
||||
.variant=${selected ? "brand" : "neutral"}
|
||||
appearance="filled"
|
||||
no-shrink
|
||||
>
|
||||
${selected
|
||||
? html`<ha-svg-icon slot="start" .path=${mdiCheck}></ha-svg-icon>`
|
||||
: nothing}
|
||||
${this.hass.localize(
|
||||
.selected=${selected}
|
||||
.label=${this.hass.localize(
|
||||
`ui.components.target-picker.type.${filterType === "entity" ? "entities" : `${filterType}s`}` as LocalizeKeys
|
||||
)}
|
||||
</ha-button>
|
||||
>
|
||||
</ha-filter-chip>
|
||||
`;
|
||||
});
|
||||
}
|
||||
@@ -672,7 +665,6 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
|
||||
private _getItems = memoizeOne(
|
||||
(
|
||||
filterTypes: TargetTypeFloorless[],
|
||||
entityFilter: this["entityFilter"],
|
||||
deviceFilter: this["deviceFilter"],
|
||||
includeDomains: this["includeDomains"],
|
||||
@@ -681,7 +673,8 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
searchTerm: string,
|
||||
createDomains: this["createDomains"],
|
||||
configEntryLookup: Record<string, ConfigEntry>,
|
||||
mode: this["mode"]
|
||||
mode: this["mode"],
|
||||
filterType?: TargetTypeFloorless
|
||||
) => {
|
||||
const items: (
|
||||
| string
|
||||
@@ -690,7 +683,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
| PickerComboBoxItem
|
||||
)[] = [];
|
||||
|
||||
if (filterTypes.length === 0 || filterTypes.includes("entity")) {
|
||||
if (!filterType || filterType === "entity") {
|
||||
let entities = this._getEntitiesMemoized(
|
||||
this.hass,
|
||||
includeDomains,
|
||||
@@ -713,7 +706,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
) as EntityComboBoxItem[];
|
||||
}
|
||||
|
||||
if (entities.length > 0 && filterTypes.length !== 1) {
|
||||
if (!filterType) {
|
||||
// show group title
|
||||
items.push(
|
||||
this.hass.localize("ui.components.target-picker.type.entities")
|
||||
@@ -723,7 +716,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
items.push(...entities);
|
||||
}
|
||||
|
||||
if (filterTypes.length === 0 || filterTypes.includes("device")) {
|
||||
if (!filterType || filterType === "device") {
|
||||
let devices = this._getDevicesMemoized(
|
||||
this.hass,
|
||||
configEntryLookup,
|
||||
@@ -741,7 +734,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
devices = this._filterGroup("device", devices);
|
||||
}
|
||||
|
||||
if (devices.length > 0 && filterTypes.length !== 1) {
|
||||
if (!filterType) {
|
||||
// show group title
|
||||
items.push(
|
||||
this.hass.localize("ui.components.target-picker.type.devices")
|
||||
@@ -751,7 +744,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
items.push(...devices);
|
||||
}
|
||||
|
||||
if (filterTypes.length === 0 || filterTypes.includes("area")) {
|
||||
if (!filterType || filterType === "area") {
|
||||
let areasAndFloors = this._getAreasAndFloorsMemoized(
|
||||
this.hass.states,
|
||||
this.hass.floors,
|
||||
@@ -777,7 +770,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
) as FloorComboBoxItem[];
|
||||
}
|
||||
|
||||
if (areasAndFloors.length > 0 && filterTypes.length !== 1) {
|
||||
if (!filterType) {
|
||||
// show group title
|
||||
items.push(
|
||||
this.hass.localize("ui.components.target-picker.type.areas")
|
||||
@@ -803,7 +796,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
);
|
||||
}
|
||||
|
||||
if (filterTypes.length === 0 || filterTypes.includes("label")) {
|
||||
if (!filterType || filterType === "label") {
|
||||
let labels = this._getLabelsMemoized(
|
||||
this.hass,
|
||||
this._labelRegistry,
|
||||
@@ -819,7 +812,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
labels = this._filterGroup("label", labels);
|
||||
}
|
||||
|
||||
if (labels.length > 0 && filterTypes.length !== 1) {
|
||||
if (!filterType) {
|
||||
// show group title
|
||||
items.push(
|
||||
this.hass.localize("ui.components.target-picker.type.labels")
|
||||
@@ -944,17 +937,17 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
}
|
||||
|
||||
private _toggleFilter(ev: any) {
|
||||
ev.stopPropagation();
|
||||
this._resetSelectedItem();
|
||||
this._filterHeader = undefined;
|
||||
const type = ev.target.type as TargetTypeFloorless;
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
const index = this.filterTypes.indexOf(type);
|
||||
if (index === -1) {
|
||||
this.filterTypes = [...this.filterTypes, type];
|
||||
if (this.filterType === type) {
|
||||
this.filterType = undefined;
|
||||
} else {
|
||||
this.filterTypes = this.filterTypes.filter((t) => t !== type);
|
||||
this.filterType = type;
|
||||
}
|
||||
|
||||
// Reset scroll position when filter changes
|
||||
@@ -962,7 +955,7 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
this._virtualizerElement.scrollToIndex(0);
|
||||
}
|
||||
|
||||
fireEvent(this, "filter-types-changed", this.filterTypes);
|
||||
fireEvent(this, "filter-type-changed", this.filterType);
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
@@ -994,18 +987,22 @@ export class HaTargetPickerSelector extends LitElement {
|
||||
|
||||
.filter {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: var(--ha-space-2);
|
||||
padding: var(--ha-space-3) var(--ha-space-3);
|
||||
overflow: auto;
|
||||
--ha-button-border-radius: var(--ha-border-radius-md);
|
||||
}
|
||||
|
||||
:host([mode="dialog"]) .filter {
|
||||
padding: var(--ha-space-3) var(--ha-space-4);
|
||||
}
|
||||
|
||||
.filter ha-button {
|
||||
.filter ha-filter-chip {
|
||||
flex-shrink: 0;
|
||||
--md-filter-chip-selected-container-color: var(
|
||||
--ha-color-fill-primary-normal-hover
|
||||
);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.filter .separator {
|
||||
@@ -1097,7 +1094,7 @@ declare global {
|
||||
}
|
||||
|
||||
interface HASSDomEvents {
|
||||
"filter-types-changed": TargetTypeFloorless[];
|
||||
"filter-type-changed": TargetTypeFloorless | undefined;
|
||||
"target-picked": {
|
||||
type: TargetType;
|
||||
id: string;
|
||||
|
@@ -18,7 +18,6 @@ import { classMap } from "lit/directives/class-map";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { LocalizeFunc } from "../common/translations/localize";
|
||||
import "../components/chips/ha-assist-chip";
|
||||
import "../components/chips/ha-filter-chip";
|
||||
import "../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
|
@@ -9,7 +9,6 @@ import {
|
||||
import type { PropertyValues } from "lit";
|
||||
import { LitElement, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import memoize from "memoize-one";
|
||||
import { isComponentLoaded } from "../../../../common/config/is_component_loaded";
|
||||
import { storage } from "../../../../common/decorators/storage";
|
||||
@@ -62,7 +61,7 @@ type DataTableItem = Pick<
|
||||
> & {
|
||||
default: boolean;
|
||||
filename: string;
|
||||
iconColor?: string;
|
||||
type: string;
|
||||
};
|
||||
|
||||
@customElement("ha-config-lovelace-dashboards")
|
||||
@@ -107,6 +106,20 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
})
|
||||
private _activeHiddenColumns?: string[];
|
||||
|
||||
@storage({
|
||||
key: "lovelace-dashboards-table-grouping",
|
||||
state: false,
|
||||
subscribe: false,
|
||||
})
|
||||
private _activeGrouping?: string = "type";
|
||||
|
||||
@storage({
|
||||
key: "lovelace-dashboards-table-collapsed",
|
||||
state: false,
|
||||
subscribe: false,
|
||||
})
|
||||
private _activeCollapsed: string[] = [];
|
||||
|
||||
public willUpdate() {
|
||||
if (!this.hasUpdated) {
|
||||
this.hass.loadFragmentTranslation("lovelace");
|
||||
@@ -132,15 +145,7 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
template: (dashboard) =>
|
||||
dashboard.icon
|
||||
? html`
|
||||
<ha-icon
|
||||
slot="item-icon"
|
||||
.icon=${dashboard.icon}
|
||||
style=${ifDefined(
|
||||
dashboard.iconColor
|
||||
? `color: ${dashboard.iconColor}`
|
||||
: undefined
|
||||
)}
|
||||
></ha-icon>
|
||||
<ha-icon slot="item-icon" .icon=${dashboard.icon}></ha-icon>
|
||||
`
|
||||
: nothing,
|
||||
},
|
||||
@@ -177,6 +182,15 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
},
|
||||
};
|
||||
|
||||
columns.type = {
|
||||
title: localize(
|
||||
"ui.panel.config.lovelace.dashboards.picker.headers.type"
|
||||
),
|
||||
sortable: true,
|
||||
groupable: true,
|
||||
filterable: true,
|
||||
};
|
||||
|
||||
columns.mode = {
|
||||
title: localize(
|
||||
"ui.panel.config.lovelace.dashboards.picker.headers.conf_mode"
|
||||
@@ -287,7 +301,7 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
url_path: "lovelace",
|
||||
mode: defaultMode,
|
||||
filename: defaultMode === "yaml" ? "ui-lovelace.yaml" : "",
|
||||
iconColor: "var(--primary-color)",
|
||||
type: this._localizeType("built_in"),
|
||||
},
|
||||
];
|
||||
if (isComponentLoaded(this.hass, "energy")) {
|
||||
@@ -298,9 +312,9 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
mode: "storage",
|
||||
url_path: "energy",
|
||||
filename: "",
|
||||
iconColor: "var(--orange-color)",
|
||||
default: false,
|
||||
require_admin: false,
|
||||
type: this._localizeType("built_in"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -312,9 +326,9 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
mode: "storage",
|
||||
url_path: "light",
|
||||
filename: "",
|
||||
iconColor: "var(--amber-color)",
|
||||
default: false,
|
||||
require_admin: false,
|
||||
type: this._localizeType("built_in"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -326,9 +340,9 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
mode: "storage",
|
||||
url_path: "safety",
|
||||
filename: "",
|
||||
iconColor: "var(--blue-grey-color)",
|
||||
default: false,
|
||||
require_admin: false,
|
||||
type: this._localizeType("built_in"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -340,9 +354,9 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
mode: "storage",
|
||||
url_path: "climate",
|
||||
filename: "",
|
||||
iconColor: "var(--deep-orange-color)",
|
||||
default: false,
|
||||
require_admin: false,
|
||||
type: this._localizeType("built_in"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -351,16 +365,25 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
.sort((a, b) =>
|
||||
stringCompare(a.title, b.title, this.hass.locale.language)
|
||||
)
|
||||
.map((dashboard) => ({
|
||||
filename: "",
|
||||
...dashboard,
|
||||
default: defaultUrlPath === dashboard.url_path,
|
||||
}))
|
||||
.map(
|
||||
(dashboard) =>
|
||||
({
|
||||
filename: "",
|
||||
...dashboard,
|
||||
default: defaultUrlPath === dashboard.url_path,
|
||||
type: this._localizeType("user_created"),
|
||||
}) satisfies DataTableItem
|
||||
)
|
||||
);
|
||||
return result;
|
||||
}
|
||||
);
|
||||
|
||||
private _localizeType = (type: "user_created" | "built_in") =>
|
||||
this.hass.localize(
|
||||
`ui.panel.config.lovelace.dashboards.picker.type.${type}`
|
||||
);
|
||||
|
||||
protected render() {
|
||||
if (!this.hass || this._dashboards === undefined) {
|
||||
return html` <hass-loading-screen></hass-loading-screen> `;
|
||||
@@ -380,9 +403,13 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
this.hass.localize
|
||||
)}
|
||||
.data=${this._getItems(this._dashboards, this.hass.defaultPanel)}
|
||||
.initialGroupColumn=${this._activeGrouping}
|
||||
.initialCollapsedGroups=${this._activeCollapsed}
|
||||
.initialSorting=${this._activeSorting}
|
||||
.columnOrder=${this._activeColumnOrder}
|
||||
.hiddenColumns=${this._activeHiddenColumns}
|
||||
@grouping-changed=${this._handleGroupingChanged}
|
||||
@collapsed-changed=${this._handleCollapseChanged}
|
||||
@columns-changed=${this._handleColumnsChanged}
|
||||
@sorting-changed=${this._handleSortingChanged}
|
||||
.filter=${this._filter}
|
||||
@@ -443,13 +470,13 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
}
|
||||
|
||||
private _canDelete(urlPath: string) {
|
||||
return !["lovelace", "energy", "light", "security", "climate"].includes(
|
||||
return !["lovelace", "energy", "light", "safety", "climate"].includes(
|
||||
urlPath
|
||||
);
|
||||
}
|
||||
|
||||
private _canEdit(urlPath: string) {
|
||||
return !["light", "security", "climate"].includes(urlPath);
|
||||
return !["light", "safety", "climate"].includes(urlPath);
|
||||
}
|
||||
|
||||
private _handleDelete = async (item: DataTableItem) => {
|
||||
@@ -571,6 +598,14 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
||||
this._activeColumnOrder = ev.detail.columnOrder;
|
||||
this._activeHiddenColumns = ev.detail.hiddenColumns;
|
||||
}
|
||||
|
||||
private _handleGroupingChanged(ev: CustomEvent) {
|
||||
this._activeGrouping = ev.detail.value;
|
||||
}
|
||||
|
||||
private _handleCollapseChanged(ev: CustomEvent) {
|
||||
this._activeCollapsed = ev.detail.value;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@@ -3455,12 +3455,17 @@
|
||||
"require_admin": "Admin only",
|
||||
"sidebar": "In sidebar",
|
||||
"filename": "Filename",
|
||||
"url": "Open"
|
||||
"url": "Open",
|
||||
"type": "Type"
|
||||
},
|
||||
"open": "Open",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"add_dashboard": "Add dashboard"
|
||||
"add_dashboard": "Add dashboard",
|
||||
"type": {
|
||||
"user_created": "User created",
|
||||
"built_in": "Built-in"
|
||||
}
|
||||
},
|
||||
"confirm_delete_title": "Delete {dashboard_title}?",
|
||||
"confirm_delete_text": "This dashboard will be permanently deleted.",
|
||||
|
Reference in New Issue
Block a user