Skip to content

Feat first page react - #391

Merged
tpanajott merged 48 commits into
develfrom
feat_first_page_react
Sep 25, 2026
Merged

tpanajott merged 48 commits into
develfrom
feat_first_page_react

Conversation

@tpanajott

Copy link
Copy Markdown
Collaborator

Large set of HTMX features rewritten to React

tpanajott added 30 commits June 28, 2026 21:26
…the edit nspanel page to be a react component
…fixed animation bug with progressbar on edit_nspanel page during updating
…if no warnings were active instead of hiding the container
@tpanajott tpanajott self-assigned this Sep 25, 2026
@tpanajott
tpanajott merged commit 44abbd9 into devel Sep 25, 2026
@tpanajott
tpanajott deleted the feat_first_page_react branch September 25, 2026 18:18
jamesmulcahy added a commit to jamesmulcahy/NSPanelManager that referenced this pull request Sep 26, 2026
- The htmx first-run wizard and the index panels partial are gone; the
  React InitialSetup now saves everything with one POST /rest/settings.
  Test that endpoint (saves, only touches submitted keys, rejects bad
  payloads, reloads once) and that the index shows InitialSetup until a
  manager address is configured.
- /rest/mqttmanager/settings (POST) was removed; keep the banned-key
  tests for the per-key GET endpoint.
- GET /rest/rooms now returns friendly_name, display_order and the
  temperature sensor fields; PUT /rest/rooms updates a room. Pin the
  display_order/displayOrder mismatch in room_put as a known bug.
- Thermostats now require use_current_temperature.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
jamesmulcahy added a commit to jamesmulcahy/NSPanelManager that referenced this pull request Sep 26, 2026
… install

NSPManager#391 replaced the htmx first-run wizard with the React InitialSetup and
removed its htmx_initial_setup_* URLs, but base.html still included
modals/initial_setup/welcome.html whenever manager_address is empty.
That template reverses the removed URLs, so on a fresh install every
page, including the index that shows the new wizard, raised
NoReverseMatch and returned 500.

Remove the include and the now-unreferenced modals/initial_setup
templates, and the index.html script tag for initial_setup.js, which
NSPManager#391 deleted.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
tpanajott pushed a commit that referenced this pull request Sep 26, 2026
… install

#391 replaced the htmx first-run wizard with the React InitialSetup and
removed its htmx_initial_setup_* URLs, but base.html still included
modals/initial_setup/welcome.html whenever manager_address is empty.
That template reverses the removed URLs, so on a fresh install every
page, including the index that shows the new wizard, raised
NoReverseMatch and returned 500.

Remove the include and the now-unreferenced modals/initial_setup
templates, and the index.html script tag for initial_setup.js, which
#391 deleted.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
tpanajott added a commit that referenced this pull request Sep 27, 2026
* NSPanel protobuf data now includes entity type and id for entity slots on entity page

