diff --git a/src/layouts/hass-tabs-subpage-data-table.ts b/src/layouts/hass-tabs-subpage-data-table.ts
index 1858895621..3807b8c292 100644
--- a/src/layouts/hass-tabs-subpage-data-table.ts
+++ b/src/layouts/hass-tabs-subpage-data-table.ts
@@ -468,7 +468,7 @@ export class HaTabsSubpageDataTable extends KeyboardShortcutMixin(LitElement) {
${!this.narrow
? html`
-
+
`
- : html`
+ : html`
+
+
+
`}
+ ${selectModeBtn}
+
+ ${groupByMenu}${sortByMenu}${settingsButton}
+
+ `}
`}
@@ -835,13 +841,20 @@ export class HaTabsSubpageDataTable extends KeyboardShortcutMixin(LitElement) {
.narrow-header-row {
display: flex;
align-items: center;
+ min-width: 100%;
gap: 16px;
padding: 0 16px;
+ box-sizing: border-box;
overflow-x: scroll;
-ms-overflow-style: none;
scrollbar-width: none;
}
+ .narrow-header-row .flex {
+ flex: 1;
+ margin-left: -16px;
+ }
+
.selection-bar {
background: rgba(var(--rgb-primary-color), 0.1);
width: 100%;
diff --git a/src/panels/config/backup/ha-config-backup-dashboard.ts b/src/panels/config/backup/ha-config-backup-dashboard.ts
index 6eeb53f63b..0a6da83f2c 100644
--- a/src/panels/config/backup/ha-config-backup-dashboard.ts
+++ b/src/panels/config/backup/ha-config-backup-dashboard.ts
@@ -13,13 +13,14 @@ import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { relativeTime } from "../../../common/datetime/relative_time";
+import { storage } from "../../../common/decorators/storage";
import type { HASSDomEvent } from "../../../common/dom/fire_event";
+import { computeDomain } from "../../../common/entity/compute_domain";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import { navigate } from "../../../common/navigate";
import type { LocalizeFunc } from "../../../common/translations/localize";
import type {
DataTableColumnContainer,
- DataTableRowData,
RowClickedEvent,
SelectionChangedEvent,
} from "../../../components/data-table/ha-data-table";
@@ -71,7 +72,15 @@ import { showBackupOnboardingDialog } from "./dialogs/show-dialog-backup_onboard
import { showGenerateBackupDialog } from "./dialogs/show-dialog-generate-backup";
import { showNewBackupDialog } from "./dialogs/show-dialog-new-backup";
import { showUploadBackupDialog } from "./dialogs/show-dialog-upload-backup";
-import { computeDomain } from "../../../common/entity/compute_domain";
+import { capitalizeFirstLetter } from "../../../common/string/capitalize-first-letter";
+
+interface BackupRow extends BackupContent {
+ formatted_type: string;
+}
+
+type BackupType = "strategy" | "custom";
+
+const TYPE_ORDER: Array = ["strategy", "custom"];
@customElement("ha-config-backup-dashboard")
class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
@@ -91,20 +100,29 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
@state() private _config?: BackupConfig;
+ @storage({ key: "backups-table-grouping", state: false, subscribe: false })
+ private _activeGrouping?: string = "formatted_type";
+
+ @storage({
+ key: "backups-table-collapsed",
+ state: false,
+ subscribe: false,
+ })
+ private _activeCollapsed?: string;
+
private _subscribed?: Promise<() => void>;
@query("hass-tabs-subpage-data-table", true)
private _dataTable!: HaTabsSubpageDataTable;
private _columns = memoizeOne(
- (localize: LocalizeFunc): DataTableColumnContainer => ({
+ (localize: LocalizeFunc): DataTableColumnContainer => ({
name: {
title: localize("ui.panel.config.backup.name"),
main: true,
sortable: true,
filterable: true,
- flex: 2,
- template: (backup) => backup.name,
+ flex: 3,
},
size: {
title: localize("ui.panel.config.backup.size"),
@@ -120,15 +138,17 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
template: (backup) =>
relativeTime(new Date(backup.date), this.hass.locale),
},
- with_strategy_settings: {
+ formatted_type: {
title: "Type",
filterable: true,
sortable: true,
- template: (backup) =>
- backup.with_strategy_settings ? "Strategy" : "Custom",
+ groupable: true,
},
locations: {
title: "Locations",
+ showNarrow: true,
+ minWidth: "60px",
+ maxWidth: "120px",
template: (backup) => html`
${(backup.agent_ids || []).map((agentId) => {
@@ -198,18 +218,44 @@ class HaConfigBackupDashboard extends SubscribeMixin(LitElement) {
})
);
+ private _groupOrder = memoizeOne((activeGrouping: string | undefined) =>
+ activeGrouping === "formatted_type"
+ ? TYPE_ORDER.map((type) => this._formatBackupType(type))
+ : undefined
+ );
+
+ private _handleGroupingChanged(ev: CustomEvent) {
+ this._activeGrouping = ev.detail.value;
+ }
+
+ private _handleCollapseChanged(ev: CustomEvent) {
+ this._activeCollapsed = ev.detail.value;
+ }
+
private _handleSelectionChanged(
ev: HASSDomEvent
): void {
this._selected = ev.detail.value;
}
+ private _formatBackupType(type: BackupType): string {
+ // Todo translate
+ return capitalizeFirstLetter(type);
+ }
+
+ private _data = memoizeOne((backups: BackupContent[]): BackupRow[] =>
+ backups.map((backup) => ({
+ ...backup,
+ formatted_type: this._formatBackupType(
+ backup.with_strategy_settings ? "strategy" : "custom"
+ ),
+ }))
+ );
+
protected render(): TemplateResult {
const backupInProgress =
"state" in this._manager && this._manager.state === "in_progress";
- const data: DataTableRowData[] = this._backups;
-
return html`
-