Skip to content

Modernization#178

Open
iantrich wants to merge 17 commits intomasterfrom
modernization
Open

Modernization#178
iantrich wants to merge 17 commits intomasterfrom
modernization

Conversation

@iantrich
Copy link
Copy Markdown
Owner

@iantrich iantrich commented Mar 1, 2026

This pull request modernizes and standardizes the development environment, tooling, and workflows for the Home Assistant restriction-card project. It introduces a new dev container setup for seamless local development, upgrades Node.js and build tooling, enforces consistent code style and linting, and refines the CI/CD pipelines for reliability and reproducibility. Documentation and configuration files are also updated to reflect these changes.

Development Environment and Tooling Modernization:

  • Introduced a new .devcontainer setup using a custom Dockerfile based on thomasloven/hass-custom-devcontainer, installing Node.js 24, enabling corepack for Yarn 4, and fixing line endings for compatibility. This provides a consistent, ready-to-use environment for developing and testing the custom card. (.devcontainer/Dockerfile, .devcontainer/DockerfileR1-R13)
  • Added a comprehensive .devcontainer/README.md with setup instructions, workflow details, and troubleshooting for the new dev container environment. (.devcontainer/README.md, .devcontainer/README.mdR1-R111)
  • Updated .devcontainer/devcontainer.json to use the new Dockerfile, improved volume mounts, environment variables, port forwarding, and VS Code extension recommendations for TypeScript and YAML. (.devcontainer/devcontainer.json, .devcontainer/devcontainer.jsonL1-R68)
  • Added .gitattributes to enforce LF line endings and explicitly declare text/binary file types, ensuring cross-platform consistency. (.gitattributes, .gitattributesR1-R19)
  • Added .yarnrc.yml to use node-modules linker for Yarn 4. (.yarnrc.yml, .yarnrc.ymlR1)

