Skip to content

UI - Watchlist - "Mark unviewed" bulk operation - #4484

Open
pongoe wants to merge 3 commits into
dgtlmoon:masterfrom
pongoe:watchlist-mark-unviewed
Open

pongoe wants to merge 3 commits into
dgtlmoon:masterfrom
pongoe:watchlist-mark-unviewed

Conversation

@pongoe

@pongoe pongoe commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Closes #4382

Adds a "Mark unviewed" button next to "Mark viewed" in the watch list bulk operations bar.

The use case is the one in the issue. You open a change, you cannot deal with it yet, and you want the watch to show as unviewed again.

The operation sets last_viewed back to the timestamp of the second-newest snapshot, not to 0. As a result, the row is unviewed again and [diff] still opens on the latest change, not on the full history. Watches with fewer than two snapshots have no change to un-view, so the operation skips them. The toast shows the real count.

The form POST and the socket.io path both go through _handle_operations, so both work.

  • Test: tests/test_mark_unviewed.py
  • Translation catalogues regenerated (extract_messages / update_catalog)

Winds last_viewed back to the second-newest snapshot so the row shows as
unviewed again and [diff] still opens on the latest change. Watches with
fewer than two snapshots are skipped, there is no change to un-view.
@dgtlmoon

Copy link
Copy Markdown
Owner

Strange, this breaks test_element_removal_full


2026-09-23T22:34:50.3006817Z __________________________ test_element_removal_full ___________________________
2026-09-23T22:34:50.3007144Z [gw6] linux -- Python 3.11.16 /usr/local/bin/python3.11
2026-09-23T22:34:50.3007335Z 
2026-09-23T22:34:50.3007470Z client = <FlaskClient <Flask 'changedetectionio.flask_app'>>
2026-09-23T22:34:50.3008006Z live_server = <LiveServer listening at http://localhost:40587>
2026-09-23T22:34:50.3009794Z measure_memory_usage = None
2026-09-23T22:34:50.3010201Z datastore_path = '/tmp/pytest-of-root/pytest-0/popen-gw6/test-datastore-gw60'
2026-09-23T22:34:50.3010705Z 
2026-09-23T22:34:50.3010968Z     def test_element_removal_full(client, live_server, measure_memory_usage, datastore_path):
2026-09-23T22:34:50.3011401Z     
2026-09-23T22:34:50.3011571Z     
2026-09-23T22:34:50.3011826Z         set_original_response(datastore_path=datastore_path)
2026-09-23T22:34:50.3012136Z     
2026-09-23T22:34:50.3012301Z     
2026-09-23T22:34:50.3012491Z         # Add our URL to the import page

@dgtlmoon

Copy link
Copy Markdown
Owner

re-running tests

@dgtlmoon

Copy link
Copy Markdown
Owner

@pongoe the test_element_removal_full failure is caused by this PR, although it doesn't look like it at first. The test is just too loose.

changedetectionio/tests/test_element_removal.py:209 checks that no unviewed change is left by doing a plain substring search on the whole watch list page:

res = client.get(url_for("watchlist.index"))
assert b"unviewed" not in res.data

This PR adds the button value="mark-unviewed" / Mark unviewed to watch-overview.html, so the word "unviewed" now appears on every watch list page that has a watch on it, whatever the watch's state. The assertion will always fail.

Fix: check for the CSS class the row actually gets, which is what your new test_mark_unviewed.py already does:

assert b'has-unread-changes' not in res.data

Also, changedetectionio/tests/test_ignorehyperlinks.py:114 (assert b"unviewed" in res.data) now passes no matter what, so it no longer tests anything. Please switch it to b'has-unread-changes' in res.data in the same PR.

(The later re-run failed for a different reason: it couldn't download the Docker image artifact, so no tests ran.)

@dgtlmoon

Copy link
Copy Markdown
Owner

So yeah, please find a way to fix that other test :-)

…nviewed"

The new "Mark unviewed" button puts the word "unviewed" on every watch list
page, so these substring checks always failed or always passed.
…ewed

# Conflicts:
#	changedetectionio/translations/messages.pot
@pongoe

pongoe commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for digging into the failure. You're dead right. I tried it both ways, the old check failed and the new one passed, so this is definitely the fix now. Swapped both tests over like you said. Thank God it's the weekend!

This branch has not been deployed

No deployments
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.

[feature] mark as read/unread

2 participants