Skip to content

Commit

Permalink
Handle automation and dashboard drag and drop at the element level (#…
Browse files Browse the repository at this point in the history
…22300)

* Handle drag and drop at action, condition, trigger level

* Clean item path

* Clean item path

* Fix selectors

* Clean selector config

* Remove enhancedSelector

* Add option row component

* Fix DnD inside option sequence or condition

* Add comments

* Remove item path logic from the dashboard too

* Fix floor/area drag and drop

* Avoid UI jump in area dashboard

* Remove unused import

* Add comment
  • Loading branch information
piitaya authored Oct 30, 2024
1 parent 51f89b0 commit bc11c0b
Show file tree
Hide file tree
Showing 34 changed files with 909 additions and 907 deletions.
66 changes: 0 additions & 66 deletions src/common/util/array-move.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/components/ha-selector/ha-selector-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export class HaActionSelector extends LitElement {
.disabled=${this.disabled}
.actions=${this._actions(this.value)}
.hass=${this.hass}
.path=${this.selector.action?.path}
></ha-automation-action>
`;
}
Expand Down
1 change: 0 additions & 1 deletion src/components/ha-selector/ha-selector-condition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export class HaConditionSelector extends LitElement {
.disabled=${this.disabled}
.conditions=${this.value || []}
.hass=${this.hass}
.path=${this.selector.condition?.path}
></ha-automation-condition>
`;
}
Expand Down
1 change: 0 additions & 1 deletion src/components/ha-selector/ha-selector-trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export class HaTriggerSelector extends LitElement {
.disabled=${this.disabled}
.triggers=${this._triggers(this.value)}
.hass=${this.hass}
.path=${this.selector.trigger?.path}
></ha-automation-trigger>
`;
}
Expand Down
29 changes: 1 addition & 28 deletions src/components/ha-service-control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { fireEvent } from "../common/dom/fire_event";
import { computeDomain } from "../common/entity/compute_domain";
import { computeObjectId } from "../common/entity/compute_object_id";
import { supportsFeature } from "../common/entity/supports-feature";
import { nestedArrayMove } from "../common/util/array-move";
import {
fetchIntegrationManifest,
IntegrationManifest,
Expand Down Expand Up @@ -597,15 +596,6 @@ export class HaServiceControl extends LitElement {
}

const selector = dataField?.selector ?? { text: undefined };
const type = Object.keys(selector)[0];
const enhancedSelector = ["action", "condition", "trigger"].includes(type)
? {
[type]: {
...selector[type],
path: [dataField.key],
},
}
: selector;

const showOptional = showOptionalToggle(dataField);

Expand Down Expand Up @@ -646,15 +636,14 @@ export class HaServiceControl extends LitElement {
(!this._value?.data ||
this._value.data[dataField.key] === undefined))}
.hass=${this.hass}
.selector=${enhancedSelector}
.selector=${selector}
.key=${dataField.key}
@value-changed=${this._serviceDataChanged}
.value=${this._value?.data
? this._value.data[dataField.key]
: undefined}
.placeholder=${dataField.default}
.localizeValue=${this._localizeValueCallback}
@item-moved=${this._itemMoved}
></ha-selector>
</ha-settings-row>`
: "";
Expand Down Expand Up @@ -856,22 +845,6 @@ export class HaServiceControl extends LitElement {
});
}

private _itemMoved(ev) {
ev.stopPropagation();
const { oldIndex, newIndex, oldPath, newPath } = ev.detail;

const data = this.value?.data ?? {};

const newData = nestedArrayMove(data, oldIndex, newIndex, oldPath, newPath);

fireEvent(this, "value-changed", {
value: {
...this.value,
data: newData,
},
});
}