Code Quality, Linting, and Formatting:

  • Migrated from legacy .eslintrc.js to a modern eslint.config.js with ESLint Flat Config, TypeScript, Prettier, and import plugins, and updated rules for stricter code quality. (eslint.config.js, [1]; removed .eslintrc.js, [2]R1)
  • Switched Prettier config from .prettierrc.js to .prettierrc.json for better compatibility and added explicit endOfLine: "lf". (.prettierrc.json, [1]; removed .prettierrc.js, [2]

CI/CD Pipeline Improvements:

  • Updated GitHub Actions workflows for build and release to use Node.js 24, Yarn 4 with Corepack, improved caching, and stricter version validation. The release workflow now automatically bumps and validates version numbers in package.json and src/const.ts based on the release tag. (.github/workflows/build.yml, [1]; .github/workflows/release.yml, [2]
  • Ensured environment variables and Node.js setup are consistent across all CI jobs. (.github/workflows/build.yml, [1]; .github/workflows/release.yml, [2]

Documentation and Configuration Updates:

  • Added project-specific Copilot instructions for code standards, architecture, and PR guidance. (.github/copilot-instructions.md, [1]; referenced in AGENTS.md, CLAUDE.md, [2]
  • Updated package.json to specify Yarn 4, Node.js 24, and new version 2.0.0. (package.json, package.jsonL3-R5)
  • Updated Home Assistant minimum version in README.md to reflect new requirements. (README.md, README.mdL21-R21)
  • Updated and cleaned up Home Assistant config and Lovelace UI test files to match new dev container structure. (.devcontainer/config/configuration.yaml, [1]; .devcontainer/ui-lovelace.yaml, [2]

These changes collectively bring the project up to date with modern development practices, improve reliability and onboarding for contributors, and ensure a consistent workflow across local development and CI/CD.

…e test coverage

update directive imports to Lit 3 paths
align card typing with latest HA/custom-card-helpers (including async card size support)
tighten Restriction card/types definitions and remove implicit any usage
improve runtime safety around helper loading and overlay element checks
add focused Vitest coverage for shouldUpdate decision branches
add reactive hass getter to satisfy Lit property contract warnings
resolve lint issues and keep build/test pipeline green
Add a full Lovelace visual editor (src/editor.ts) and integrate it into restriction-card (src/restriction-card.ts). The card now exposes getConfigElement/getStubConfig, dynamically loads the editor, caches the inner card element, builds it lazily, and forwards hass updates. Improved helpers loading, added robust polling/timeout for loadCardHelpers, added timer management (_timers) with a helper to schedule/clear timeouts, and switched blocked-message alerts to dispatch hass-notification events. Coerce duration to number and add duration field in types (deprecated delay retained). Devcontainer updated: switch to thomasloven/hass-custom-devcontainer base, install Node 24 in image, enable corepack, fix CRLF in container script, and set LOVELACE_LOCAL_FILES env. UI Lovelace example trimmed and README Home Assistant minimum version bumped to 2026.2.3. Misc: console logging for debug and small refactors to rendering/shouldUpdate logic.
Copilot AI review requested due to automatic review settings March 1, 2026 04:46
@iantrich iantrich linked an issue Mar 1, 2026 that may be closed by this pull request
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR modernizes the development/tooling setup for the Home Assistant custom card and upgrades the runtime codebase to a new major version, aligning builds, linting, tests, and the devcontainer workflow with newer Node/Yarn/Lit/TypeScript.

Changes:

  • Upgrade runtime to Lit 3 and introduce a Lovelace visual editor for the card (v2.0.0).
  • Modernize build/test/lint toolchain (Rollup 4, ESLint flat config, Prettier 3, Vitest) and move to Yarn 4 via Corepack.
  • Refresh devcontainer + CI workflows for Node.js 24 and updated contributor documentation.

Reviewed changes

Copilot reviewed 27 out of 31 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tsconfig.json Updates TS target/libs and switches module resolution to bundler.
src/types.ts Adds duration, refactors restriction config types, and introduces typed card helper interfaces.
src/restriction-card.ts Migrates to Lit 3, adds editor hooks/stub config, refactors helper loading, caching, and timeout handling.
src/restriction-card.test.ts Adds Vitest coverage for shouldUpdate.
src/editor.ts Adds a full visual editor implementation (restriction-card-editor).
src/const.ts Bumps card version to 2.0.0.
src/action-handler-directive.ts Migrates directive implementation to Lit 3 directive APIs and expands action handling behavior.
rollup.config.js Replaces legacy Rollup plugins with modern @rollup/* plugins; adds dev/prod behaviors and warning filtering.
rollup.config.dev.js Switches dev build to esbuild + improved watch config for container mounts.
package.json Moves to ESM, bumps version, adopts Yarn 4, adds Vitest, updates dependencies and scripts.
package-lock.json Removes npm lockfile (migration to Yarn).
eslint.config.js Introduces ESLint 9 flat config with TS + Prettier integration.
README.md Updates minimum supported Home Assistant version for v2.0.0.
LICENSE Replaces file contents (currently not license text).
CLAUDE.md Adds reference to Copilot instructions.
AGENTS.md Adds reference to Copilot instructions.
.yarnrc.yml Configures Yarn to use node-modules linker.
.prettierrc.json Adds Prettier config (incl. LF line endings).
.prettierrc.js Removes old Prettier config.
.gitignore Expands ignored paths, including devcontainer HA data and Yarn artifacts.
.github/workflows/release.yml Updates release pipeline for Node 24 + Yarn 4 and adds semver/version-bump validation.
.github/workflows/build.yml Updates CI build to Node 24 + Yarn 4 (Corepack).
.github/copilot-instructions.md Adds project-specific Copilot/contributor guidance.
.gitattributes Enforces LF line endings and declares binary files.
.eslintrc.js Removes legacy ESLint config.
.devcontainer/ui-lovelace.yaml Removes example usage of restriction-card from dev Lovelace dashboard.
.devcontainer/devcontainer.json Replaces devcontainer config to build from Dockerfile and run HA + watch builds.
.devcontainer/config/configuration.yaml Updates HA config defaults for devcontainer environment.
.devcontainer/README.md Adds devcontainer setup/workflow documentation.
.devcontainer/Dockerfile Introduces a custom devcontainer image (Node 24 + Corepack).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread LICENSE Outdated
Comment thread src/restriction-card.ts Outdated
Comment thread src/restriction-card.ts Outdated
Comment thread src/restriction-card.test.ts Outdated
Comment thread .github/copilot-instructions.md Outdated
Comment thread .github/copilot-instructions.md Outdated
Comment thread .devcontainer/README.md Outdated
Comment thread .devcontainer/Dockerfile Outdated
Support legacy `delay` config and ensure `duration` is a positive number (coerced and validated), storing a sanitized numeric value in the card config. Update unit tests to use the correct `hass` change key and adjust test setup to compare previous vs current hass state. Rename references in devcontainer README and Copilot instructions from `config-template-card` to `restriction-card`. Replace LICENSE file content with the MIT license.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 26 out of 31 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/release.yml
Comment thread src/restriction-card.ts
Comment thread src/restriction-card.ts Outdated
Comment thread src/restriction-card.ts Outdated
Comment thread src/action-handler-directive.ts
@ildar170975
Copy link
Copy Markdown
Collaborator

@iantrich
Same, ready for testing and review if needed, you can ping me any time.

Refactor card helper loading and timeout handling, tighten touch handling, and clean up debug logs. Key changes:

- .devcontainer: remove LOVELACE_LOCAL_FILES entry.
- action-handler-directive: import forwardHaptic and trigger haptic on hold; wrap touchend listener to call preventDefault before ending action.
- editor: remove customElement decorator import/usage and reorder action option entries.
- restriction-card:
  - remove noisy console logging and lower one message to debug.
  - add _cancelWaitForHelpers and lifecycle cancellation to avoid leaks when disconnected.
  - replace _scheduleTimeout to return IDs and add _clearScheduledTimeout for consistent timeout management.
  - make loadCardHelpers and _waitForCardHelpers more robust: use Promise.race with scheduled timeout, clear resolve timeout on success, add cancellable polling, handle disconnection, and ensure window.load event + polling cooperate.
  - conditionally define the custom element at the end to avoid double-registration.

These changes fix potential timer leaks, improve reliability of helper resolution, and make touch/hold UX more responsive.
@iantrich iantrich linked an issue Mar 1, 2026 that may be closed by this pull request
Use the Lovelace CardHelpers showConfirmationDialog helper when present to display confirmation dialogs (with localized title/button text), and fall back to window.confirm otherwise. Adds an optional showConfirmationDialog signature to CardHelpers in types.ts and updates restriction-card.ts to build localized text and await the helper result before proceeding.
Copilot AI review requested due to automatic review settings March 2, 2026 03:30
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 26 out of 31 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/release.yml
Comment thread src/action-handler-directive.ts
Comment thread src/action-handler-directive.ts Outdated
Comment thread src/restriction-card.ts
Comment thread src/restriction-card.ts Outdated
iantrich added 2 commits March 2, 2026 03:46
Clarify and expand README: document that restriction types are map objects and that an empty map (e.g. block: {} or hide: {}) enables a restriction; add examples for hide with exemptions and condition and update examples to use empty maps instead of booleans. Fix action handler touch behavior: preventDefault on cancelable touchend events and simplify touchend listener to call element.actionHandler.end directly to avoid duplicate handling and unwanted clicks on touch devices. Also remove an obsolete comment in restriction-card.ts.
Copilot AI review requested due to automatic review settings March 2, 2026 03:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread package.json
Comment thread .devcontainer/devcontainer.json
Comment thread src/restriction-card.ts
@@ -118,7 +145,9 @@ class RestrictionCard extends LitElement implements LovelaceCard {
return html`
<div id="mainContainer" style=${ifDefined(styleMap(this._config.css_variables || {}))}>
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

The style binding nests Lit directives (ifDefined(styleMap(...))), which Lit doesn’t support; this can result in the style attribute not being applied (or rendering as "[object Object]"). Bind the style directive directly (and drop ifDefined here), letting styleMap handle empty/undefined values.

Suggested change
<div id="mainContainer" style=${ifDefined(styleMap(this._config.css_variables || {}))}>
<div id="mainContainer" style=${styleMap(this._config.css_variables || {})}>

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@ildar170975 I feel like are much more well versed in the css world of things, can you verify this with the beta release?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I will check in a few days. away from PC now

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Hi @ildar170975, just checking in to see if you've had a chance to test this release yet. Thanks!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hi Ian, please let me recheck all my test cases once again! Last time I checked (almost immediately after your PR) things were OK, but let me be more sure.
In a few days I will be near a PC and recheck everything, please give me a week.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@iantrich
Hi again!
I think we need a bit more efforts to release a "real" 2.0 version, please check the latest issues I just registered.
Will start thinking how to solve these issues.
Also, right now I am testing UI for editing the card's options, may be it will get us issues...

Comment thread .github/workflows/release.yml
Comment thread .github/copilot-instructions.md
@iantrich
Copy link
Copy Markdown
Owner Author

iantrich commented Mar 2, 2026

@ildar170975 I cut a beta release that should be available on HACS now. Please test it out at your leisure. Thanks for all your help in my absence!

Copilot AI review requested due to automatic review settings March 2, 2026 04:31
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 33 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/restriction-card.ts Outdated
Comment thread src/action-handler-directive.ts
Comment thread src/action-handler-directive.ts
Comment thread src/restriction-card.ts Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 2, 2026 13:25
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 33 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/copilot-instructions.md
Comment thread README.md Outdated
Copilot AI review requested due to automatic review settings March 2, 2026 14:04
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 33 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/restriction-card.ts
Comment on lines +88 to +100
const legacyDelay = (config as { delay?: unknown }).delay;
const rawDuration = config.duration ?? legacyDelay ?? 5;
const coercedDuration = Number(rawDuration);

this._config = {
duration: 5,
duration: Number.isFinite(coercedDuration) && coercedDuration > 0 ? coercedDuration : 5,
action: 'tap',
locked_icon: 'mdi:lock-outline',
...config,
};
// Keep validated duration in case YAML input is null/blank/invalid
this._config.duration = Number.isFinite(coercedDuration) && coercedDuration > 0 ? coercedDuration : 5;
// Clear cached element so it is rebuilt with the new config
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

setConfig() assigns duration twice: once in the object literal (before spreading ...config) and again immediately after. This duplication makes the initialization harder to follow. Consider constructing _config so the validated duration is applied once after spreading the user config (so it can’t be overridden by invalid input).

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +55

expect(
card.shouldUpdate(
changedProps([
['_config', {}],
['_hass', createHass('off')],
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

In this test, changedProps uses the key '_hass', but RestrictionCard.shouldUpdate() reads the previous hass from changedProps.get('hass'). That makes this assertion pass for the wrong reason (it will behave as if there was no previous hass). Use ['hass', previousHass] consistently so the test reflects real Lit update behavior.

Suggested change
expect(
card.shouldUpdate(
changedProps([
['_config', {}],
['_hass', createHass('off')],
const previousHass = createHass('on');
(card as RestrictionCardElementForTest & { hass?: HomeAssistant }).hass = createHass('off');
expect(
card.shouldUpdate(
changedProps([
['_config', {}],
['hass', previousHass],

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings March 3, 2026 05:22
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 32 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/restriction-card.ts
Comment on lines 134 to 137
protected render(): TemplateResult | void {
if (!this._config || !this._hass || !this._config.card || !this._helpers) {
console.info('[RC] render() → bailing early (missing required state)');
return html``;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

render() logs at console.info every time required state is missing. Since render() can run frequently in Lovelace, this can spam the console and add overhead during initial load and updates. Consider removing this log or gating it behind an explicit debug flag.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Duration reached feedback missing in case of hold action Homeassitant card editor gui for subcards

3 participants