dbviewer 0.7.10 → 0.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/app/assets/images/dbviewer/emoji-favicon.txt +1 -0
- data/app/assets/images/dbviewer/favicon.ico +4 -0
- data/app/assets/images/dbviewer/favicon.png +4 -0
- data/app/assets/images/dbviewer/favicon.svg +10 -0
- data/app/assets/javascripts/dbviewer/entity_relationship_diagram.js +38 -42
- data/app/assets/javascripts/dbviewer/error_handler.js +58 -0
- data/app/assets/javascripts/dbviewer/home.js +25 -34
- data/app/assets/javascripts/dbviewer/layout.js +100 -129
- data/app/assets/javascripts/dbviewer/query.js +309 -246
- data/app/assets/javascripts/dbviewer/sidebar.js +170 -183
- data/app/assets/javascripts/dbviewer/utility.js +124 -0
- data/app/assets/stylesheets/dbviewer/application.css +8 -146
- data/app/assets/stylesheets/dbviewer/entity_relationship_diagram.css +0 -34
- data/app/assets/stylesheets/dbviewer/logs.css +0 -11
- data/app/assets/stylesheets/dbviewer/query.css +21 -9
- data/app/assets/stylesheets/dbviewer/table.css +49 -131
- data/app/controllers/concerns/dbviewer/database_operations/connection_management.rb +90 -0
- data/app/controllers/concerns/dbviewer/database_operations/data_export.rb +31 -0
- data/app/controllers/concerns/dbviewer/database_operations/database_information.rb +54 -0
- data/app/controllers/concerns/dbviewer/database_operations/datatable_operations.rb +37 -0
- data/app/controllers/concerns/dbviewer/database_operations/query_operations.rb +37 -0
- data/app/controllers/concerns/dbviewer/database_operations/relationship_management.rb +175 -0
- data/app/controllers/concerns/dbviewer/database_operations/table_operations.rb +46 -0
- data/app/controllers/concerns/dbviewer/database_operations.rb +4 -9
- data/app/controllers/dbviewer/api/tables_controller.rb +12 -0
- data/app/controllers/dbviewer/entity_relationship_diagrams_controller.rb +0 -15
- data/app/controllers/dbviewer/tables_controller.rb +4 -33
- data/app/views/dbviewer/entity_relationship_diagrams/index.html.erb +1 -1
- data/app/views/dbviewer/tables/query.html.erb +21 -6
- data/app/views/dbviewer/tables/show.html.erb +2 -2
- data/app/views/layouts/dbviewer/application.html.erb +12 -3
- data/config/routes.rb +2 -2
- data/lib/dbviewer/database/manager.rb +2 -2
- data/lib/dbviewer/datatable/query_operations.rb +1 -17
- data/lib/dbviewer/engine.rb +29 -0
- data/lib/dbviewer/version.rb +1 -1
- metadata +15 -10
- data/app/controllers/concerns/dbviewer/connection_management.rb +0 -88
- data/app/controllers/concerns/dbviewer/data_export.rb +0 -32
- data/app/controllers/concerns/dbviewer/database_information.rb +0 -62
- data/app/controllers/concerns/dbviewer/datatable_support.rb +0 -47
- data/app/controllers/concerns/dbviewer/pagination_concern.rb +0 -34
- data/app/controllers/concerns/dbviewer/query_operations.rb +0 -28
- data/app/controllers/concerns/dbviewer/relationship_management.rb +0 -173
- data/app/controllers/concerns/dbviewer/table_operations.rb +0 -56
@@ -1,277 +1,340 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
}
|
9
|
-
|
10
|
-
// Get initial query value from a data attribute to avoid string escaping issues
|
11
|
-
const initialQueryEncoded = document
|
12
|
-
.getElementById("monaco-editor")
|
13
|
-
.getAttribute("data-initial-query");
|
14
|
-
const initialQuery = decodeHTMLEntities(initialQueryEncoded);
|
15
|
-
|
16
|
-
// Determine initial theme based on document theme
|
17
|
-
const initialTheme =
|
18
|
-
document.documentElement.getAttribute("data-bs-theme") === "dark"
|
19
|
-
? "vs-dark"
|
20
|
-
: "vs";
|
21
|
-
|
22
|
-
// Initialize Monaco Editor with SQL syntax highlighting
|
23
|
-
const editor = monaco.editor.create(document.getElementById("monaco-editor"), {
|
24
|
-
value: initialQuery || "",
|
25
|
-
language: "sql",
|
26
|
-
theme: initialTheme,
|
27
|
-
automaticLayout: true, // Resize automatically
|
28
|
-
minimap: { enabled: true },
|
29
|
-
scrollBeyondLastLine: false,
|
30
|
-
lineNumbers: "on",
|
31
|
-
renderLineHighlight: "all",
|
32
|
-
tabSize: 2,
|
33
|
-
wordWrap: "on",
|
34
|
-
formatOnPaste: true,
|
35
|
-
formatOnType: true,
|
36
|
-
autoIndent: "full",
|
37
|
-
folding: true,
|
38
|
-
glyphMargin: false,
|
39
|
-
suggestOnTriggerCharacters: true,
|
40
|
-
fixedOverflowWidgets: true,
|
41
|
-
quickSuggestions: {
|
42
|
-
other: true,
|
43
|
-
comments: true,
|
44
|
-
strings: true,
|
45
|
-
},
|
46
|
-
suggest: {
|
47
|
-
showKeywords: true,
|
48
|
-
showSnippets: true,
|
49
|
-
preview: true,
|
50
|
-
showIcons: true,
|
51
|
-
maxVisibleSuggestions: 12,
|
52
|
-
},
|
53
|
-
});
|
1
|
+
document.addEventListener("DOMContentLoaded", function () {
|
2
|
+
// Validate that required utility scripts have loaded
|
3
|
+
if (!window.DBViewer || !DBViewer.Utility || !DBViewer.ErrorHandler) {
|
4
|
+
console.error(
|
5
|
+
"Required DBViewer scripts not loaded. Please check utility.js and error_handler.js."
|
6
|
+
);
|
7
|
+
return;
|
8
|
+
}
|
54
9
|
|
55
|
-
//
|
56
|
-
|
57
|
-
const
|
58
|
-
|
10
|
+
// Destructure the needed functions for easier access
|
11
|
+
const { decodeHTMLEntities, ThemeManager } = DBViewer.Utility;
|
12
|
+
const { displayError } = DBViewer.ErrorHandler;
|
13
|
+
|
14
|
+
// Get initial query value from a data attribute to avoid string escaping issues
|
15
|
+
const initialQueryEncoded = document
|
16
|
+
.getElementById("monaco-editor")
|
17
|
+
?.getAttribute("data-initial-query");
|
18
|
+
const initialQuery = initialQueryEncoded
|
19
|
+
? decodeHTMLEntities(initialQueryEncoded)
|
20
|
+
: "";
|
21
|
+
|
22
|
+
// Use RequireJS to load Monaco
|
23
|
+
require(["vs/editor/editor.main"], function () {
|
24
|
+
const initialTheme =
|
25
|
+
ThemeManager.getCurrentTheme() === "dark" ? "vs-dark" : "vs";
|
26
|
+
|
27
|
+
const editorContainer = document.getElementById("monaco-editor");
|
28
|
+
if (!editorContainer) {
|
29
|
+
throw new Error("Monaco editor container not found");
|
30
|
+
}
|
59
31
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
32
|
+
const editor = monaco.editor.create(editorContainer, {
|
33
|
+
value: initialQuery || "",
|
34
|
+
language: "sql",
|
35
|
+
theme: initialTheme,
|
36
|
+
automaticLayout: true, // Resize automatically
|
37
|
+
minimap: { enabled: true },
|
38
|
+
scrollBeyondLastLine: false,
|
39
|
+
lineNumbers: "on",
|
40
|
+
renderLineHighlight: "all",
|
41
|
+
tabSize: 2,
|
42
|
+
wordWrap: "on",
|
43
|
+
formatOnPaste: true,
|
44
|
+
formatOnType: true,
|
45
|
+
autoIndent: "full",
|
46
|
+
folding: true,
|
47
|
+
glyphMargin: false,
|
48
|
+
suggestOnTriggerCharacters: true,
|
49
|
+
fixedOverflowWidgets: true,
|
50
|
+
quickSuggestions: {
|
51
|
+
other: true,
|
52
|
+
comments: true,
|
53
|
+
strings: true,
|
54
|
+
},
|
55
|
+
suggest: {
|
56
|
+
showKeywords: true,
|
57
|
+
showSnippets: true,
|
58
|
+
preview: true,
|
59
|
+
showIcons: true,
|
60
|
+
maxVisibleSuggestions: 12,
|
61
|
+
},
|
62
|
+
});
|
66
63
|
|
67
|
-
|
68
|
-
|
64
|
+
// Theme change listener
|
65
|
+
document.addEventListener("dbviewerThemeChanged", (event) => {
|
66
|
+
const newTheme = event.detail.theme === "dark" ? "vs-dark" : "vs";
|
67
|
+
monaco.editor.setTheme(newTheme);
|
68
|
+
|
69
|
+
// Update editor container border color
|
70
|
+
const editorContainer = document.querySelector(
|
71
|
+
".monaco-editor-container"
|
72
|
+
);
|
73
|
+
editorContainer.style.borderColor =
|
74
|
+
event.detail.theme === "dark" ? "#495057" : "#ced4da";
|
75
|
+
|
76
|
+
// Update status bar styling based on theme
|
77
|
+
updateStatusBarTheme(event.detail.theme);
|
78
|
+
|
79
|
+
// Update example query buttons
|
80
|
+
const exampleQueries = document.querySelectorAll(".example-query");
|
81
|
+
exampleQueries.forEach((query) => {
|
82
|
+
if (event.detail.theme === "dark") {
|
83
|
+
query.style.borderColor = "#495057";
|
84
|
+
if (!query.classList.contains("btn-primary")) {
|
85
|
+
query.style.color = "#f8f9fa";
|
86
|
+
}
|
87
|
+
} else {
|
88
|
+
query.style.borderColor = "#ced4da";
|
89
|
+
if (!query.classList.contains("btn-primary")) {
|
90
|
+
query.style.color = "";
|
91
|
+
}
|
92
|
+
}
|
93
|
+
});
|
94
|
+
});
|
69
95
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
96
|
+
/**
|
97
|
+
* Update the status bar styling based on current theme
|
98
|
+
* @param {string} theme - 'dark' or 'light'
|
99
|
+
*/
|
100
|
+
function updateStatusBarTheme(theme) {
|
101
|
+
const statusBar = document.querySelector(".monaco-status-bar");
|
102
|
+
if (!statusBar) return;
|
103
|
+
|
104
|
+
if (theme === "dark") {
|
105
|
+
statusBar.style.backgroundColor = "#343a40";
|
106
|
+
statusBar.style.borderColor = "#495057";
|
107
|
+
statusBar.style.color = "#adb5bd";
|
108
|
+
} else {
|
109
|
+
statusBar.style.backgroundColor = "#f8f9fa";
|
110
|
+
statusBar.style.borderColor = "#ced4da";
|
111
|
+
statusBar.style.color = "#6c757d";
|
82
112
|
}
|
83
113
|
}
|
84
|
-
});
|
85
|
-
});
|
86
114
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
monaco.languages.
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
115
|
+
const tableName = document.getElementById("table_name").value;
|
116
|
+
const columns = JSON.parse(document.getElementById("columns_data").value);
|
117
|
+
|
118
|
+
// Register SQL completion providers
|
119
|
+
monaco.languages.registerCompletionItemProvider("sql", {
|
120
|
+
provideCompletionItems: function () {
|
121
|
+
const suggestions = [];
|
122
|
+
|
123
|
+
// Add table name suggestion
|
124
|
+
suggestions.push({
|
125
|
+
label: tableName,
|
126
|
+
kind: monaco.languages.CompletionItemKind.Class,
|
127
|
+
insertText: tableName,
|
128
|
+
detail: "Table name",
|
129
|
+
});
|
130
|
+
|
131
|
+
// Add column name suggestions
|
132
|
+
columns.forEach((col) => {
|
133
|
+
suggestions.push({
|
134
|
+
label: col.name,
|
135
|
+
kind: monaco.languages.CompletionItemKind.Field,
|
136
|
+
insertText: col.name,
|
137
|
+
detail: `Column (${col.type})`,
|
138
|
+
});
|
139
|
+
});
|
140
|
+
|
141
|
+
// Add common SQL keywords
|
142
|
+
const keywords = [
|
143
|
+
{ label: "SELECT", insertText: "SELECT " },
|
144
|
+
{ label: "FROM", insertText: "FROM " },
|
145
|
+
{ label: "WHERE", insertText: "WHERE " },
|
146
|
+
{ label: "ORDER BY", insertText: "ORDER BY " },
|
147
|
+
{ label: "GROUP BY", insertText: "GROUP BY " },
|
148
|
+
{ label: "HAVING", insertText: "HAVING " },
|
149
|
+
{ label: "LIMIT", insertText: "LIMIT " },
|
150
|
+
{ label: "JOIN", insertText: "JOIN " },
|
151
|
+
{ label: "LEFT JOIN", insertText: "LEFT JOIN " },
|
152
|
+
{ label: "INNER JOIN", insertText: "INNER JOIN " },
|
153
|
+
];
|
154
|
+
|
155
|
+
keywords.forEach((kw) => {
|
156
|
+
suggestions.push({
|
157
|
+
label: kw.label,
|
158
|
+
kind: monaco.languages.CompletionItemKind.Keyword,
|
159
|
+
insertText: kw.insertText,
|
160
|
+
});
|
161
|
+
});
|
162
|
+
|
163
|
+
return { suggestions };
|
164
|
+
},
|
114
165
|
});
|
115
166
|
|
116
|
-
|
167
|
+
// Handle form submission - transfer content to hidden input before submitting
|
168
|
+
const sqlForm = document.getElementById("sql-query-form");
|
169
|
+
sqlForm.addEventListener("submit", function (event) {
|
170
|
+
event.preventDefault();
|
171
|
+
const queryInput = document.getElementById("query-input");
|
117
172
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
detail: "Table name",
|
124
|
-
});
|
173
|
+
queryInput.value = editor.getValue();
|
174
|
+
const statusInfo = document.querySelector(
|
175
|
+
".monaco-status-bar .status-info"
|
176
|
+
);
|
177
|
+
if (statusInfo) statusInfo.textContent = "Executing query...";
|
125
178
|
|
126
|
-
|
127
|
-
columns.forEach((col) => {
|
128
|
-
suggestions.push({
|
129
|
-
label: col.name,
|
130
|
-
kind: monaco.languages.CompletionItemKind.Field,
|
131
|
-
insertText: col.name,
|
132
|
-
detail: `Column (${col.type})`,
|
133
|
-
});
|
179
|
+
this.submit();
|
134
180
|
});
|
135
181
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
182
|
+
const exampleQueries = document.querySelectorAll(".example-query");
|
183
|
+
exampleQueries.forEach((example) => {
|
184
|
+
example.style.cursor = "pointer";
|
185
|
+
example.addEventListener("click", () => {
|
186
|
+
const query = decodeHTMLEntities(example.textContent);
|
187
|
+
editor.setValue(query);
|
188
|
+
editor.focus();
|
189
|
+
|
190
|
+
const statusInfo = document.querySelector(
|
191
|
+
".monaco-status-bar .status-info"
|
192
|
+
);
|
193
|
+
statusInfo.textContent = "Example query loaded";
|
194
|
+
|
195
|
+
setTimeout(() => {
|
196
|
+
const position = editor.getPosition();
|
197
|
+
if (position) {
|
198
|
+
statusInfo.textContent = `Ln ${position.lineNumber}, Col ${position.column}`;
|
199
|
+
} else {
|
200
|
+
statusInfo.textContent = "Ready";
|
201
|
+
}
|
202
|
+
}, 2000);
|
155
203
|
});
|
156
204
|
});
|
157
205
|
|
158
|
-
|
159
|
-
|
160
|
-
|
206
|
+
// Setup editor keybindings if editor was initialized successfully
|
207
|
+
editor.addCommand(
|
208
|
+
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter,
|
209
|
+
function () {
|
210
|
+
const queryValue = editor.getValue();
|
211
|
+
const queryInput = document.getElementById("query-input");
|
212
|
+
const sqlForm = document.getElementById("sql-query-form");
|
161
213
|
|
162
|
-
|
163
|
-
document
|
164
|
-
.getElementById("sql-query-form")
|
165
|
-
.addEventListener("submit", function (event) {
|
166
|
-
// Stop the form from submitting immediately
|
167
|
-
event.preventDefault();
|
214
|
+
queryInput.value = queryValue;
|
168
215
|
|
169
|
-
|
170
|
-
|
171
|
-
|
216
|
+
// Update status to indicate submission
|
217
|
+
const statusInfo = document.querySelector(
|
218
|
+
".monaco-status-bar .status-info"
|
219
|
+
);
|
220
|
+
if (statusInfo) statusInfo.textContent = "Executing query...";
|
172
221
|
|
173
|
-
|
174
|
-
|
175
|
-
|
222
|
+
sqlForm.submit();
|
223
|
+
}
|
224
|
+
);
|
225
|
+
|
226
|
+
// Add SELECT * action
|
227
|
+
editor.addAction({
|
228
|
+
id: "insert-select-all",
|
229
|
+
label: "Insert SELECT * FROM statement",
|
230
|
+
keybindings: [
|
231
|
+
monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KeyS,
|
232
|
+
],
|
233
|
+
run: function () {
|
234
|
+
try {
|
235
|
+
editor.trigger("keyboard", "type", {
|
236
|
+
text: `SELECT * FROM ${tableName} LIMIT 100`,
|
237
|
+
});
|
238
|
+
} catch (error) {
|
239
|
+
console.error("Error inserting SELECT statement:", error);
|
240
|
+
}
|
241
|
+
return null;
|
242
|
+
},
|
243
|
+
});
|
176
244
|
|
177
|
-
//
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
});
|
245
|
+
// Add WHERE clause action
|
246
|
+
editor.addAction({
|
247
|
+
id: "insert-where",
|
248
|
+
label: "Insert WHERE clause",
|
249
|
+
keybindings: [
|
250
|
+
monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KeyW,
|
251
|
+
],
|
252
|
+
run: function () {
|
253
|
+
editor.trigger("keyboard", "type", { text: " WHERE " });
|
254
|
+
return null;
|
255
|
+
},
|
256
|
+
});
|
186
257
|
|
187
|
-
//
|
188
|
-
editor.
|
189
|
-
|
190
|
-
|
191
|
-
|
258
|
+
// Add toggle table structure action
|
259
|
+
editor.addAction({
|
260
|
+
id: "toggle-table-structure",
|
261
|
+
label: "Toggle Table Structure Reference",
|
262
|
+
keybindings: [
|
263
|
+
monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KeyT,
|
264
|
+
],
|
265
|
+
run: function () {
|
266
|
+
const tableStructureContent = document.getElementById(
|
267
|
+
"tableStructureContent"
|
268
|
+
);
|
269
|
+
if (!tableStructureContent) {
|
270
|
+
throw new Error("Table structure content element not found");
|
271
|
+
}
|
272
|
+
|
273
|
+
bootstrap.Collapse.getOrCreateInstance(tableStructureContent).toggle();
|
274
|
+
return null;
|
275
|
+
},
|
276
|
+
});
|
192
277
|
|
193
|
-
|
194
|
-
|
195
|
-
|
278
|
+
const statusBarDiv = document.createElement("div");
|
279
|
+
statusBarDiv.className = "monaco-status-bar";
|
280
|
+
statusBarDiv.innerHTML = `<div class="status-info">Ready</div>
|
281
|
+
<div class="column-info">Table: ${tableName} (${columns.length} columns)</div>`;
|
282
|
+
editorContainer.after(statusBarDiv);
|
196
283
|
|
197
|
-
//
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
editor.trigger("keyboard", "type", {
|
206
|
-
text: `SELECT * FROM ${tableName} LIMIT 100`,
|
284
|
+
// Apply initial theme to status bar
|
285
|
+
updateStatusBarTheme(ThemeManager.getCurrentTheme());
|
286
|
+
|
287
|
+
// Update status bar with cursor position
|
288
|
+
editor.onDidChangeCursorPosition((e) => {
|
289
|
+
const position = `Ln ${e.position.lineNumber}, Col ${e.position.column}`;
|
290
|
+
const statusInfo = statusBarDiv.querySelector(".status-info");
|
291
|
+
if (statusInfo) statusInfo.textContent = position;
|
207
292
|
});
|
208
|
-
return null;
|
209
|
-
},
|
210
|
-
});
|
211
293
|
|
212
|
-
editor
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KeyW,
|
217
|
-
],
|
218
|
-
run: function () {
|
219
|
-
editor.trigger("keyboard", "type", { text: " WHERE " });
|
220
|
-
return null;
|
221
|
-
},
|
222
|
-
});
|
294
|
+
// Focus the editor when page loads
|
295
|
+
window.addEventListener("load", () => {
|
296
|
+
editor.focus();
|
297
|
+
});
|
223
298
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KeyT,
|
229
|
-
],
|
230
|
-
run: function () {
|
231
|
-
// Use Bootstrap's collapse API to toggle
|
232
|
-
bootstrap.Collapse.getOrCreateInstance(
|
233
|
-
document.getElementById("tableStructureContent")
|
234
|
-
).toggle();
|
235
|
-
return null;
|
236
|
-
},
|
237
|
-
});
|
299
|
+
// Toggle icon when table structure collapses or expands
|
300
|
+
const tableStructureContent = document.getElementById(
|
301
|
+
"tableStructureContent"
|
302
|
+
);
|
238
303
|
|
239
|
-
|
240
|
-
const
|
241
|
-
|
242
|
-
|
243
|
-
<div class="column-info">Table: ${tableName} (${columns.length} columns)</div>`;
|
244
|
-
document.getElementById("monaco-editor").after(statusBarDiv);
|
245
|
-
|
246
|
-
// Apply initial theme to status bar
|
247
|
-
const currentTheme =
|
248
|
-
document.documentElement.getAttribute("data-bs-theme") || "light";
|
249
|
-
updateStatusBarTheme(currentTheme);
|
250
|
-
|
251
|
-
// Update status bar with cursor position
|
252
|
-
editor.onDidChangeCursorPosition((e) => {
|
253
|
-
const position = `Ln ${e.position.lineNumber}, Col ${e.position.column}`;
|
254
|
-
statusBarDiv.querySelector(".status-info").textContent = position;
|
255
|
-
});
|
304
|
+
tableStructureContent.addEventListener("show.bs.collapse", function () {
|
305
|
+
const icon = document.querySelector("#tableStructureHeader button i");
|
306
|
+
icon.classList.replace("bi-chevron-down", "bi-chevron-up");
|
307
|
+
});
|
256
308
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
});
|
309
|
+
tableStructureContent.addEventListener("hide.bs.collapse", function () {
|
310
|
+
const icon = document.querySelector("#tableStructureHeader button i");
|
311
|
+
icon.classList.replace("bi-chevron-up", "bi-chevron-down");
|
312
|
+
});
|
261
313
|
|
262
|
-
//
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
314
|
+
// Add error recovery mechanism
|
315
|
+
window.addEventListener("error", function (e) {
|
316
|
+
// Only handle Monaco editor related errors
|
317
|
+
if (e.message.includes("monaco") || e.message.includes("editor")) {
|
318
|
+
displayError(
|
319
|
+
"query-container",
|
320
|
+
"Editor Error",
|
321
|
+
"An error occurred in the SQL editor",
|
322
|
+
"Please refresh the page to restore full functionality"
|
323
|
+
);
|
324
|
+
}
|
325
|
+
});
|
270
326
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
327
|
+
// Global error handler for Monaco editor errors
|
328
|
+
window.addEventListener("error", function (e) {
|
329
|
+
// Only handle Monaco editor related errors
|
330
|
+
if (e.message.includes("monaco") || e.message.includes("editor")) {
|
331
|
+
displayError(
|
332
|
+
"query-container",
|
333
|
+
"Editor Error",
|
334
|
+
"An error occurred in the SQL editor",
|
335
|
+
"Please refresh the page to restore full functionality"
|
336
|
+
);
|
337
|
+
}
|
338
|
+
});
|
277
339
|
});
|
340
|
+
});
|