-
- [[localize('ui.panel.developer-tools.tabs.services.description')]]
-
-
-
-
-
-
-
-
-
- [[localize('ui.panel.developer-tools.tabs.services.no_parameters')]]
-
-
-
-
-
-
- [[localize('ui.panel.developer-tools.tabs.services.column_parameter')]]
- |
-
- [[localize('ui.panel.developer-tools.tabs.services.column_description')]]
- |
-
- [[localize('ui.panel.developer-tools.tabs.services.column_example')]]
- |
-
-
-
- [[attribute.key]] |
- [[attribute.description]] |
- [[attribute.example]] |
-
-
-
-
-
-
-
- [[localize('ui.panel.developer-tools.tabs.services.fill_example_data')]]
-
-
-
-
-
-
-
- `;
- }
-
- static get properties() {
- return {
- hass: {
- type: Object,
- },
-
- domainService: {
- type: String,
- observer: "_domainServiceChanged",
- },
-
- _domain: {
- type: String,
- computed: "_computeDomain(domainService)",
- },
-
- _service: {
- type: String,
- computed: "_computeService(domainService)",
- },
-
- serviceData: {
- type: String,
- value: "",
- },
-
- parsedJSON: {
- type: Object,
- computed: "_computeParsedServiceData(serviceData)",
- },
-
- validJSON: {
- type: Boolean,
- computed: "_computeValidJSON(parsedJSON)",
- },
-
- _attributes: {
- type: Array,
- computed: "_computeAttributesArray(hass, _domain, _service)",
- },
-
- _description: {
- type: String,
- computed: "_computeDescription(hass, _domain, _service)",
- },
-
- rtl: {
- reflectToAttribute: true,
- computed: "_computeRTL(hass)",
- },
- };
- }
-
- _domainServiceChanged() {
- this.serviceData = "";
- }
-
- _computeAttributesArray(hass, domain, service) {
- const serviceDomains = hass.services;
- if (!(domain in serviceDomains)) return [];
- if (!(service in serviceDomains[domain])) return [];
-
- const fields = serviceDomains[domain][service].fields;
- return Object.keys(fields).map(function (field) {
- return { key: field, ...fields[field] };
- });
- }
-
- _computeDescription(hass, domain, service) {
- const serviceDomains = hass.services;
- if (!(domain in serviceDomains)) return undefined;
- if (!(service in serviceDomains[domain])) return undefined;
- return serviceDomains[domain][service].description;
- }
-
- _computeServiceDataKey(domainService) {
- return `panel-dev-service-state-servicedata.${domainService}`;
- }
-
- _computeDomain(domainService) {
- return domainService.split(".", 1)[0];
- }
-
- _computeService(domainService) {
- return domainService.split(".", 2)[1] || null;
- }
-
- _computeParsedServiceData(serviceData) {
- try {
- return serviceData.trim() ? safeLoad(serviceData) : {};
- } catch (err) {
- return ERROR_SENTINEL;
- }
- }
-
- _computeValidJSON(parsedJSON) {
- return parsedJSON !== ERROR_SENTINEL;
- }
-
- _computeHasEntity(attributes) {
- return attributes.some((attr) => attr.key === "entity_id");
- }
-
- _computeEntityValue(parsedJSON) {
- return parsedJSON === ERROR_SENTINEL ? "" : parsedJSON.entity_id;
- }
-
- _computeEntityDomainFilter(domain) {
- return ENTITY_COMPONENT_DOMAINS.includes(domain) ? [domain] : null;
- }
-
- _callService(ev) {
- const button = ev.target;
- if (this.parsedJSON === ERROR_SENTINEL) {
- showAlertDialog(this, {
- text: this.hass.localize(
- "ui.panel.developer-tools.tabs.services.alert_parsing_yaml",
- "data",
- this.serviceData
- ),
- });
- button.actionError();
- return;
- }
- this.hass
- .callService(this._domain, this._service, this.parsedJSON)
- .then(() => {
- button.actionSuccess();
- })
- .catch(() => {
- button.actionError();
- });
- }
-
- _fillExampleData() {
- const example = {};
- this._attributes.forEach((attribute) => {
- if (attribute.example) {
- let value = "";
- try {
- value = safeLoad(attribute.example);
- } catch (err) {
- value = attribute.example;
- }
- example[attribute.key] = value;
- }
- });
- this.serviceData = safeDump(example);
- }
-
- _entityPicked(ev) {
- this.serviceData = safeDump({
- ...this.parsedJSON,
- entity_id: ev.target.value,
- });
- }
-
- _yamlChanged(ev) {
- this.serviceData = ev.detail.value;
- }
-
- _computeRTL(hass) {
- return computeRTL(hass);
- }
-}
-
-customElements.define("developer-tools-service", HaPanelDevService);
diff --git a/src/panels/developer-tools/service/developer-tools-service.ts b/src/panels/developer-tools/service/developer-tools-service.ts
new file mode 100644
index 0000000000..22abadf25f
--- /dev/null
+++ b/src/panels/developer-tools/service/developer-tools-service.ts
@@ -0,0 +1,350 @@
+import { safeLoad } from "js-yaml";
+import {
+ css,
+ CSSResultArray,
+ html,
+ LitElement,
+ property,
+ query,
+} from "lit-element";
+import memoizeOne from "memoize-one";
+import { LocalStorage } from "../../../common/decorators/local-storage";
+import { computeDomain } from "../../../common/entity/compute_domain";
+import { computeObjectId } from "../../../common/entity/compute_object_id";
+import "../../../components/buttons/ha-progress-button";
+import "../../../components/entity/ha-entity-picker";
+import "../../../components/ha-card";
+import "../../../components/ha-expansion-panel";
+import "../../../components/ha-service-control";
+import "../../../components/ha-service-picker";
+import "../../../components/ha-yaml-editor";
+import type { HaYamlEditor } from "../../../components/ha-yaml-editor";
+import { ServiceAction } from "../../../data/script";
+import { haStyle } from "../../../resources/styles";
+import "../../../styles/polymer-ha-style";
+import { HomeAssistant } from "../../../types";
+import "../../../util/app-localstorage-document";
+
+class HaPanelDevService extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property() public narrow!: boolean;
+
+ @LocalStorage("panel-dev-service-state-service-data", true)
+ private _serviceData?: ServiceAction = { service: "", target: {}, data: {} };
+
+ @LocalStorage("panel-dev-service-state-yaml-mode", true)
+ private _yamlMode = false;
+
+ @query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
+
+ protected firstUpdated(params) {
+ super.firstUpdated(params);
+ if (!this._serviceData?.service) {
+ const domain = Object.keys(this.hass.services).sort()[0];
+ const service = Object.keys(this.hass.services[domain]).sort()[0];
+ this._serviceData = {
+ service: `${domain}.${service}`,
+ target: {},
+ data: {},
+ };
+ }
+ }
+
+ protected render() {
+ const { target, fields } = this._fields(
+ this.hass.services,
+ this._serviceData?.service
+ );
+
+ const isValid = this._isValid(this._serviceData, fields, target);
+
+ return html`
+
+
+ ${this.hass.localize(
+ "ui.panel.developer-tools.tabs.services.description"
+ )}
+
+
+ ${this._yamlMode
+ ? html`
`
+ : html`
+
`}
+
+