Compare commits

...

13 Commits

Author SHA1 Message Date
Simon Lamon
9a45fbc488 Merge branch 'dev' into sec_pypi_publishing 2025-11-23 17:01:26 +01:00
Franck Nijhof
4674384f7d Allow deleting helpers directly from helpers panel (#28044)
* Allow deleting helpers directly from helpers panel

* Fix error handling in helper deletion logic

Address review feedback by improving the logic in _deleteHelper:
- Throw error when entity is not found in registry or component not loaded
- Move return statement outside of nested condition to ensure proper control flow
- Prevent fallthrough to config entry deletion for old-style helpers

Addresses review comment from @MindFreeze

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-23 15:20:20 +01:00
steinmn
2e7c95a8cc Translate dashboard panel url error message (#27306)
* Translate dashboard panel url error message

* Use backend provided translations
2025-11-23 14:54:21 +01:00
Simon Lamon
9630b175a1 Remove open from ha-dropdown (#28037) 2025-11-22 14:30:06 +02:00
Petar Petrov
be319503f7 Update color scheme in ZHA network visualization (#28032) 2025-11-21 19:09:37 +01:00
Simon Lamon
aef3cb1c36 Merge branch 'dev' into sec_pypi_publishing 2025-11-20 09:53:07 +01:00
Simon Lamon
8535ee0694 Merge branch 'dev' into sec_pypi_publishing 2025-11-13 06:58:30 +01:00
Simon Lamon
b8110d1a45 Merge branch 'dev' into sec_pypi_publishing 2025-10-27 06:41:51 +01:00
Simon Lamon
19e9de39c5 Merge branch 'dev' into sec_pypi_publishing 2025-10-19 10:56:12 +02:00
Simon Lamon
f22f01e513 Merge branch 'dev' into sec_pypi_publishing 2025-10-06 20:28:38 +02:00
Simon Lamon
3f86f144b5 Merge branch 'dev' into sec_pypi_publishing 2025-10-04 17:25:20 +02:00
Simon Lamon
4efef5ed16 Update release.yaml 2025-09-24 07:04:06 +02:00
Simon Lamon
cac7ae2a40 Remove twine and introduce trusted publishing 2025-09-20 21:23:04 +02:00
8 changed files with 105 additions and 13 deletions

View File

@@ -19,8 +19,11 @@ jobs:
release: release:
name: Release name: Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: pypi
permissions: permissions:
contents: write # Required to upload release assets contents: write # Required to upload release assets
id-token: write # For "Trusted Publisher" to PyPi
if: github.repository_owner == 'home-assistant'
steps: steps:
- name: Checkout the repository - name: Checkout the repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
@@ -46,14 +49,18 @@ jobs:
run: ./script/translations_download run: ./script/translations_download
env: env:
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }} LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
- name: Build and release package - name: Build and release package
run: | run: |
python3 -m pip install twine build python3 -m pip install build
export TWINE_USERNAME="__token__"
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
export SKIP_FETCH_NIGHTLY_TRANSLATIONS=1 export SKIP_FETCH_NIGHTLY_TRANSLATIONS=1
script/release script/release
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
skip-existing: true
- name: Upload release assets - name: Upload release assets
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2 uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
with: with:

View File

@@ -11,7 +11,7 @@ A compact, accessible dropdown menu for choosing actions or settings. `ha-dropdo
### Example usage (composition) ### Example usage (composition)
```html ```html
<ha-dropdown open> <ha-dropdown>
<ha-button slot="trigger" with-caret>Dropdown</ha-button> <ha-button slot="trigger" with-caret>Dropdown</ha-button>
<ha-dropdown-item> <ha-dropdown-item>

View File

@@ -28,7 +28,7 @@ export class DemoHaDropdown extends LitElement {
<div class=${mode}> <div class=${mode}>
<ha-card header="ha-button in ${mode}"> <ha-card header="ha-button in ${mode}">
<div class="card-content"> <div class="card-content">
<ha-dropdown open> <ha-dropdown>
<ha-button slot="trigger" with-caret>Dropdown</ha-button> <ha-button slot="trigger" with-caret>Dropdown</ha-button>
<ha-dropdown-item> <ha-dropdown-item>

View File

@@ -1,5 +1,4 @@
#!/bin/sh #!/bin/sh
# Pushes a new version to PyPi.
# Stop on errors # Stop on errors
set -e set -e
@@ -12,5 +11,4 @@ yarn install
script/build_frontend script/build_frontend
rm -rf dist home_assistant_frontend.egg-info rm -rf dist home_assistant_frontend.egg-info
python3 -m build python3 -m build -q
python3 -m twine upload dist/*.whl --skip-existing

View File

@@ -5,6 +5,7 @@ import {
mdiCancel, mdiCancel,
mdiChevronRight, mdiChevronRight,
mdiCog, mdiCog,
mdiDelete,
mdiDotsVertical, mdiDotsVertical,
mdiMenuDown, mdiMenuDown,
mdiPencilOff, mdiPencilOff,
@@ -109,10 +110,11 @@ import { configSections } from "../ha-panel-config";
import "../integrations/ha-integration-overflow-menu"; import "../integrations/ha-integration-overflow-menu";
import { renderConfigEntryError } from "../integrations/ha-config-integration-page"; import { renderConfigEntryError } from "../integrations/ha-config-integration-page";
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
import { isHelperDomain } from "./const"; import { isHelperDomain, type HelperDomain } from "./const";
import { showHelperDetailDialog } from "./show-dialog-helper-detail"; import { showHelperDetailDialog } from "./show-dialog-helper-detail";
import { slugify } from "../../../common/string/slugify"; import { slugify } from "../../../common/string/slugify";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { HELPERS_CRUD } from "../../../data/helpers_crud";
import { import {
fetchDiagnosticHandlers, fetchDiagnosticHandlers,
getConfigEntryDiagnosticsDownloadUrl, getConfigEntryDiagnosticsDownloadUrl,
@@ -451,6 +453,19 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
}, },
] ]
: []), : []),
...(helper.editable && helper.entity
? [
{
divider: true,
},
{
path: mdiDelete,
label: this.hass.localize("ui.common.delete"),
warning: true,
action: () => this._deleteHelper(helper),
},
]
: []),
]} ]}
> >
</ha-icon-overflow-menu> </ha-icon-overflow-menu>
@@ -1280,6 +1295,62 @@ ${rejected
} }
} }
private async _deleteHelper(helper: HelperItem) {
if (!helper.entity_id) {
return;
}
const confirmed = await showConfirmationDialog(this, {
title: this.hass.localize(
"ui.panel.config.helpers.picker.delete_confirm_title"
),
text: this.hass.localize(
"ui.panel.config.helpers.picker.delete_confirm_text",
{ name: helper.name }
),
confirmText: this.hass.localize("ui.common.delete"),
dismissText: this.hass.localize("ui.common.cancel"),
destructive: true,
});
if (!confirmed) {
return;
}
try {
// For old-style helpers (input_boolean, etc.), use HELPERS_CRUD
if (isHelperDomain(helper.type)) {
const entityReg = this._entityReg.find(
(e) => e.entity_id === helper.entity_id
);
if (
!entityReg?.unique_id ||
!isComponentLoaded(this.hass, helper.type)
) {
throw new Error(
this.hass.localize("ui.panel.config.helpers.picker.delete_failed")
);
}
await HELPERS_CRUD[helper.type as HelperDomain].delete(
this.hass,
entityReg.unique_id
);
return;
}
// For config entry-based helpers, delete the config entry
if (helper.configEntry) {
await deleteConfigEntry(this.hass, helper.configEntry.entry_id);
}
} catch (err: any) {
showAlertDialog(this, {
text:
err.message ||
this.hass.localize("ui.panel.config.helpers.picker.delete_failed"),
});
}
}
private _createHelper() { private _createHelper() {
showHelperDetailDialog(this, {}); showHelperDetailDialog(this, {});
} }

View File

@@ -295,7 +295,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
color: color:
route.route_status === "Active" route.route_status === "Active"
? primaryColor ? primaryColor
: style.getPropertyValue("--disabled-color"), : style.getPropertyValue("--dark-primary-color"),
type: ["Child", "Parent"].includes(neighbor.relationship) type: ["Child", "Parent"].includes(neighbor.relationship)
? "solid" ? "solid"
: "dotted", : "dotted",
@@ -335,7 +335,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
symbolSize: 5, symbolSize: 5,
lineStyle: { lineStyle: {
width: 1, width: 1,
color: style.getPropertyValue("--disabled-color"), color: style.getPropertyValue("--dark-primary-color"),
type: "dotted", type: "dotted",
}, },
ignoreForceLayout: true, ignoreForceLayout: true,

View File

@@ -309,7 +309,20 @@ export class DialogLovelaceDashboardDetail extends LitElement {
} }
this.closeDialog(); this.closeDialog();
} catch (err: any) { } catch (err: any) {
this._error = { base: err?.message || "Unknown error" }; let localizedErrorMessage: string | undefined;
if (err?.translation_domain && err?.translation_key) {
const localize = await this.hass.loadBackendTranslation(
"exceptions",
err.translation_domain
);
localizedErrorMessage = localize(
`component.${err.translation_domain}.exceptions.${err.translation_key}.message`,
err.translation_placeholders
);
}
this._error = {
base: localizedErrorMessage || err?.message || "Unknown error",
};
} finally { } finally {
this._submitting = false; this._submitting = false;
} }

View File

@@ -3265,7 +3265,10 @@
"create_helper": "Create helper", "create_helper": "Create helper",
"no_helpers": "Looks like you don't have any helpers yet!", "no_helpers": "Looks like you don't have any helpers yet!",
"search": "Search {number} {number, plural,\n one {helper}\n other {helpers}\n}", "search": "Search {number} {number, plural,\n one {helper}\n other {helpers}\n}",
"error_information": "Error information" "error_information": "Error information",
"delete_confirm_title": "Delete helper?",
"delete_confirm_text": "Are you sure you want to delete {name}?",
"delete_failed": "Failed to delete helper"
}, },
"dialog": { "dialog": {
"create": "Create", "create": "Create",