mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 15:26:36 +00:00
Fix multiple sortable (#13522)
This commit is contained in:
parent
1e19799da9
commit
c116ad67ed
@ -49,6 +49,7 @@ import { subscribeRepairsIssueRegistry } from "../data/repairs";
|
||||
import { updateCanInstall, UpdateEntity } from "../data/update";
|
||||
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||
import { actionHandler } from "../panels/lovelace/common/directives/action-handler-directive";
|
||||
import { loadSortable, SortableInstance } from "../resources/sortable.ondemand";
|
||||
import { haStyleScrollbar } from "../resources/styles";
|
||||
import type { HomeAssistant, PanelInfo, Route } from "../types";
|
||||
import "./ha-icon";
|
||||
@ -177,8 +178,6 @@ const computePanels = memoizeOne(
|
||||
}
|
||||
);
|
||||
|
||||
let Sortable;
|
||||
|
||||
@customElement("ha-sidebar")
|
||||
class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@ -205,6 +204,8 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _recentKeydownActiveUntil = 0;
|
||||
|
||||
private sortableStyleLoaded = false;
|
||||
|
||||
// @ts-ignore
|
||||
@LocalStorage("sidebarPanelOrder", true, {
|
||||
attribute: false,
|
||||
@ -217,7 +218,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
})
|
||||
private _hiddenPanels: string[] = [];
|
||||
|
||||
private _sortable?;
|
||||
private _sortable?: SortableInstance;
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
@ -658,36 +659,36 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
|
||||
private async _activateEditMode() {
|
||||
if (!Sortable) {
|
||||
const [sortableImport, sortStylesImport] = await Promise.all([
|
||||
import("sortablejs/modular/sortable.core.esm"),
|
||||
import("../resources/ha-sortable-style"),
|
||||
]);
|
||||
await Promise.all([this._loadSortableStyle(), this._createSortable()]);
|
||||
}
|
||||
|
||||
private async _loadSortableStyle() {
|
||||
if (this.sortableStyleLoaded) return;
|
||||
|
||||
const sortStylesImport = await import("../resources/ha-sortable-style");
|
||||
|
||||
const style = document.createElement("style");
|
||||
style.innerHTML = (sortStylesImport.sortableStyles as CSSResult).cssText;
|
||||
this.shadowRoot!.appendChild(style);
|
||||
|
||||
Sortable = sortableImport.Sortable;
|
||||
Sortable.mount(sortableImport.OnSpill);
|
||||
Sortable.mount(sortableImport.AutoScroll());
|
||||
}
|
||||
|
||||
this.sortableStyleLoaded = true;
|
||||
await this.updateComplete;
|
||||
|
||||
this._createSortable();
|
||||
}
|
||||
|
||||
private _createSortable() {
|
||||
this._sortable = new Sortable(this.shadowRoot!.getElementById("sortable"), {
|
||||
private async _createSortable() {
|
||||
const Sortable = await loadSortable();
|
||||
this._sortable = new Sortable(
|
||||
this.shadowRoot!.getElementById("sortable")!,
|
||||
{
|
||||
animation: 150,
|
||||
fallbackClass: "sortable-fallback",
|
||||
dataIdAttr: "data-panel",
|
||||
handle: "paper-icon-item",
|
||||
onSort: async () => {
|
||||
this._panelOrder = this._sortable.toArray();
|
||||
this._panelOrder = this._sortable!.toArray();
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private _deactivateEditMode() {
|
||||
|
@ -41,7 +41,7 @@ export const addItem = (
|
||||
|
||||
export const reorderItems = (
|
||||
hass: HomeAssistant,
|
||||
itemIds: [string]
|
||||
itemIds: string[]
|
||||
): Promise<ShoppingListItem> =>
|
||||
hass.callWS({
|
||||
type: "shopping_list/items/reorder",
|
||||
|
@ -30,8 +30,10 @@ import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import { SensorCardConfig, ShoppingListCardConfig } from "./types";
|
||||
import type { HaTextField } from "../../../components/ha-textfield";
|
||||
|
||||
let Sortable;
|
||||
import {
|
||||
loadSortable,
|
||||
SortableInstance,
|
||||
} from "../../../resources/sortable.ondemand";
|
||||
|
||||
@customElement("hui-shopping-list-card")
|
||||
class HuiShoppingListCard
|
||||
@ -59,7 +61,7 @@ class HuiShoppingListCard
|
||||
|
||||
@state() private _renderEmptySortable = false;
|
||||
|
||||
private _sortable?;
|
||||
private _sortable?: SortableInstance;
|
||||
|
||||
@query("#sortable") private _sortableEl?: HTMLElement;
|
||||
|
||||
@ -299,12 +301,6 @@ class HuiShoppingListCard
|
||||
}
|
||||
|
||||
private async _toggleReorder() {
|
||||
if (!Sortable) {
|
||||
const sortableImport = await import(
|
||||
"sortablejs/modular/sortable.core.esm"
|
||||
);
|
||||
Sortable = sortableImport.Sortable;
|
||||
}
|
||||
this._reordering = !this._reordering;
|
||||
await this.updateComplete;
|
||||
if (this._reordering) {
|
||||
@ -315,18 +311,22 @@ class HuiShoppingListCard
|
||||
}
|
||||
}
|
||||
|
||||
private _createSortable() {
|
||||
private async _createSortable() {
|
||||
const Sortable = await loadSortable();
|
||||
const sortableEl = this._sortableEl;
|
||||
this._sortable = new Sortable(sortableEl, {
|
||||
this._sortable = new Sortable(sortableEl!, {
|
||||
animation: 150,
|
||||
fallbackClass: "sortable-fallback",
|
||||
dataIdAttr: "item-id",
|
||||
handle: "ha-svg-icon",
|
||||
onEnd: async (evt) => {
|
||||
if (evt.newIndex === undefined || evt.oldIndex === undefined) {
|
||||
return;
|
||||
}
|
||||
// Since this is `onEnd` event, it's possible that
|
||||
// an item wa dragged away and was put back to its original position.
|
||||
if (evt.oldIndex !== evt.newIndex) {
|
||||
reorderItems(this.hass!, this._sortable.toArray()).catch(() =>
|
||||
reorderItems(this.hass!, this._sortable!.toArray()).catch(() =>
|
||||
this._fetchData()
|
||||
);
|
||||
// Move the shopping list item in memory.
|
||||
|
@ -15,11 +15,13 @@ import "../../../components/entity/ha-entity-picker";
|
||||
import type { HaEntityPicker } from "../../../components/entity/ha-entity-picker";
|
||||
import "../../../components/ha-icon-button";
|
||||
import { sortableStyles } from "../../../resources/ha-sortable-style";
|
||||
import {
|
||||
loadSortable,
|
||||
SortableInstance,
|
||||
} from "../../../resources/sortable.ondemand";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { EntityConfig } from "../entity-rows/types";
|
||||
|
||||
let Sortable;
|
||||
|
||||
@customElement("hui-entity-editor")
|
||||
export class HuiEntityEditor extends LitElement {
|
||||
@property({ attribute: false }) protected hass?: HomeAssistant;
|
||||
@ -32,7 +34,7 @@ export class HuiEntityEditor extends LitElement {
|
||||
|
||||
@state() private _renderEmptySortable = false;
|
||||
|
||||
private _sortable?;
|
||||
private _sortable?: SortableInstance;
|
||||
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
@ -123,23 +125,18 @@ export class HuiEntityEditor extends LitElement {
|
||||
}
|
||||
|
||||
private async _createSortable() {
|
||||
if (!Sortable) {
|
||||
const sortableImport = await import(
|
||||
"sortablejs/modular/sortable.core.esm"
|
||||
);
|
||||
const Sortable = await loadSortable();
|
||||
|
||||
Sortable = sortableImport.Sortable;
|
||||
Sortable.mount(sortableImport.OnSpill);
|
||||
Sortable.mount(sortableImport.AutoScroll());
|
||||
}
|
||||
|
||||
this._sortable = new Sortable(this.shadowRoot!.querySelector(".entities"), {
|
||||
this._sortable = new Sortable(
|
||||
this.shadowRoot!.querySelector(".entities")!,
|
||||
{
|
||||
animation: 150,
|
||||
fallbackClass: "sortable-fallback",
|
||||
handle: "ha-svg-icon",
|
||||
dataIdAttr: "data-entity-id",
|
||||
onEnd: async (evt: SortableEvent) => this._entityMoved(evt),
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private async _addEntity(ev: CustomEvent): Promise<void> {
|
||||
|
@ -16,11 +16,13 @@ import type { HaEntityPicker } from "../../../components/entity/ha-entity-picker
|
||||
import "../../../components/ha-icon-button";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import { sortableStyles } from "../../../resources/ha-sortable-style";
|
||||
import {
|
||||
loadSortable,
|
||||
SortableInstance,
|
||||
} from "../../../resources/sortable.ondemand";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { EntityConfig, LovelaceRowConfig } from "../entity-rows/types";
|
||||
|
||||
let Sortable;
|
||||
|
||||
declare global {
|
||||
interface HASSDomEvents {
|
||||
"entities-changed": {
|
||||
@ -41,7 +43,7 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
||||
|
||||
@state() private _renderEmptySortable = false;
|
||||
|
||||
private _sortable?;
|
||||
private _sortable?: SortableInstance;
|
||||
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
@ -173,22 +175,17 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
||||
}
|
||||
|
||||
private async _createSortable() {
|
||||
if (!Sortable) {
|
||||
const sortableImport = await import(
|
||||
"sortablejs/modular/sortable.core.esm"
|
||||
);
|
||||
const Sortable = await loadSortable();
|
||||
|
||||
Sortable = sortableImport.Sortable;
|
||||
Sortable.mount(sortableImport.OnSpill);
|
||||
Sortable.mount(sortableImport.AutoScroll());
|
||||
}
|
||||
|
||||
this._sortable = new Sortable(this.shadowRoot!.querySelector(".entities"), {
|
||||
this._sortable = new Sortable(
|
||||
this.shadowRoot!.querySelector(".entities")!,
|
||||
{
|
||||
animation: 150,
|
||||
fallbackClass: "sortable-fallback",
|
||||
handle: ".handle",
|
||||
onEnd: async (evt: SortableEvent) => this._rowMoved(evt),
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private async _addEntity(ev: CustomEvent): Promise<void> {
|
||||
|
11
src/resources/sortable.ondemand.ts
Normal file
11
src/resources/sortable.ondemand.ts
Normal file
@ -0,0 +1,11 @@
|
||||
let loaded: typeof import("./sortable").default;
|
||||
|
||||
export type { SortableInstance } from "./sortable";
|
||||
export const loadSortable = async (): Promise<
|
||||
typeof import("./sortable").default
|
||||
> => {
|
||||
if (!loaded) {
|
||||
loaded = (await import("./sortable")).default;
|
||||
}
|
||||
return loaded;
|
||||
};
|
11
src/resources/sortable.ts
Normal file
11
src/resources/sortable.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import Sortable from "sortablejs";
|
||||
import SortableCore, {
|
||||
OnSpill,
|
||||
AutoScroll,
|
||||
} from "sortablejs/modular/sortable.core.esm";
|
||||
|
||||
SortableCore.mount(OnSpill, new AutoScroll());
|
||||
|
||||
export default SortableCore as typeof Sortable;
|
||||
|
||||
export type { Sortable as SortableInstance };
|
Loading…
x
Reference in New Issue
Block a user