* Add media player entity to NSPanel protobufs (#384)

* Add media player entity to NSPanel protobufs

Add a MediaPlayer entity state (playback state, title, artist, volume,
mute, optional source volume and capability flags), a MediaPlayerCommand
for panel to manager control, and ENTITY_TYPE_MEDIA_PLAYER for entity
page slots.

Also add the REBOOTING panel state that the firmware protobuf already
carries, so regenerated firmware files keep it.

Generated with protoc 27.0 and protoc-gen-c 1.4.1.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01X7aYyRjzk53Sd7gxF46E3u

* Add album art URL to the media player entity state

The manager can fetch the album art from Home Assistant, convert it into
a format the panel can draw, and serve it. The new field tells the panel
where to fetch it. The URL changes whenever the art changes, so the panel
can compare it with the last URL it drew to tell when to fetch again.

Co-Authored-By: Claude Opus 5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>

* Home Assistant media players and album art for NSPanels (#385)

* Add Home Assistant media player entities

Media players can be placed on a room's entities page. The manager follows
the Home Assistant media_player entity and publishes its state to the
NSPanel as an NSPanelEntityState protobuf. Media player commands from the
panel are forwarded to Home Assistant.

Some setups, such as multi-room audio matrices, have a separate volume for
the source feeding a player. How that is exposed in Home Assistant differs
between setups, so a global setting selects a source volume strategy:

- none (default): no source volume.
- player_attributes: the player reports the source volume and the source
  entity ID as state attributes. Volume changes go to the source entity.
- source_entity: the player reports the source entity ID as a state
  attribute and the source's own volume_level is used.

Media players are added through a new REST endpoint for now, the web UI
will follow separately.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01X7aYyRjzk53Sd7gxF46E3u

* Serve media player album art to NSPanels

Media players now save the "entity_picture" attribute from Home Assistant
and give the NSPanel an album_art_url pointing at the Nextion image
server on the manager. The URL includes a hash of the source, so it
changes whenever the album art does.

When a panel requests the image, the manager downloads it from Home
Assistant (once, cached until the art changes) and converts it for the
panel: center cropped and scaled to the requested size (default
100x100), returned as raw little-endian RGB565 pixels. format=png
returns the same image as a PNG for checking the conversion in a
browser.

The Nextion image server was removed from the build because ImageMagick
broke static linking of the release binary. It is back, using the
header-only stb library for decoding and resizing instead.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Validate media player entity requests

- Only accept PUT. Other methods used to create or update entities too.
- Only update existing media players. Passing the ID of another type of
  entity used to overwrite it.
- Check that the entities page belongs to the room and is not a scenes
  page, that the slot is within the page and that it is free.
- Return 400/404 for bad or unknown IDs instead of 500.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Configure source volume per media player instead of globally

The source volume strategy and the attribute names it reads were global
settings, but they describe how one Home Assistant integration exposes
the source feeding a player. A setup with, say, an audio matrix and an
AVR could not describe both, and nothing in the settings UI could have
made that any better.

They are now part of the media player's entity_data, set through the
same PUT /rest/entities/media_players request that creates the player.
All three fields are optional; a player without them keeps its own
volume only.

The endpoint rejects a strategy that is missing the attributes it needs,
which the manager could previously only log and fall back to no source
volume for, leaving the user with no indication of why.

On the manager side HomeAssistantSourceVolumeStrategy::create() reads
the entity's data rather than MqttManagerConfig, so the three
MQTT_MANAGER_SETTING entries are gone. Loading the config now returns
the entity_data for the strategy to be built from, which also fixes the
ordering: the strategy used to be created before the config it depends
on was read.

The web UI for all of this is still missing, see MEDIA_PLAYER_TODO.md.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Address review comments on media players and album art

- Only detach from and reattach to Home Assistant when the media
  player's entity ID changes, and only rebuild the source volume
  strategy when its settings change. A rebuilt strategy starts from the
  last player attributes, since no fresh state is requested otherwise.
- Explicitly reject OpenHAB media players, which are not implemented,
  instead of treating them as unknown controllers.
- Warn about unknown playback actions. NONE is expected, it is sent with
  volume and mute changes.
- Catch exceptions in the Nextion image server request handler and
  respond with a 500 instead.
- Cache converted album art per media player, size and format, so panels
  requesting the same image do not each decode and scale it again.
  get_album_art() returns a shared pointer, which also tells the cache
  when the art has changed.
- Allow images up to 1024 px per side, for format=png on displays larger
  than the NSPanel.
- Use make_shared to create Home Assistant media players, and uint16_t
  for the manager port.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Add a per media player volume step

Some players need bigger or smaller volume steps than others, an Android
TV box might have 10 volume levels where a receiver has 80, so the step
is set per media player rather than globally.

- volume_step is an optional integer between 1 and 100 (%) in
  PUT /rest/entities/media_players. A new media player defaults to 5,
  and updating an existing one without it keeps its current step.
- The MQTTManager reads it from entity_data, falling back to 5 when it
  is missing or invalid, and sends it to the panel.
- NSPanelEntityState.MediaPlayer gains volume_step (field 17). The same
  step applies to the volume and the source volume. Regenerated with
  protoc 27.0.

The firmware's volume up/down buttons and the web UI field are still to
do, see MEDIA_PLAYER_TODO.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Remove MEDIA_PLAYER_TODO.md

It is a local working note rather than part of the change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>

* Updated to latest firmware build and also fixed a bug where nspanel states would get reset when reloading manager config

* Feat first page react (#391)

* First work on first page react setup

* Initial work on react first page

* Almost all functionality is now replicated and improved on from the HTMX based solution

* Pre merge with devel

* Fixed bugs

* There is now a global toast/notify framework for react to use

* React now uses RXStomp as a backend for handling STOMP

* Finishing touces and also removing old HTMX first page setup

* First page now uses react MDI icons instead of web font.

* Fixed typos

* Initial setup is now performed using React instead of bodged HTMX guide

* NSPanel first page view now handles rebooting state correctly

* Updated icons to use mdi SVGs via React and laos updated some error messages

* Updated nspanel firmware protobuf files

* Set fixed height of NSPanel boxes on first page

* Pre devel merge

* Fixed an error where resolved warnings would not be removed from web ui

* Editing entities will now show error in notification instead of in developer console

* Cleanup of old HTMX files and switched nspanel status and actions in the edit nspanel page to be a react component

* NSPanel warnings on edit_nspanel page is now a react component. Also fixed animation bug with progressbar on edit_nspanel page during updating

* Updated style of progressbar during updating in edit_nspanel sidebar

* Fixed a bug where an empty nspanel warnings container would be shown if no warnings were active instead of hiding the container

* NSPanel logs view is now a react component and it's also possible to download nspanel logs now.

* Fixed issues cuasing bun build to fail

* Fixed a bug that caused chrome browsers to fail to connect to stomp socket via react components

* Fixed a bug where debouncing of state update events in rooms were not working correctly

* Updated CSS

* Updated theme

* Static grid complete

* Background animation of boxes on NSPanelBox now follows cursor with a gradiant

* Small visual improvments

* Will now set permissions on manifest.json as to be able to merge changes from different branches

* Also set permissions on dir

* Fixed tiles animation visibility

* Started work on make eidt_room a full react page

* Moved stop into docker dir

* It's now possible to change room name and temperature sensor

* Manager configured NSPanel friendly name is now repected and retained across NSPanel reboots

* Updated gitignore

* Fixed openhab lights not loading the correct key for openhab item for switches in the new React setup

* Fixed multiple react bugs. Also fixed a bug that caused all panels to become of state "offline" when the manager reloaded.

* Add port, container name and seed path options to the dev build script (#387)

* Add port, container name and seed path options to the dev build script

docker-build_and_run_dev.sh always ran on port 8000 as a container named
nspanelmanager, so a second dev stack could not run next to the first.

- --external-port: host port mapped to the container's port 8000.
- --container-name: name of the running container.
- --config-seed-path: where to copy db.sqlite3 and secret.key from when
  data/ does not have them yet. Defaults to the current directory, as
  before.

--target-platform only shifted once, so its value was parsed as the next
option. It now shifts past the value like the new options.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Fail fast when --config-seed-path is missing the DB or secret key

An explicit seed path with a typo previously fell through silently and
started the stack with an empty database. Now the script exits before
building if either file is missing, and warns when data/ already has
files that the seed will not overwrite.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>

* Remove the leftover htmx setup wizard that 500s every page on a fresh install

#391 replaced the htmx first-run wizard with the React InitialSetup and
removed its htmx_initial_setup_* URLs, but base.html still included
modals/initial_setup/welcome.html whenever manager_address is empty.
That template reverses the removed URLs, so on a fresh install every
page, including the index that shows the new wizard, raised
NoReverseMatch and returned 500.

Remove the include and the now-unreferenced modals/initial_setup
templates, and the index.html script tag for initial_setup.js, which
#391 deleted.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: James Mulcahy <[email protected]>
Co-authored-by: Claude Opus 5 <[email protected]>
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.

1 participant