Skip to content

Conversation

mtrezza
Copy link
Member

@mtrezza mtrezza commented Aug 4, 2025

Summary by CodeRabbit

  • New Features

    • Added navigation confirmation prompts to prevent losing unsaved changes in playground tabs.
    • Dashboard settings now manage both view preferences and JS Console scripts, with updated UI explanations.
  • Bug Fixes

    • Improved legacy script import to prevent duplicate entries and ensure correct tab ordering.
  • Refactor

    • Switched tab and script ID generation to use UUIDs for better consistency and reliability.
    • Streamlined internal logic for tab and script management.

Copy link

parse-github-assistant bot commented Aug 4, 2025

🚀 Thanks for opening this pull request!

Copy link

coderabbitai bot commented Aug 4, 2025

📝 Walkthrough

Walkthrough

The changes refactor tab and script ID management to use UUIDs instead of numeric IDs, enhance legacy script import logic to prevent duplicates and ensure correct ordering, and extend dashboard settings to manage both view preferences and scripts. Navigation guards are added to the playground to warn users about unsaved changes before navigating away.

Changes

Cohort / File(s) Change Summary
Playground Tab ID Refactor & Navigation Guard
src/dashboard/Data/Playground/Playground.react.js
Replaces numeric tab IDs with UUIDs using crypto.randomUUID(), removes all nextTabId logic, updates tab creation and loading to use UUIDs, and implements navigation confirmation dialogs (both on browser unload and internal navigation) to prevent loss of unsaved changes.
Dashboard Settings: Script Management Integration
src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js
Adds a ScriptManager alongside ViewPreferencesManager, updates initialization and deletion logic to handle both, adds UI explanations for script storage, and slightly rewords descriptions. Method and property names are updated to reflect the new dual-manager logic.
ScriptManager: Legacy Import & UUIDs
src/lib/ScriptManager.js
Enhances legacy script import by preventing duplicates, ensures legacy scripts open as the first tab, marks them as saved, increments order of existing scripts, and auto-saves. Script IDs are now UUIDs via crypto.randomUUID(). Adds a public generateScriptId() method and updates internal ID generation logic.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Playground
    participant ScriptManager
    participant Browser

    User->>Playground: Attempt to close tab or navigate away
    Playground->>Playground: Check for unsaved changes
    alt Unsaved changes exist
        Playground->>User: Show confirmation dialog
        alt User confirms
            Playground->>Browser: Proceed with navigation/unload
        else User cancels
            Playground->>Browser: Prevent navigation/unload
        end
    else No unsaved changes
        Playground->>Browser: Proceed with navigation/unload
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
  • 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.

Support

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

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 generate unit tests to generate unit tests for 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.

@parseplatformorg
Copy link
Contributor

🎉 Snyk checks have passed. No issues have been found so far.

security/snyk check is complete. No issues have been found. (View Details)

@mtrezza mtrezza changed the title fix: Legacy script in JavaScript console not imported into new tab fix: Legacy script in JavaScript console not imported on migration to modern console Aug 4, 2025
@mtrezza mtrezza changed the title fix: Legacy script in JavaScript console not imported on migration to modern console fix: Legacy script in JavaScript console not imported to modern console Aug 4, 2025
Copy link

@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

🧹 Nitpick comments (2)
src/dashboard/Data/Playground/Playground.react.js (2)

656-744: Consider refactoring to reduce code duplication.

The unsaved changes detection logic is duplicated between useBeforeUnload and the checkForUnsavedChanges function. While the implementation works correctly, consider extracting this logic into a shared function.

Extract the common logic:

