Skip to content

Add context to event trigger#7182

Merged
bramkragten merged 14 commits intohome-assistant:devfrom
OnFreund:event_context
Oct 21, 2020
Merged

Add context to event trigger#7182
bramkragten merged 14 commits intohome-assistant:devfrom
OnFreund:event_context

Conversation

@OnFreund
Copy link
Contributor

@OnFreund OnFreund commented Oct 1, 2020

Proposed change

Add automation editor support to context in event triggers.
The backend is implemented in home-assistant/core#40932.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (thank you!)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • There is no commented out code in this PR.
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

platform: "event";
event_type: string;
event_data: any;
context: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not true. Right now context is always context_id: string, user_id?: string

.defaultValue=${event_data}
@value-changed=${this._dataChanged}
></ha-yaml-editor>
<ha-yaml-editor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't just put up a YAML editor. Instead we know that context ID can only have a user that is relevant for matching, so we should show a drop down where the user can pick users to match.

@zsarnett
Copy link
Contributor

@OnFreund Any progress?

@OnFreund
Copy link
Contributor Author

@zsarnett I think I understand how to show a user drop down using ha-user-picker but I'm not sure how to allow selection of multiple users.

@bramkragten
Copy link
Member

bramkragten commented Oct 12, 2020

@OnFreund
Copy link
Contributor Author

Thanks @bramkragten, ha-entities-picker pointed me in the right direction. The view aspect is working now, but something isn't working well with change propagation. I'm not exactly sure how ha-automation-trigger-event is propagating its value, but right now it isn't working for me.

platform: "event";
event_type: string;
event_data: any;
context: ContextConstraint;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is context mandatory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's optional, I'll change this.

"ui.panel.config.automation.editor.triggers.type.event.context_user_pick"
)}
.hass=${this.hass}
.value=${this._wrapUsersInArray(context)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the user_id constraint can contain either a single user id or an array of them. This normalizes it to an array. Is there a better way to do this?

"ui.panel.config.automation.editor.triggers.type.event.context_user_pick"
)}
.hass=${this.hass}
.value=${this._wrapUsersInArray(context)}
Copy link
Member

@bramkragten bramkragten Oct 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.value=${this._wrapUsersInArray(context)}
.value=${this._wrapUsersInArray(context?.user_id)}

.hass=${this.hass}
.value=${this._wrapUsersInArray(context)}
.users=${this._users}
@value-changed=${this._valueChanged}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't use the default _valueChanged handler, as this value needs to be merged in the context object first.

.hass=${this.hass}
.value=${this._wrapUsersInArray(context)}
.users=${this._users}
@value-changed=${this._valueChanged}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@value-changed=${this._valueChanged}
@value-changed=${this._usersChanged}
private _usersChanged(ev) {
    ev.stopPropagation();
    fireEvent(this, "value-changed", {
      value: { ...this.trigger, context: {...this.trigger.context, user_id: ev.detail.value} },
    });
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that did the trick!

Comment on lines +121 to +122
event_data: any;
context: ContextConstraint;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
event_data: any;
context: ContextConstraint;
event_data?: any;
context?: ContextConstraint;

And you should guard for context being undefined.


public static get defaultConfig() {
return { event_type: "", event_data: {} };
return { event_type: "", event_data: {}, context: { user_id: [] } };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to add this

Suggested change
return { event_type: "", event_data: {}, context: { user_id: [] } };
return { event_type: "" };

Comment on lines +66 to +67
const empty: string[] = [];
return empty.concat(context.user_id || []);
Copy link
Member

@bramkragten bramkragten Oct 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const empty: string[] = [];
return empty.concat(context.user_id || []);
if (typeof user_id === "string") {
return [user_id];
}
return user_id;

`;
}

private _wrapUsersInArray(context): string[] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private _wrapUsersInArray(context): string[] {
private _wrapUsersInArray(user_id: string | string[] | undefined): string[] {

}

protected firstUpdated(): void {
if (!this._users) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't be defined here, so you can skip this check.

private async _addUser(event: PolymerChangedEvent<string>) {
event.stopPropagation();
const toAdd = event.detail.value;
(event.currentTarget as any).value = "";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bramkragten this doesn't work, because ha-user-picker is doing this:

const newValue = ev.detail.item.dataset.userId;

if (newValue !== this._value) {

And changing the value doesn't change the selected item. What's the best way to resolve this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's actually weird, because it's comparing to ev.detail.item.dataset.userId, yet setting to ev.detail.value:

private _userChanged(ev) {
    const newValue = ev.detail.item.dataset.userId;

    if (newValue !== this._value) {
      this.value = ev.detail.value;
      setTimeout(() => {
        fireEvent(this, "value-changed", { value: newValue });
        fireEvent(this, "change");
      }, 0);
    }
  }

Copy link
Member

@bramkragten bramkragten Oct 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that doesn't seem correct. I think newValue should be ev.detail.value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really strange. So ev.detail.value doesn't even exist (which means that this.value = ev.detail.value; is probably wrong), and ev.newValue is always undefined.
It seems like ev.detail.item.dataset.userId is indeed the right way to grab the currently selected user, but it's unclear how to programmatically select a user...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a red herring - this method on ha-user-picker isn't even called by setting value to "", and it's unclear that value even has any meaning (I thought it was called, because it was called twice when picking a user, so I assumed one of those was a result of setting value to "").
I'm completely stumped 🤷‍♂️

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll put this PR on my todo list :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance we can get it in time for the beta? The core feature is already merged

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try 🙈

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now

@bramkragten
Copy link
Member

If a user removes all users, should the user_id be removed or should it be an empty list?

@OnFreund
Copy link
Contributor Author

Thanks @bramkragten!

If a user removes all users, should the user_id be removed or should it be an empty list?

It should be removed

@bramkragten
Copy link
Member

@OnFreund can you review/test this?

@OnFreund
Copy link
Contributor Author

Looks great, and working. The only thing that's slightly off is that when you add a user, the drop down only contains users who haven't been selected, yet if you open it again after adding a user, it will show all users.

@bramkragten
Copy link
Member

Not seeing that? How can I reproduce that?

@OnFreund
Copy link
Contributor Author

  1. Start with no users
  2. Add one user
  3. Second dropdown only shows "No User", and remaining users. Select one of them
  4. Third dropdown created with "No User" and remaining users.
  5. Second dropdown now has all users.

@bramkragten
Copy link
Member

@OnFreund can you try again?

@OnFreund
Copy link
Contributor Author

Perfect!

@bramkragten bramkragten merged commit 30f34ee into home-assistant:dev Oct 21, 2020
@bramkragten bramkragten mentioned this pull request Oct 21, 2020
@OnFreund OnFreund deleted the event_context branch October 22, 2020 09:34
@github-actions github-actions bot locked and limited conversation to collaborators Jul 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants