Skip to content

Conversation

@elibosley
Copy link
Member

@elibosley elibosley commented May 14, 2025

Summary by CodeRabbit

  • New Features

    • Changelog modal now displays changelog documentation within an embedded iframe if a URL is available, allowing navigation within the iframe and providing a "Back to Changelog" button to return to the original view.
    • "View on Docs" button dynamically updates to reflect the current page within the iframe.
    • Added support for displaying a formatted changelog string and testing modal behavior with or without this content.
    • Introduced a new component to fetch, parse, and render changelogs from URLs with enhanced markdown handling.
    • Update OS store extended to manage changelog display and release stability, consolidating changelog state and actions.
  • Bug Fixes

    • Close button in modal dialogs is now visible on all screen sizes.
  • Chores

    • Updated the default server state, which may affect registration device counts and types.
    • Added new localization string for changelog titles with version placeholders.
    • Removed deprecated changelog store and related tests, simplifying state management.
    • Refined backup and restoration scripts for unraid-components directory to use move operations with improved logging.
    • Improved modal visibility state handling by consolidating changelog modal controls into the main update OS store.
    • Added URL origin and pattern checks for changelog iframe navigation security.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 14, 2025

Walkthrough

This update changes the default server state from 'ENOKEYFILE' to 'BASIC', affecting registration parameters. The modal close button is made visible on all screen sizes. The changelog modal now embeds changelogs in an iframe with navigation tracking, a "Back to Changelog" button, and dynamic links. A new RawChangelogRenderer component was introduced as a fallback for changelog rendering. The changelog store and its tests were removed, consolidating changelog logic into the main update OS store. Translation strings and localization were added accordingly.

Changes

File(s) Change Summary
web/_data/serverState.ts Changed default server state from 'ENOKEYFILE' to 'BASIC', updating registration device count and type accordingly. No changes to exports or public API.
web/components/Modal.vue Removed hidden class from close button container to make the close button visible on all screen sizes starting from small. No API changes.
web/components/UpdateOs/ChangelogModal.vue Refactored changelog modal to display changelog in an iframe if a changelog URL is present. Added iframe navigation tracking via postMessage, a "Back to Changelog" button to reset navigation, dynamic "View on Docs" link reflecting current iframe URL, event listeners for navigation messages, and updated icons. Removed previous error parsing display and raw HTML changelog rendering in favor of fallback component. Added reactive refs, computed properties, lifecycle hooks, and template changes to support new iframe-based UI.
web/components/UpdateOs/RawChangelogRenderer.vue Added new Vue 3 component to fetch, parse, and render changelog markdown from a URL with custom markdown parsing and link adjustments. Handles loading, error states, and displays a parsed changelog with version and date.
web/pages/changelog.vue Replaced useUpdateOsChangelogStore with useUpdateOsStore. Added async fetch function to load release data and set in store. Modified test functions to set releases with various changelog states including empty and broken data. Updated template with buttons to trigger these functions alongside the original fetch button.
web/store/updateOsChangelog.ts Removed entire changelog store module including state, getters, actions, and watchers related to changelog fetching and parsing. Changelog logic consolidated into main update OS store.
web/store/updateOs.ts Extended main update OS store with new state and computed properties for changelog modal visibility, release details, changelog URLs, and release stability checks. Renamed modalOpen to updateOsModalVisible. Added actions to set release for update and confirm installation.
web/components/Modals.ce.vue Removed import and usage of useUpdateOsChangelogStore. Updated modal visibility and release data to use useUpdateOsStore only. Updated UpdateOsChangelogModal open prop to use new store state.
web/components/UpdateOs/CheckUpdateResponseModal.vue Removed import and usage of useUpdateOsChangelogStore. Redirected release update setting to useUpdateOsStore. No other logic changes.
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php Added new translation entry for "Unraid OS {0} Changelog" with version placeholder. No changes to exported entities.
web/locales/en_US.json Added new localization string key "Unraid OS {0} Changelog" with corresponding English value. No changes to existing entries.
web/__test__/store/updateOsChangelog.test.ts Removed entire test suite for the removed changelog store.
web/__test__/store/updateOs.test.ts Updated test assertions to replace modalOpen with updateOsModalVisible reflecting store state rename. No other test logic changes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ChangelogModal
    participant Iframe
    participant Docs

    User->>ChangelogModal: Open changelog modal
    ChangelogModal->>Iframe: Load changelog URL
    User->>Iframe: Navigate within iframe
    Iframe-->>ChangelogModal: PostMessage (navigation event)
    ChangelogModal->>ChangelogModal: Update navigation state
    User->>ChangelogModal: Click "Back to Changelog"
    ChangelogModal->>Iframe: Reset src to original changelog URL
    ChangelogModal->>Docs: "View on Docs" (opens current iframe URL)