+  const hasUnsavedChanges = useCallback(() => {
+    for (const tab of tabs) {
+      if (tab.saved === false) {
+        return true;
+      }
+
+      let currentContent = '';
+      if (tab.id === activeTabId && editorRef.current) {
+        currentContent = editorRef.current.value;
+      } else {
+        currentContent = tab.code;
+      }
+
+      const savedTab = savedTabs.find(saved => saved.id === tab.id);
+
+      if (!savedTab) {
+        if (currentContent.trim() !== '') {
+          return true;
+        }
+      } else {
+        if (currentContent !== savedTab.code) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }, [tabs, activeTabId, savedTabs]);

   useBeforeUnload(
     useCallback(
       (event) => {
-        // Check for unsaved changes across all tabs
-        let hasChanges = false;
-        // ... duplicate code ...
-        if (hasChanges) {
+        if (hasUnsavedChanges()) {
           const message = 'You have unsaved changes in your playground tabs. Are you sure you want to leave?';
           event.preventDefault();
           event.returnValue = message;
           return message;
         }
       },
-      [tabs, activeTabId, savedTabs]
+      [hasUnsavedChanges]
     )
   );

180-180: Consider using ScriptManager's generateScriptId() for consistency.

While directly using crypto.randomUUID() works correctly, the codebase would be more maintainable if all script/tab ID generation went through ScriptManager.generateScriptId(). This would centralize UUID generation logic and make future changes easier.

Consider using the centralized method:

-    const newTabId = crypto.randomUUID();
+    const newTabId = scriptManagerRef.current?.generateScriptId() || crypto.randomUUID();

Also applies to: 258-258, 267-267, 317-317

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a552d1f and 0355f0e.

📒 Files selected for processing (3)
  • src/dashboard/Data/Playground/Playground.react.js (5 hunks)
  • src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js (7 hunks)
  • src/lib/ScriptManager.js (5 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: mtrezza
PR: parse-community/parse-dashboard#2828
File: src/dashboard/Data/Browser/Browser.react.js:1605-1607
Timestamp: 2025-05-27T12:09:47.644Z
Learning: In script execution dialogs in Parse Dashboard (specifically the `confirmExecuteScriptRows` method in `src/dashboard/Data/Browser/Browser.react.js`), individual `setState` calls to update `processedScripts` counter should be kept as-is rather than batched, because this provides real-time progress feedback to users in the dialog UI.
📚 Learning: in script execution dialogs in parse dashboard (specifically the `confirmexecutescriptrows` method i...
Learnt from: mtrezza
PR: parse-community/parse-dashboard#2828
File: src/dashboard/Data/Browser/Browser.react.js:1605-1607
Timestamp: 2025-05-27T12:09:47.644Z
Learning: In script execution dialogs in Parse Dashboard (specifically the `confirmExecuteScriptRows` method in `src/dashboard/Data/Browser/Browser.react.js`), individual `setState` calls to update `processedScripts` counter should be kept as-is rather than batched, because this provides real-time progress feedback to users in the dialog UI.

Applied to files:

  • src/dashboard/Data/Playground/Playground.react.js
  • src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js
  • src/lib/ScriptManager.js
📚 Learning: preference reads and writes in the classpreferences.js module are expected to be infrequent operatio...
Learnt from: mtrezza
PR: parse-community/parse-dashboard#2769
File: src/lib/ClassPreferences.js:26-26
Timestamp: 2025-05-02T11:55:52.809Z
Learning: Preference reads and writes in the ClassPreferences.js module are expected to be infrequent operations, so optimizing for performance (like caching) is unnecessary in this context.

Applied to files:

  • src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js
📚 Learning: the bcryptjs library is used in parse dashboard for password encryption and validation in three file...
Learnt from: mtrezza
PR: parse-community/parse-dashboard#0
File: :0-0
Timestamp: 2025-05-11T16:43:27.354Z
Learning: The bcryptjs library is used in Parse Dashboard for password encryption and validation in three files: Parse-Dashboard/Authentication.js (compareSync), Parse-Dashboard/CLI/mfa.js (genSaltSync, hashSync), and src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js (genSaltSync, hashSync).

Applied to files:

  • src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Docker linux/amd64
🔇 Additional comments (14)
src/lib/ScriptManager.js (5)

48-79: LGTM! Well-implemented legacy script import logic.

The implementation correctly:

  • Prevents duplicate legacy scripts from being imported multiple times
  • Ensures the legacy script opens as the first tab (order 0)
  • Marks it as saved to avoid unnecessary unsaved warnings
  • Preserves the order of existing scripts by incrementing them

260-267: LGTM! Clean public API for script ID generation.

Good encapsulation of the UUID generation logic with proper JSDoc documentation.


283-284: LGTM! Correct handling of UUID script IDs from server.

The change correctly preserves the script ID as a string to support UUIDs.


372-376: LGTM! Proper legacy script initialization.

Good decision to mark the imported legacy script as saved, preventing unnecessary unsaved change warnings for this one-time migration.


412-417: Approved: crypto.randomUUID() Implementation

This is the correct, web-standard approach for UUID v4 generation. According to MDN, crypto.randomUUID() is supported in:

  • Chrome 92+ / Edge 92+ / Opera 78+
  • Firefox 95+
  • Safari 15.4+
  • Secure contexts only (HTTPS or localhost)
  • Node.js 16.7.0+ (crypto.randomUUID() in the crypto module) and Web Crypto API in Node.js 18+

No code changes required. If you must support older browsers or non-HTTPS environments, include a polyfill.

src/dashboard/Data/Playground/Playground.react.js (5)

180-184: LGTM! Proper UUID initialization for tabs.

Good use of useMemo to ensure the initial tab ID is generated only once.


317-329: LGTM! Clean refactoring to UUID-based tab IDs.

The removal of nextTabId state simplifies the code while maintaining correct functionality.


258-268: LGTM! Consistent UUID usage in tab initialization.

All code paths correctly generate UUIDs for new tabs, maintaining consistency.


600-600: LGTM! Correct removal of obsolete nextTabId logic.


603-653: LGTM! Comprehensive navigation guard for browser unload events.

The implementation correctly:

  • Checks all tabs for unsaved changes
  • Handles both active (editor content) and inactive (stored code) tabs
  • Uses the standard beforeunload pattern for maximum compatibility
src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js (4)

21-21: LGTM! Clean integration of ScriptManager.

The initialization follows the existing pattern and the method rename appropriately reflects its expanded scope.

Also applies to: 32-32, 62-71


129-141: LGTM! Proper handling of dual storage deletion.

The implementation correctly ensures both view preferences and scripts are deleted, with appropriate success/failure messaging.


474-478: LGTM! Clear and informative UI updates.

The explanatory text effectively communicates the expanded scope of server storage to include JS Console scripts.


483-483: LGTM! Improved clarity in field descriptions.

The updated descriptions are more concise and the warning emojis effectively highlight important information.

Also applies to: 503-503, 519-519

@mtrezza mtrezza merged commit 8c8d084 into parse-community:alpha Aug 4, 2025
11 checks passed
@mtrezza mtrezza deleted the fix/legacy-js-script branch August 4, 2025 19:58
parseplatformorg pushed a commit that referenced this pull request Aug 4, 2025
# [7.4.0-alpha.3](7.4.0-alpha.2...7.4.0-alpha.3) (2025-08-04)

### Bug Fixes

* Legacy script in JavaScript console not imported to modern console ([#2963](#2963)) ([8c8d084](8c8d084))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 7.4.0-alpha.3

@parseplatformorg parseplatformorg added the state:released-alpha Released as alpha version label Aug 4, 2025
parseplatformorg pushed a commit that referenced this pull request Sep 1, 2025
# [7.4.0](7.3.0...7.4.0) (2025-09-01)

### Bug Fixes

* Legacy script in JavaScript console not imported to modern console ([#2963](#2963)) ([8c8d084](8c8d084))

### Features

* Add App Settings option to store dashboard settings on server ([#2958](#2958)) ([666e078](666e078))
* Add config parameter name to quick add dialogs in Config page ([#2970](#2970)) ([31988f6](31988f6))
* Add info panel setting to auto-load first row on opening new browser tab ([#2972](#2972)) ([020a25d](020a25d))
* Modernize JavaScript console with tabs and server-side storage of scripts ([#2962](#2962)) ([6e0c7f2](6e0c7f2))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 7.4.0

@parseplatformorg parseplatformorg added the state:released Released as stable version label Sep 1, 2025
beiguancyc pushed a commit to beiguancyc/parse-dashboard that referenced this pull request Sep 2, 2025
* source:
  chore(release): 7.4.0 [skip ci]
  empty commit to trigger CI
  chore(release): 7.4.0-alpha.5 [skip ci]
  feat: Add info panel setting to auto-load first row on opening new browser tab (parse-community#2972)
  chore(release): 7.4.0-alpha.4 [skip ci]
  feat: Add config parameter name to quick add dialogs in Config page (parse-community#2970)
  refactor: Bump @babel/runtime-corejs3 from 7.27.4 to 7.28.3 (parse-community#2966)
  chore(release): 7.4.0-alpha.3 [skip ci]
  fix: Legacy script in JavaScript console not imported to modern console (parse-community#2963)
  chore(release): 7.4.0-alpha.2 [skip ci]
  feat: Modernize JavaScript console with tabs and server-side storage of scripts (parse-community#2962)
  chore(release): 7.4.0-alpha.1 [skip ci]
  feat: Add App Settings option to store dashboard settings on server (parse-community#2958)
  refactor: Bump inquirer from 12.6.3 to 12.9.0 (parse-community#2959)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state:released Released as stable version state:released-alpha Released as alpha version
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants