mirror of
https://github.com/home-assistant/frontend.git
synced 2025-05-03 17:48:43 +00:00
Add move card to view (#2262)
* Add move card to view * Fix style * Fix style and tests * last style change * update tests
This commit is contained in:
parent
e2218f1e6e
commit
2cdb542112
@ -1,6 +1,8 @@
|
|||||||
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
||||||
import "@polymer/paper-button/paper-button";
|
import "@polymer/paper-button/paper-button";
|
||||||
|
import "@polymer/paper-menu-button/paper-menu-button";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||||
|
|
||||||
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
|
||||||
@ -8,7 +10,7 @@ import { confDeleteCard } from "../editor/delete-card";
|
|||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { Lovelace } from "../types";
|
import { Lovelace } from "../types";
|
||||||
import { swapCard } from "../editor/config-util";
|
import { swapCard, moveCard } from "../editor/config-util";
|
||||||
|
|
||||||
export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
||||||
public cardConfig?: LovelaceCardConfig;
|
public cardConfig?: LovelaceCardConfig;
|
||||||
@ -35,10 +37,19 @@ export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
|||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
paper-icon-button {
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
paper-icon-button.delete {
|
paper-icon-button.delete {
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
paper-item.header {
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<div>
|
<div>
|
||||||
@ -60,6 +71,29 @@ export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
|||||||
this.path![1] + 1
|
this.path![1] + 1
|
||||||
}"
|
}"
|
||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
|
<paper-menu-button vertical-offset="48">
|
||||||
|
<paper-icon-button
|
||||||
|
title="Move card to a different view"
|
||||||
|
icon="hass:file-replace"
|
||||||
|
?disabled="${this.lovelace!.config.views.length === 1}"
|
||||||
|
slot="dropdown-trigger"
|
||||||
|
></paper-icon-button>
|
||||||
|
<paper-listbox on-iron-select="_deselect" slot="dropdown-content">
|
||||||
|
<paper-item disabled class="header">Move card to view</paper-item>
|
||||||
|
${
|
||||||
|
this.lovelace!.config.views.map((view, index) => {
|
||||||
|
if (index === this.path![0]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
<paper-item @click="${this._moveCard}" .index="${index}"
|
||||||
|
>${view.title}</paper-item
|
||||||
|
>
|
||||||
|
`;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-menu-button>
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
class="delete"
|
class="delete"
|
||||||
icon="hass:delete"
|
icon="hass:delete"
|
||||||
@ -93,6 +127,14 @@ export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _moveCard(ev: MouseEvent): void {
|
||||||
|
const lovelace = this.lovelace!;
|
||||||
|
const path = this.path!;
|
||||||
|
lovelace.saveConfig(
|
||||||
|
moveCard(lovelace.config, path, [(ev.currentTarget! as any).index])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private _deleteCard(): void {
|
private _deleteCard(): void {
|
||||||
confDeleteCard(this.lovelace!, this.path!);
|
confDeleteCard(this.lovelace!, this.path!);
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,44 @@ export const swapCard = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const moveCard = (
|
||||||
|
config: LovelaceConfig,
|
||||||
|
fromPath: [number, number],
|
||||||
|
toPath: [number]
|
||||||
|
): LovelaceConfig => {
|
||||||
|
if (fromPath[0] === toPath[0]) {
|
||||||
|
throw new Error("You can not move a card to the view it is in.");
|
||||||
|
}
|
||||||
|
const fromView = config.views[fromPath[0]];
|
||||||
|
const card = fromView.cards![fromPath[1]];
|
||||||
|
|
||||||
|
const newView1 = {
|
||||||
|
...fromView,
|
||||||
|
cards: (fromView.cards || []).filter(
|
||||||
|
(_origConf, ind) => ind !== fromPath[1]
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const toView = config.views[toPath[0]];
|
||||||
|
const cards = toView.cards ? [...toView.cards, card] : [card];
|
||||||
|
|
||||||
|
const newView2 = {
|
||||||
|
...toView,
|
||||||
|
cards,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
views: config.views.map((origView, index) =>
|
||||||
|
index === toPath[0]
|
||||||
|
? newView2
|
||||||
|
: index === fromPath[0]
|
||||||
|
? newView1
|
||||||
|
: origView
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const addView = (
|
export const addView = (
|
||||||
config: LovelaceConfig,
|
config: LovelaceConfig,
|
||||||
viewConfig: LovelaceViewConfig
|
viewConfig: LovelaceViewConfig
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import * as assert from "assert";
|
import * as assert from "assert";
|
||||||
|
|
||||||
import { swapCard } from "../../../../src/panels/lovelace/editor/config-util";
|
import {
|
||||||
|
swapCard,
|
||||||
|
moveCard,
|
||||||
|
} from "../../../../src/panels/lovelace/editor/config-util";
|
||||||
import { LovelaceConfig } from "../../../../src/data/lovelace";
|
import { LovelaceConfig } from "../../../../src/data/lovelace";
|
||||||
|
|
||||||
describe("swapCard", () => {
|
describe("swapCard", () => {
|
||||||
@ -52,3 +55,77 @@ describe("swapCard", () => {
|
|||||||
assert.deepEqual(expected, result);
|
assert.deepEqual(expected, result);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("moveCard", () => {
|
||||||
|
it("move a card to an empty view", () => {
|
||||||
|
const config: LovelaceConfig = {
|
||||||
|
views: [
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
cards: [{ type: "card1" }, { type: "card2" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = moveCard(config, [1, 0], [0]);
|
||||||
|
const expected = {
|
||||||
|
views: [
|
||||||
|
{
|
||||||
|
cards: [{ type: "card1" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cards: [{ type: "card2" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
assert.deepEqual(expected, result);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("move a card to different view", () => {
|
||||||
|
const config: LovelaceConfig = {
|
||||||
|
views: [
|
||||||
|
{
|
||||||
|
cards: [{ type: "v1-c1" }, { type: "v1-c2" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cards: [{ type: "v2-c1" }, { type: "v2-c2" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = moveCard(config, [1, 0], [0]);
|
||||||
|
const expected = {
|
||||||
|
views: [
|
||||||
|
{
|
||||||
|
cards: [{ type: "v1-c1" }, { type: "v1-c2" }, { type: "v2-c1" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cards: [{ type: "v2-c2" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
assert.deepEqual(expected, result);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("move a card to the same view", () => {
|
||||||
|
const config: LovelaceConfig = {
|
||||||
|
views: [
|
||||||
|
{
|
||||||
|
cards: [{ type: "v1-c1" }, { type: "v1-c2" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cards: [{ type: "v2-c1" }, { type: "v2-c2" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = function() {
|
||||||
|
moveCard(config, [1, 0], [1]);
|
||||||
|
};
|
||||||
|
assert.throws(
|
||||||
|
result,
|
||||||
|
Error,
|
||||||
|
"You can not move a card to the view it is in."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user