Loading

Suggested reviewers

  • mdatelle
  • pujitm
  • zackspear

Poem

Changelogs now in iframes dwell,
With buttons to guide and stories to tell.
A modal close now clear in sight,
Server state set just right.
Markdown parsing trimmed away,
New components lead the way.
🚀📜✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 6981b77 and 384fc71.

📒 Files selected for processing (3)
  • web/components/UpdateOs/ChangelogModal.vue (3 hunks)
  • web/components/UpdateOs/RawChangelogRenderer.vue (1 hunks)
  • web/helpers/urls.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • web/helpers/urls.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/components/UpdateOs/RawChangelogRenderer.vue
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (7)
web/components/UpdateOs/ChangelogModal.vue (7)

39-46: Well-structured iframe navigation setup

Good implementation of reactive state management for the iframe navigation with clear variable naming. The computed property for docsChangelogUrl correctly handles the null case.


52-72: Secure iframe message handling implementation

The message handler properly implements multiple layers of validation:

  1. Message type verification
  2. Source window validation
  3. Origin validation using regex pattern
  4. URL format and value validation

This addresses security concerns raised in previous reviews about preventing message spoofing and ensuring only trusted origins can trigger navigation changes.


74-82: Proper event listener lifecycle management

Good practice using Vue lifecycle hooks to register and clean up event listeners, preventing potential memory leaks.


84-90: Clean implementation of navigation reset function

The function to revert to the initial changelog effectively manages both the iframe source and the component state.


125-132: Well-structured fallback for changelog rendering

Good use of conditional rendering to fall back to the raw changelog when a pretty URL is not available, ensuring users always get the changelog content regardless of format availability.


134-141: Clear loading state implementation

The loading state provides good user feedback with both visual (spinner) and text indicators.


148-155: Improved navigation UX with context-aware buttons

Good implementation of conditional navigation controls:

  1. "Back to Changelog" button appears only when navigated away from the main changelog
  2. "View on Docs" button dynamically uses the current navigation state

These improvements provide a better user experience when exploring changelog links.

Also applies to: 157-165


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
web/components/UpdateOs/ChangelogModal.vue (1)

90-93: Synchronise iframe content when switching releases

watch(docsChangelogUrl, …) resets state but leaves the old document visible until Vue re-renders (which may not happen if the element is reused). Push the new URL directly to the iframe to avoid brief flashes of the previous changelog.

 watch(docsChangelogUrl, (newUrl) => {
   currentIframeUrl.value = newUrl;
   hasNavigated.value = false;
+  if (iframeRef.value && newUrl) {
+    iframeRef.value.src = newUrl;
+  }
 });

This guarantees the iframe is always in sync with the selected release.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e580f64 and 2bd218f.

📒 Files selected for processing (5)
  • web/_data/serverState.ts (1 hunks)
  • web/components/Modal.vue (1 hunks)
  • web/components/UpdateOs/ChangelogModal.vue (3 hunks)
  • web/pages/changelog.vue (3 hunks)
  • web/store/updateOsChangelog.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test API
  • GitHub Check: Build Web App
  • GitHub Check: Build API
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (9)
web/components/Modal.vue (1)

124-124: Close button visibility improved

The close button container is now visible on all screen sizes by removing the hidden class, improving accessibility and usability across devices.

web/store/updateOsChangelog.ts (1)

23-23: Added debug logging for changelog fetching

Additional logging will be helpful for tracking when changelog data is updated and fetched.

web/pages/changelog.vue (6)

7-7: Added support for pretty-formatted changelogs

The new changelogPretty reactive variable will store formatted changelog content from the release JSON.


13-13: Added debug logging for changelog data

Helpful logging for development and debugging purposes.