private _dataChanged(ev: CustomEvent) {
ev.stopPropagation();
if (!ev.detail.isValid) {
Expand Down
58 changes: 30 additions & 28 deletions src/components/ha-sortable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ import { customElement, property } from "lit/decorators";
import type { SortableEvent } from "sortablejs";
import { fireEvent } from "../common/dom/fire_event";
import type { SortableInstance } from "../resources/sortable";
import { ItemPath } from "../types";

declare global {
interface HASSDomEvents {
"item-moved": {
oldIndex: number;
newIndex: number;
oldPath?: ItemPath;
newPath?: ItemPath;
};
"item-added": {
index: number;
data: any;
};
"item-removed": {
index: number;
};
"drag-start": undefined;
"drag-end": undefined;
Expand All @@ -21,7 +25,7 @@ declare global {

export type HaSortableOptions = Omit<
SortableInstance.SortableOptions,
"onStart" | "onChoose" | "onEnd"
"onStart" | "onChoose" | "onEnd" | "onUpdate" | "onAdd" | "onRemove"
>;

@customElement("ha-sortable")
Expand All @@ -31,9 +35,6 @@ export class HaSortable extends LitElement {
@property({ type: Boolean })
public disabled = false;

@property({ type: Array })
public path?: ItemPath;

@property({ type: Boolean, attribute: "no-style" })
public noStyle: boolean = false;

Expand Down Expand Up @@ -138,6 +139,9 @@ export class HaSortable extends LitElement {
onChoose: this._handleChoose,
onStart: this._handleStart,
onEnd: this._handleEnd,
onUpdate: this._handleUpdate,
onAdd: this._handleAdd,
onRemove: this._handleRemove,
};

if (this.draggableSelector) {
Expand All @@ -159,33 +163,31 @@ export class HaSortable extends LitElement {
this._sortable = new Sortable(container, options);
}

private _handleEnd = async (evt: SortableEvent) => {
private _handleUpdate = (evt) => {
fireEvent(this, "item-moved", {
newIndex: evt.newIndex,
oldIndex: evt.oldIndex,
});
};

private _handleAdd = (evt) => {
fireEvent(this, "item-added", {
index: evt.newIndex,
data: evt.item.sortableData,
});
};

private _handleRemove = (evt) => {
fireEvent(this, "item-removed", { index: evt.oldIndex });
};

private _handleEnd = async (evt) => {
fireEvent(this, "drag-end");
// put back in original location
if (this.rollback && (evt.item as any).placeholder) {
(evt.item as any).placeholder.replaceWith(evt.item);
delete (evt.item as any).placeholder;
}

const oldIndex = evt.oldIndex;
const oldPath = (evt.from.parentElement as HaSortable).path;
const newIndex = evt.newIndex;
const newPath = (evt.to.parentElement as HaSortable).path;

if (
oldIndex === undefined ||
newIndex === undefined ||
(oldIndex === newIndex && oldPath?.join(".") === newPath?.join("."))
) {
return;
}

fireEvent(this, "item-moved", {
oldIndex,
newIndex,
oldPath,
newPath,
});
};

private _handleStart = () => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/trace/hat-trace-timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { LabelRegistryEntry } from "../../data/label_registry";
import { LogbookEntry } from "../../data/logbook";
import {
ChooseAction,
ChooseActionChoice,
Option,
IfAction,
ParallelAction,
RepeatAction,
Expand Down Expand Up @@ -413,7 +413,7 @@ class ActionRenderer {
: undefined;
const choiceConfig = this._getDataFromPath(
`${this.keys[index]}/choose/${chooseTrace.result.choice}`
) as ChooseActionChoice | undefined;
) as Option | undefined;
const choiceName = choiceConfig
? `${
choiceConfig.alias ||
Expand Down
5 changes: 3 additions & 2 deletions src/data/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,14 @@ export interface ForEachRepeat extends BaseRepeat {
for_each: string | any[];
}

export interface ChooseActionChoice extends BaseAction {
export interface Option {
alias?: string;
conditions: string | Condition[];
sequence: Action | Action[];
}

export interface ChooseAction extends BaseAction {
choose: ChooseActionChoice | ChooseActionChoice[] | null;
choose: Option | Option[] | null;
default?: Action | Action[];
}

Expand Down
17 changes: 7 additions & 10 deletions src/data/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { supportsFeature } from "../common/entity/supports-feature";
import type { CropOptions } from "../dialogs/image-cropper-dialog/show-image-cropper-dialog";
import { isHelperDomain } from "../panels/config/helpers/const";
import { UiAction } from "../panels/lovelace/components/hui-action-editor";
import { HomeAssistant, ItemPath } from "../types";
import { HomeAssistant } from "../types";
import {
DeviceRegistryEntry,
getDeviceIntegrationLookup,
Expand Down Expand Up @@ -68,9 +68,8 @@ export type Selector =
| UiStateContentSelector;

export interface ActionSelector {
action: {
path?: ItemPath;
} | null;
// eslint-disable-next-line @typescript-eslint/ban-types
action: {} | null;
}

export interface AddonSelector {
Expand Down Expand Up @@ -121,9 +120,8 @@ export interface ColorTempSelector {
}

export interface ConditionSelector {
condition: {
path?: ItemPath;
} | null;
// eslint-disable-next-line @typescript-eslint/ban-types
condition: {} | null;
}

export interface ConversationAgentSelector {
Expand Down Expand Up @@ -432,9 +430,8 @@ export interface TimeSelector {
}

export interface TriggerSelector {
trigger: {
path?: ItemPath;
} | null;
// eslint-disable-next-line @typescript-eslint/ban-types
trigger: {} | null;
}

export interface TTSSelector {
Expand Down
Loading

0 comments on commit bc11c0b

Please sign in to comment.