From 4649754873e3deaf4d4e9216eda0bce38d622ffd Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Mon, 4 Aug 2025 20:56:55 +0200
Subject: [PATCH 1/7] script uuid
---
.../Data/Playground/Playground.react.js | 40 ++++++++-----------
src/lib/ScriptManager.js | 26 ++++++------
2 files changed, 29 insertions(+), 37 deletions(-)
diff --git a/src/dashboard/Data/Playground/Playground.react.js b/src/dashboard/Data/Playground/Playground.react.js
index 8ba356101..69bbc54b3 100644
--- a/src/dashboard/Data/Playground/Playground.react.js
+++ b/src/dashboard/Data/Playground/Playground.react.js
@@ -176,11 +176,11 @@ export default function Playground() {
const containerRef = useRef(null);
// Tab management state
+ const initialTabId = useMemo(() => crypto.randomUUID(), []);
const [tabs, setTabs] = useState([
- { id: 1, name: 'Tab 1', code: DEFAULT_CODE_EDITOR_VALUE }
+ { id: initialTabId, name: 'Tab 1', code: DEFAULT_CODE_EDITOR_VALUE }
]);
- const [activeTabId, setActiveTabId] = useState(1);
- const [nextTabId, setNextTabId] = useState(2);
+ const [activeTabId, setActiveTabId] = useState(initialTabId);
const [renamingTabId, setRenamingTabId] = useState(null);
const [renamingValue, setRenamingValue] = useState('');
const [savedTabs, setSavedTabs] = useState([]); // All saved tabs including closed ones
@@ -235,8 +235,6 @@ export default function Playground() {
if (tabsToOpen.length > 0) {
setTabs(tabsToOpen);
- const maxId = Math.max(...allScripts.map(tab => tab.id));
- setNextTabId(maxId + 1);
// Set active tab to the first one
setActiveTabId(tabsToOpen[0].id);
@@ -249,8 +247,6 @@ export default function Playground() {
const firstScript = { ...allScripts[0], order: 0 };
setTabs([firstScript]);
setActiveTabId(firstScript.id);
- const maxId = Math.max(...allScripts.map(tab => tab.id));
- setNextTabId(maxId + 1);
// Save it as open
await scriptManagerRef.current.openScript(context.applicationId, firstScript.id, 0);
@@ -258,17 +254,17 @@ export default function Playground() {
setSavedTabs(allScripts.filter(script => script.saved !== false));
} else {
// Fallback to default tab if no scripts exist
- setTabs([{ id: 1, name: 'Tab 1', code: DEFAULT_CODE_EDITOR_VALUE, order: 0 }]);
- setActiveTabId(1);
- setNextTabId(2);
+ const defaultTabId = crypto.randomUUID();
+ setTabs([{ id: defaultTabId, name: 'Tab 1', code: DEFAULT_CODE_EDITOR_VALUE, order: 0 }]);
+ setActiveTabId(defaultTabId);
}
}
} catch (error) {
console.warn('Failed to load scripts via ScriptManager:', error);
// Fallback to default tab if loading fails
- setTabs([{ id: 1, name: 'Tab 1', code: DEFAULT_CODE_EDITOR_VALUE, order: 0 }]);
- setActiveTabId(1);
- setNextTabId(2);
+ const defaultTabId = crypto.randomUUID();
+ setTabs([{ id: defaultTabId, name: 'Tab 1', code: DEFAULT_CODE_EDITOR_VALUE, order: 0 }]);
+ setActiveTabId(defaultTabId);
}
// Load other data from localStorage
@@ -317,18 +313,19 @@ export default function Playground() {
// Tab management functions
const createNewTab = useCallback(() => {
+ const newTabId = crypto.randomUUID();
+ const tabCount = tabs.length + 1;
const newTab = {
- id: nextTabId,
- name: `Tab ${nextTabId}`,
+ id: newTabId,
+ name: `Tab ${tabCount}`,
code: '', // Start with empty code instead of default value
saved: false, // Mark as unsaved initially
order: tabs.length // Assign order as the last position
};
const updatedTabs = [...tabs, newTab];
setTabs(updatedTabs);
- setActiveTabId(nextTabId);
- setNextTabId(nextTabId + 1);
- }, [tabs, nextTabId]);
+ setActiveTabId(newTabId);
+ }, [tabs]);
const closeTab = useCallback(async (tabId) => {
if (tabs.length <= 1) {
@@ -591,11 +588,6 @@ export default function Playground() {
setTabs(updatedTabs);
setActiveTabId(savedTab.id);
- // Update nextTabId if necessary
- if (savedTab.id >= nextTabId) {
- setNextTabId(savedTab.id + 1);
- }
-
// Save the open state through ScriptManager
if (scriptManagerRef.current && context?.applicationId) {
try {
@@ -604,7 +596,7 @@ export default function Playground() {
console.error('Failed to open script:', error);
}
}
- }, [tabs, nextTabId, switchTab, context?.applicationId]);
+ }, [tabs, switchTab, context?.applicationId]);
// Focus input when starting to rename
useEffect(() => {
diff --git a/src/lib/ScriptManager.js b/src/lib/ScriptManager.js
index 4bbb4bcb6..0e7872f60 100644
--- a/src/lib/ScriptManager.js
+++ b/src/lib/ScriptManager.js
@@ -233,6 +233,14 @@ export default class ScriptManager {
return this.serverStorage.isServerConfigEnabled();
}
+ /**
+ * Generates a unique ID for a new script/tab
+ * @returns {string} A UUID string
+ */
+ generateScriptId() {
+ return this._generateScriptId();
+ }
+
/**
* Gets scripts from server storage
* @private
@@ -248,7 +256,7 @@ export default class ScriptManager {
const scriptId = key.replace('console.js.script.', '');
scripts.push({
- id: parseInt(scriptId, 10),
+ id: scriptId, // Keep as string (UUID) instead of parsing as integer
...config
});
}
@@ -338,7 +346,7 @@ export default class ScriptManager {
if (legacyCode && legacyCode.trim()) {
// Create a script with the legacy code, marked as unsaved
const script = {
- id: this._generateScriptId({ name: 'Legacy Script', code: legacyCode }),
+ id: this._generateScriptId(),
name: 'Legacy Script',
code: legacyCode,
saved: false, // Mark as unsaved so user can choose to save it
@@ -377,19 +385,11 @@ export default class ScriptManager {
}
/**
- * Generates a unique ID for a script
+ * Generates a unique ID for a script using UUID
* @private
*/
- _generateScriptId(script) {
- // Use a hash of the script name and code as a fallback ID
- const str = `${script.name || 'script'}-${script.code || ''}`;
- let hash = 0;
- for (let i = 0; i < str.length; i++) {
- const char = str.charCodeAt(i);
- hash = ((hash << 5) - hash) + char;
- hash = hash & hash; // Convert to 32bit integer
- }
- return Math.abs(hash);
+ _generateScriptId() {
+ return crypto.randomUUID();
}
}
From c2643d3b2d880ce4ad7d3c2d1c12fe55d98b4318 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Mon, 4 Aug 2025 21:29:47 +0200
Subject: [PATCH 2/7] delete local js scripts
---
.../DashboardSettings.react.js | 33 +++++++++++++------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js b/src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js
index 4e2cd7b0f..c7d8f11aa 100644
--- a/src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js
+++ b/src/dashboard/Settings/DashboardSettings/DashboardSettings.react.js
@@ -18,6 +18,7 @@ import Notification from 'dashboard/Data/Browser/Notification.react';
import * as ColumnPreferences from 'lib/ColumnPreferences';
import * as ClassPreferences from 'lib/ClassPreferences';
import ViewPreferencesManager from 'lib/ViewPreferencesManager';
+import ScriptManager from 'lib/ScriptManager';
import bcrypt from 'bcryptjs';
import * as OTPAuth from 'otpauth';
import QRCode from 'qrcode';
@@ -28,6 +29,7 @@ export default class DashboardSettings extends DashboardView {
this.section = 'App Settings';
this.subsection = 'Dashboard Configuration';
this.viewPreferencesManager = null;
+ this.scriptManager = null;
this.state = {
createUserInput: false,
@@ -57,12 +59,13 @@ export default class DashboardSettings extends DashboardView {
}
componentDidMount() {
- this.initializeViewPreferencesManager();
+ this.initializeManagers();
}
- initializeViewPreferencesManager() {
+ initializeManagers() {
if (this.context) {
this.viewPreferencesManager = new ViewPreferencesManager(this.context);
+ this.scriptManager = new ScriptManager(this.context);
this.loadStoragePreference();
}
}
@@ -123,11 +126,18 @@ export default class DashboardSettings extends DashboardView {
return;
}
- const success = this.viewPreferencesManager.deleteFromBrowser(this.context.applicationId);
- if (success) {
- this.showNote('Successfully deleted views from browser storage.');
+ if (!this.scriptManager) {
+ this.showNote('ScriptManager not initialized');
+ return;
+ }
+
+ const viewsSuccess = this.viewPreferencesManager.deleteFromBrowser(this.context.applicationId);
+ const scriptsSuccess = this.scriptManager.deleteFromBrowser(this.context.applicationId);
+
+ if (viewsSuccess && scriptsSuccess) {
+ this.showNote('Successfully deleted dashboard settings from browser storage.');
} else {
- this.showNote('Failed to delete views from browser storage.');
+ this.showNote('Failed to delete all dashboard settings from browser storage.');
}
}
@@ -461,13 +471,16 @@ export default class DashboardSettings extends DashboardView {
}
/>
- {this.viewPreferencesManager && this.viewPreferencesManager.isServerConfigEnabled() && (
+ {this.viewPreferencesManager && this.scriptManager && this.viewPreferencesManager.isServerConfigEnabled() && (