16-16: Storing pretty-formatted changelog content

The code now properly stores the formatted changelog content from the fetched data.


26-31: Updated changelog modal trigger with pretty content

The function now correctly provides the pretty-formatted changelog to the modal component, along with required metadata.


34-46: Added test function for non-pretty changelog display

This function allows testing the modal's fallback behavior when pretty-formatted content is unavailable.


55-68: Improved test UI with additional button

The UI now provides two distinct testing options with proper spacing, allowing for more comprehensive testing of the changelog modal functionality.

web/components/UpdateOs/ChangelogModal.vue (1)

124-128: Confirm mutatedParsedChangelog is sanitised before injecting with v-html

Directly binding raw HTML invites XSS if upstream sanitisation ever slips. Please ensure the string is produced with a trusted sanitiser (e.g., DOMPurify) or add one here.

elibosley and others added 3 commits May 19, 2025 12:23
@elibosley elibosley force-pushed the feat/changelog-iframe branch from 5276cde to 05e9a00 Compare May 19, 2025 16:23
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
web/pages/changelog.vue (1)

91-92: ⚠️ Potential issue

Raw HTML insertion is XSS-prone

v-html="changelog" renders whatever HTML the remote service returns. If that source is ever compromised, users could receive arbitrary scripts.

Mitigation: sanitize with DOMPurify (or similar) before assignment.

-import { ref } from 'vue';
+import { ref } from 'vue';
+import DOMPurify from 'dompurify';-        changelog.value = data[0].changelog;
+        changelog.value = DOMPurify.sanitize(data[0].changelog);

This is a security fix, not a cosmetic change.

🧹 Nitpick comments (8)
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php (1)

199-201: Typo: It\s should be It’s

Unrelated to this PR but worth fixing while you’re touching the file—\s renders literally.

-'It\s highly recommended to review the changelog before continuing your update.' => _('It\'s highly recommended to review the changelog before continuing your update.'),
+'It\'s highly recommended to review the changelog before continuing your update.' => _('It\'s highly recommended to review the changelog before continuing your update.'),
web/store/updateOsChangelog.ts (2)

15-18: Return null consistently for “no URL”

changelogUrl falls back to an empty string, whereas changelogPretty returns null. Consumers that treat the two props similarly might have to branch twice.

-const changelogUrl = computed((): string => releaseForUpdate.value?.changelog || '');
+const changelogUrl = computed((): string | null =>
+  releaseForUpdate.value?.changelog ?? null,
+);

Using null for “absent” mirrors the optional field in the API type and keeps truthiness checks uniform.


27-39: Minor: guard against empty sha256

fetchAndConfirmInstall will happily enqueue a callback with an empty hash. A quick guard avoids “invalid param” issues later.

-const fetchAndConfirmInstall = (sha256: string) => {
+const fetchAndConfirmInstall = (sha256: string) => {
+  if (!sha256) return;
web/components/UpdateOs/RawChangelogRenderer.vue (2)

88-90: Duplicate network hit

onMounted(fetchAndParseChangelog) plus a watch(..., { immediate: true }) triggers two identical requests on mount.

Remove one of them to halve latency & load:

-onMounted(fetchAndParseChangelog);
-watch(() => props.changelog, fetchAndParseChangelog, { immediate: true });
+watch(() => props.changelog, fetchAndParseChangelog, { immediate: true });

92-97: Fragile <h1> stripping

Using a single regex assumes the first heading is on one line and not preceded by whitespace or attributes. marked already gives you renderer hooks—just skip depth 1 headings instead of injecting <br /> and post-processing.

web/pages/changelog.vue (1)

13-13: Remove the permanent console log

console.debug('[changelog] data', data); is helpful while developing but pollutes production logs.
Swap it for a conditional if (import.meta.env.DEV) or delete it before shipping.

web/components/UpdateOs/ChangelogModal.vue (2)

113-119: Consider dropping allow-same-origin

Including allow-same-origin restores the iframe’s normal origin, enabling it to read/write its own cookies and potentially relaxes certain sandbox protections.
If the docs page does not need document.cookie, switching to:

sandbox="allow-scripts"

further reduces the blast radius of a compromised docs site.
Up to you, but worth evaluating.


147-154: Button lacks type="button"

Inside forms (Modal content could be nested in a <form> in the future), the default type is “submit”. Adding an explicit type="button" prevents accidental submissions.

-<BrandButton
+<BrandButton
+  type="button"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 1c1dcdd and 48a96f6.

📒 Files selected for processing (7)
  • plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php (2 hunks)
  • web/components/Modal.vue (1 hunks)
  • web/components/UpdateOs/ChangelogModal.vue (2 hunks)
  • web/components/UpdateOs/RawChangelogRenderer.vue (1 hunks)
  • web/locales/en_US.json (1 hunks)
  • web/pages/changelog.vue (3 hunks)
  • web/store/updateOsChangelog.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • web/locales/en_US.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/components/Modal.vue
🧰 Additional context used
🧬 Code Graph Analysis (2)
web/store/updateOsChangelog.ts (2)
web/store/callbackActions.ts (1)
  • useCallbackActionsStore (26-184)
web/types/server.ts (1)
  • ServerUpdateOsResponse (53-62)
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php (1)
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.plugin.manager/include/UnraidCheck.php (1)
  • _ (108-108)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Build API
  • GitHub Check: Build Web App
  • GitHub Check: Test API
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php (2)

396-396: 👍 Apostrophe swap looks good

The curly apostrophe has been replaced with a straight ASCII one, which avoids encoding headaches and keeps the key “safe-character” compliant.
No further action required.


405-405: New key added consistently

The new entry follows the existing sprintf pattern and placeholder style, so downstream consumers will pick it up without surprises.
Looks good.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
web/pages/changelog.vue (1)

13-21: ⚠️ Potential issue

Add network-error handling to the fetch

fetch() failures (offline, 5xx, CORS, bad JSON, etc.) will currently throw and leave the page blank.
Wrap the call in try / catch and surface a user-friendly message instead of crashing.

 onMounted(async () => {
-    const response = await fetch('https://releases.unraid.net/json');
-    const data = await response.json();
-    console.debug('[changelog] data', data);
-    if (data.length > 0) {
-        changelog.value = data[0].changelog;
-        changelogPretty.value = data[0].changelog_pretty;
-    }
+    try {
+        const response = await fetch('https://releases.unraid.net/json');
+        if (!response.ok) throw new Error(`HTTP ${response.status}`);
+        const data = await response.json();
+        console.debug('[changelog] data', data);
+        if (data.length > 0) {
+            changelog.value = data[0].changelog;
+            changelogPretty.value = data[0].changelog_pretty;
+        }
+    } catch (error) {
+        console.error('[changelog] Failed to fetch or parse data:', error);
+        // Set user-friendly error message
+        changelog.value = `<p>Unable to load changelog data. Please try again later.</p>`;
+    }
 });
web/components/UpdateOs/ChangelogModal.vue (1)

51-66: ⚠️ Potential issue

Fix the URL validation in the iframe message handler

The origin check at line 57 is too strict and won't account for ports (like :443) or variations in the docs domain. Additionally, the code assigns event.data.url to currentIframeUrl without validation, which could lead to security issues.

Apply this change to properly validate both the origin and URL:

-    event.origin === 'https://docs.unraid.net'
+    typeof event.origin === 'string' &&
+    event.origin.startsWith('https://docs.unraid.net') &&
+    // Validate URL is also from docs domain
+    typeof event.data.url === 'string' &&
+    event.data.url.startsWith('https://docs.unraid.net')

This prevents potential security issues where:

  1. Valid origins with explicit ports might be rejected
  2. Malicious docs pages could emit arbitrary URLs through postMessage
🧹 Nitpick comments (2)
web/pages/changelog.vue (2)

36-60: Added testing functions for edge cases

Two new functions have been added to test the changelog modal with different data scenarios (missing pretty format and broken parsing), which helps validate fallback behavior.

Consider adding a comment explaining these are for testing/development purposes, or conditionally including them only in development environments:

+// Testing functions for development - consider hiding in production
 function showChangelogWithoutPretty() {

67-87: Added UI elements for testing edge cases

The template has been updated to use the new store's modal visibility state and adds buttons for testing different changelog scenarios.

Consider conditionally showing these test buttons only in development mode:

+<div v-if="import.meta.env.DEV" class="mb-6 flex gap-4">
-<div class="mb-6 flex gap-4">
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between f793d73 and a2809af.

📒 Files selected for processing (9)
  • web/__test__/store/updateOs.test.ts (2 hunks)
  • web/__test__/store/updateOsChangelog.test.ts (0 hunks)
  • web/components/Modals.ce.vue (1 hunks)
  • web/components/UpdateOs/ChangelogModal.vue (3 hunks)
  • web/components/UpdateOs/CheckUpdateResponseModal.vue (1 hunks)
  • web/components/UpdateOs/RawChangelogRenderer.vue (1 hunks)
  • web/pages/changelog.vue (1 hunks)
  • web/store/updateOs.ts (4 hunks)
  • web/store/updateOsChangelog.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • web/store/updateOsChangelog.ts
  • web/test/store/updateOsChangelog.test.ts
✅ Files skipped from review due to trivial changes (1)
  • web/components/Modals.ce.vue
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/components/UpdateOs/RawChangelogRenderer.vue
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Test API
  • GitHub Check: Build Web App
  • GitHub Check: Build API
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (17)
web/__test__/store/updateOs.test.ts (2)

61-61: Updated property name for better clarity

The test now uses the more descriptive updateOsModalVisible property name instead of what was likely modalOpen, making the test more understandable.


89-89: Property name changed consistently

The test has been consistently updated to use updateOsModalVisible instead of the previous property name, ensuring the test matches the implementation.

Also applies to: 94-94, 97-97

web/components/UpdateOs/CheckUpdateResponseModal.vue (1)

182-182: Store migration completed correctly

The click handler now uses updateOsStore.setReleaseForUpdate() instead of the previous changelog-specific store, aligning with the consolidation of changelog functionality into the main update OS store.

web/pages/changelog.vue (3)

2-5: Imports updated for store consolidation

The imports have been updated to use the consolidated useUpdateOsStore instead of the previous separate changelog store, with appropriate reactive helpers.


8-10: Added support for pretty changelog format

The component now has a new reactive variable for formatted changelog content and correctly retrieves store properties using storeToRefs.


23-34: Updated changelog modal function for the consolidated store

The function now correctly includes the new changelogPretty field and uses the consolidated updateOsStore.

web/store/updateOs.ts (6)

12-13: Added required dependencies for changelog functionality

The store now properly imports the semver prerelease function for release stability checking and the callback actions store for update confirmation.


28-30: Renamed and added state properties for clarity

The modalOpen property was renamed to the more descriptive updateOsModalVisible, and new state for managing changelog visibility and release details has been added.


66-91: Consolidated changelog functionality

Changelog-related logic previously in a separate store has been consolidated here, including URL handling, pretty format support, and update confirmation functionality.


129-129: Updated setter for renamed property

The setModalOpen action now correctly updates the renamed updateOsModalVisible property.


137-146: Exposed new state and getters

The store now properly exposes the renamed modal visibility state and new changelog-related properties.


151-152: Exposed new actions

The new actions for setting release details and confirming installation are now properly exposed from the store.

web/components/UpdateOs/ChangelogModal.vue (5)

109-115: Sandbox attribute looks good

The iframe has been properly secured with a sandbox attribute that allows only the minimum required capabilities (scripts and same-origin).


143-149: Back to Changelog button implementation looks good

The "Back to Changelog" button properly appears only when navigated away from the main changelog, and correctly resets the iframe to the initial URL.


152-159: View on Docs button correctly uses the current URL

The button now uses the current iframe URL or falls back to the original changelog URL, which ensures users can always access the documentation externally.


119-126: Good fallback implementation with RawChangelogRenderer

Using the RawChangelogRenderer as a fallback when no changelog URL is available ensures users can still view changelog content even without iframe support.


86-89: Good URL tracking implementation

The watch on docsChangelogUrl ensures that the component state is reset properly when the changelog URL changes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
web/pages/changelog.vue (1)

11-15: ⚠️ Potential issue

Add error handling to the fetch call

The showChangelogModalFromReleasesEndpoint function lacks error handling for network failures, which could cause the page to crash when offline or encountering server errors.

 async function showChangelogModalFromReleasesEndpoint() {
-    const response = await fetch('https://releases.unraid.net/os?branch=stable&current_version=6.12.3');
-    const data = await response.json();
-    updateOsStore.setReleaseForUpdate(data);
+    try {
+        const response = await fetch('https://releases.unraid.net/os?branch=stable&current_version=6.12.3');
+        if (!response.ok) throw new Error(`HTTP ${response.status}`);
+        const data = await response.json();
+        updateOsStore.setReleaseForUpdate(data);
+    } catch (error) {
+        console.error('Failed to fetch changelog data:', error);
+        // Optional: Set an error state in the store or display a user-friendly message
+    }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between a2809af and 571e578.

📒 Files selected for processing (1)
  • web/pages/changelog.vue (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Build Web App
  • GitHub Check: Build API
  • GitHub Check: Test API
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
web/pages/changelog.vue (3)

3-8: Good use of store refactoring and Pinia best practices

The refactoring to use the consolidated useUpdateOsStore and properly extracting reactive state with storeToRefs follows Vue 3 and Pinia best practices.


29-53: Good test coverage with edge cases

The test functions effectively cover various scenarios including missing pretty changelog URL and completely broken changelog links, which will help ensure the component handles edge cases properly.


61-85: Well-organized test UI

The test UI provides clear, visually distinct buttons for each test scenario, making it easy to test different changelog rendering conditions.

@github-actions
Copy link
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1388/dynamix.unraid.net.plg

@elibosley elibosley merged commit fcd6fbc into main May 19, 2025
12 checks passed
@elibosley elibosley deleted the feat/changelog-iframe branch May 19, 2025 19:34
pujitm pushed a commit that referenced this pull request Jul 8, 2025
🤖 I have created a release *beep* *boop*
---


## [4.9.0](v4.8.0...v4.9.0)
(2025-07-08)


### Features

* add graphql resource for API plugins
([#1420](#1420))
([642a220](642a220))
* add management page for API keys
([#1408](#1408))
([0788756](0788756))
* add rclone ([#1362](#1362))
([5517e75](5517e75))
* API key management
([#1407](#1407))
([d37dc3b](d37dc3b))
* api plugin management via CLI
([#1416](#1416))
([3dcbfbe](3dcbfbe))
* build out docker components
([#1427](#1427))
([711cc9a](711cc9a))
* docker and info resolver issues
([#1423](#1423))
([9901039](9901039))
* fix shading in UPC to be less severe
([#1438](#1438))
([b7c2407](b7c2407))
* info resolver cleanup
([#1425](#1425))
([1b279bb](1b279bb))
* initial codeql setup
([#1390](#1390))
([2ade7eb](2ade7eb))
* initialize claude code in codebse
([#1418](#1418))
([b6c4ee6](b6c4ee6))
* move api key fetching to use api key service
([#1439](#1439))
([86bea56](86bea56))
* move to cron v4 ([#1428](#1428))
([b8035c2](b8035c2))
* move to iframe for changelog
([#1388](#1388))
([fcd6fbc](fcd6fbc))
* native slackware package
([#1381](#1381))
([4f63b4c](4f63b4c))
* send active unraid theme to docs
([#1400](#1400))
([f71943b](f71943b))
* slightly better watch mode
([#1398](#1398))
([881f1e0](881f1e0))
* upgrade nuxt-custom-elements
([#1461](#1461))
([345e83b](345e83b))
* use bigint instead of long
([#1403](#1403))
([574d572](574d572))


### Bug Fixes

* activation indicator removed
([5edfd82](5edfd82))
* alignment of settings on ManagementAccess settings page
([#1421](#1421))
([70c790f](70c790f))
* allow rclone to fail to initialize
([#1453](#1453))
([7c6f02a](7c6f02a))
* always download 7.1 versioned files for patching
([edc0d15](edc0d15))
* api `pnpm type-check`
([#1442](#1442))
([3122bdb](3122bdb))
* **api:** connect config `email` validation
([#1454](#1454))
([b9a1b9b](b9a1b9b))
* backport
unraid/webgui[#2269](https://github.com/unraid/api/issues/2269) rc.nginx
update ([#1436](#1436))
([a7ef06e](a7ef06e))
* bigint
([e54d27a](e54d27a))
* config migration from `myservers.cfg`
([#1440](#1440))
([c4c9984](c4c9984))
* **connect:** fatal race-condition in websocket disposal
([#1462](#1462))
([0ec0de9](0ec0de9))
* **connect:** mothership connection
([#1464](#1464))
([7be8bc8](7be8bc8))
* console hidden
([9b85e00](9b85e00))
* debounce is too long
([#1426](#1426))
([f12d231](f12d231))
* delete legacy connect keys and ensure description
([22fe91c](22fe91c))
* **deps:** pin dependencies
([#1465](#1465))
([ba75a40](ba75a40))
* **deps:** pin dependencies
([#1470](#1470))
([412b329](412b329))
* **deps:** storybook v9
([#1476](#1476))
([45bb49b](45bb49b))
* **deps:** update all non-major dependencies
([#1366](#1366))
([291ee47](291ee47))
* **deps:** update all non-major dependencies
([#1379](#1379))
([8f70326](8f70326))
* **deps:** update all non-major dependencies
([#1389](#1389))
([cb43f95](cb43f95))
* **deps:** update all non-major dependencies
([#1399](#1399))
([68df344](68df344))
* **deps:** update dependency @types/diff to v8
([#1393](#1393))
([00da27d](00da27d))
* **deps:** update dependency cache-manager to v7
([#1413](#1413))
([9492c2a](9492c2a))
* **deps:** update dependency commander to v14
([#1394](#1394))
([106ea09](106ea09))
* **deps:** update dependency diff to v8
([#1386](#1386))
([e580f64](e580f64))
* **deps:** update dependency dotenv to v17
([#1474](#1474))
([d613bfa](d613bfa))
* **deps:** update dependency lucide-vue-next to ^0.509.0
([#1383](#1383))
([469333a](469333a))
* **deps:** update dependency marked to v16
([#1444](#1444))
([453a5b2](453a5b2))
* **deps:** update dependency shadcn-vue to v2
([#1302](#1302))
([26ecf77](26ecf77))
* **deps:** update dependency vue-sonner to v2
([#1401](#1401))
([53ca414](53ca414))
* disable file changes on Unraid 7.2
([#1382](#1382))
([02de89d](02de89d))
* do not start API with doinst.sh
([7d88b33](7d88b33))
* do not uninstall fully on 7.2
([#1484](#1484))
([2263881](2263881))
* drop console with terser
([a87d455](a87d455))
* error logs from `cloud` query when connect is not installed
([#1450](#1450))
([719f460](719f460))
* flash backup integration with Unraid Connect config
([#1448](#1448))
([038c582](038c582))
* header padding regression
([#1477](#1477))
([e791cc6](e791cc6))
* incorrect state merging in redux store
([#1437](#1437))
([17b7428](17b7428))
* lanip copy button not present
([#1459](#1459))
([a280786](a280786))
* move to bigint scalar
([b625227](b625227))
* node_modules dir removed on plugin update
([#1406](#1406))
([7b005cb](7b005cb))
* omit Connect actions in UPC when plugin is not installed
([#1417](#1417))
([8c8a527](8c8a527))
* parsing of `ssoEnabled` in state.php
([#1455](#1455))
([f542c8e](f542c8e))
* pin ranges ([#1460](#1460))
([f88400e](f88400e))
* pr plugin promotion workflow
([#1456](#1456))
([13bd9bb](13bd9bb))
* proper fallback if missing paths config modules
([7067e9e](7067e9e))
* rc.unraid-api now cleans up older dependencies
([#1404](#1404))
([83076bb](83076bb))
* remote access lifecycle during boot & shutdown
([#1422](#1422))
([7bc583b](7bc583b))
* sign out correctly on error
([#1452](#1452))
([d08fc94](d08fc94))
* simplify usb listing
([#1402](#1402))
([5355115](5355115))
* theme issues when sent from graph
([#1424](#1424))
([75ad838](75ad838))
* **ui:** notifications positioning regression
([#1445](#1445))
([f73e5e0](f73e5e0))
* use some instead of every for connect detection
([9ce2fee](9ce2fee))


### Reverts

* revert package.json dependency updates from commit 711cc9a for api and
packages/*
([94420e4](94420e4))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@coderabbitai coderabbitai bot mentioned this pull request Jul 17, 2025
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.

3 participants