sqlui 0.1.25 → 0.1.26
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/app/views/databases.erb +5 -22
- data/client/resources/sqlui.css +21 -5
- data/client/resources/sqlui.html +2 -0
- data/client/resources/sqlui.js +112 -62
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20b037b445c287b8e9586a2f5820d4be597bb977db8a9412721790a5239a2f87
|
4
|
+
data.tar.gz: '08e5d525245186d568bd2deb86f4a5d25adc9a57d3729651ff74d6fe90e22451'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 631086186d72bfe55f633e88a1017e911d53c4185b9139da4ebf0d462ec9fb48fbf639154fc014453285835c504b1ce8a18f20e9de9c78239a95566b2cde3177
|
7
|
+
data.tar.gz: 24cd3591e88d28785765b6add934a19458c19920cdd77c02f31f7356ca6cefdf4971e45df560c1e451a50ee4192c1ca4d9f8cae227cfe7daa87463b82f7ada6f
|
data/.version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.26
|
data/app/views/databases.erb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<html lang="en">
|
2
2
|
<head>
|
3
|
-
<title
|
3
|
+
<title><%= config.name %> Databases</title>
|
4
4
|
|
5
5
|
<style>
|
6
6
|
body {
|
@@ -71,30 +71,13 @@
|
|
71
71
|
.database {
|
72
72
|
margin: 0;
|
73
73
|
padding: 10px;
|
74
|
-
cursor: pointer;
|
75
74
|
border-bottom: 1px solid #eeeeee;
|
76
75
|
}
|
77
76
|
|
78
77
|
.database:last-child {
|
79
78
|
border-bottom: none;
|
80
79
|
}
|
81
|
-
|
82
|
-
.database:hover {
|
83
|
-
background: #eee;
|
84
|
-
}
|
85
80
|
</style>
|
86
|
-
|
87
|
-
<script>
|
88
|
-
function openDatabase(event, url) {
|
89
|
-
if (event.shiftKey) {
|
90
|
-
window.open(url, '_blank').focus()
|
91
|
-
} else if (event.metaKey) {
|
92
|
-
window.open(url).focus()
|
93
|
-
} else {
|
94
|
-
window.location = url
|
95
|
-
}
|
96
|
-
}
|
97
|
-
</script>
|
98
81
|
</head>
|
99
82
|
|
100
83
|
<body>
|
@@ -103,12 +86,12 @@
|
|
103
86
|
<h1 class="server-name"><%= config.name %> Databases</h1>
|
104
87
|
</div>
|
105
88
|
<% config.database_configs.each do |database_config| %>
|
106
|
-
<div class="database"
|
89
|
+
<div class="database">
|
107
90
|
<div class="name-and-links">
|
108
91
|
<h2 class='name'><%= database_config.display_name %></h2>
|
109
|
-
<a class='query-link' href="<%= database_config.url_path %>/query"
|
110
|
-
<a class='saved-link' href="<%= database_config.url_path %>/saved"
|
111
|
-
<a class='structure-link' href="<%= database_config.url_path %>/structure"
|
92
|
+
<a class='query-link' href="<%= database_config.url_path %>/query">query</a>
|
93
|
+
<a class='saved-link' href="<%= database_config.url_path %>/saved">saved</a>
|
94
|
+
<a class='structure-link' href="<%= database_config.url_path %>/structure">structure</a>
|
112
95
|
</div>
|
113
96
|
<p class='description'>
|
114
97
|
<%= database_config.description %>
|
data/client/resources/sqlui.css
CHANGED
@@ -113,7 +113,11 @@ p {
|
|
113
113
|
display: flex;
|
114
114
|
border-top: 1px solid #ddd;
|
115
115
|
border-bottom: 1px solid #ddd;
|
116
|
-
|
116
|
+
}
|
117
|
+
|
118
|
+
.submit-fill {
|
119
|
+
display: flex;
|
120
|
+
flex: 1
|
117
121
|
}
|
118
122
|
|
119
123
|
.submit-button {
|
@@ -243,18 +247,30 @@ thead {
|
|
243
247
|
}
|
244
248
|
|
245
249
|
.saved-list-item {
|
246
|
-
cursor: pointer;
|
247
250
|
border-bottom: 1px solid #eeeeee;
|
248
251
|
margin: 0;
|
249
252
|
padding: 10px;
|
250
253
|
}
|
251
254
|
|
252
255
|
.saved-list-item h2 {
|
253
|
-
margin: 0 0
|
256
|
+
margin: 0 10px 0 0;
|
254
257
|
}
|
255
258
|
|
256
|
-
.saved-
|
257
|
-
|
259
|
+
.saved-list-item p {
|
260
|
+
margin: 10px 0 0;
|
261
|
+
}
|
262
|
+
|
263
|
+
.name-and-links {
|
264
|
+
display: flex;
|
265
|
+
flex-direction: row;
|
266
|
+
align-items: center;
|
267
|
+
}
|
268
|
+
|
269
|
+
.name-and-links a {
|
270
|
+
margin-right: 5px;
|
271
|
+
color: darkblue;
|
272
|
+
font-size: 16px;
|
273
|
+
text-decoration: none;
|
258
274
|
}
|
259
275
|
|
260
276
|
.cm-editor.cm-focused {
|
data/client/resources/sqlui.html
CHANGED
@@ -26,6 +26,8 @@
|
|
26
26
|
</div>
|
27
27
|
|
28
28
|
<div id="submit-box" class="submit-box tab-content-element graph-element query-element" style="display: none;">
|
29
|
+
<input id="cancel-button" class="submit-button" type="button" value="cancel"></input>
|
30
|
+
<div class="submit-fill"></div>
|
29
31
|
<input id="submit-current-button" class="submit-button" type="button" value="run selection (ctrl-enter)"></input>
|
30
32
|
<input id="submit-all-button" class="submit-button" type="button" value="run (ctrl-shift-enter)"></input>
|
31
33
|
</div>
|
data/client/resources/sqlui.js
CHANGED
@@ -23869,6 +23869,9 @@
|
|
23869
23869
|
document.getElementById('submit-current-button').addEventListener('click', function (event) {
|
23870
23870
|
submitCurrent(event.target, event);
|
23871
23871
|
});
|
23872
|
+
document.getElementById('cancel-button').addEventListener('click', function (event) {
|
23873
|
+
clearResult();
|
23874
|
+
});
|
23872
23875
|
|
23873
23876
|
const fixedHeightEditor = EditorView.theme({
|
23874
23877
|
'.cm-scroller': { height: '200px', overflow: 'auto', resize: 'vertical' }
|
@@ -24160,6 +24163,8 @@
|
|
24160
24163
|
document.getElementById('submit-box').style.display = 'flex';
|
24161
24164
|
document.getElementById('graph-box').style.display = 'flex';
|
24162
24165
|
document.getElementById('graph-status').style.display = 'flex';
|
24166
|
+
document.getElementById('fetch-sql-box').style.display = 'none';
|
24167
|
+
document.getElementById('cancel-button').style.display = 'none';
|
24163
24168
|
maybeFetchResult();
|
24164
24169
|
|
24165
24170
|
const selection = getSelection();
|
@@ -24172,6 +24177,8 @@
|
|
24172
24177
|
document.getElementById('submit-box').style.display = 'flex';
|
24173
24178
|
document.getElementById('result-box').style.display = 'flex';
|
24174
24179
|
document.getElementById('result-status').style.display = 'flex';
|
24180
|
+
document.getElementById('fetch-sql-box').style.display = 'none';
|
24181
|
+
document.getElementById('cancel-button').style.display = 'none';
|
24175
24182
|
const selection = getSelection();
|
24176
24183
|
focus();
|
24177
24184
|
setSelection(selection);
|
@@ -24199,21 +24206,48 @@
|
|
24199
24206
|
setSavedStatus(`${saved.length} files`);
|
24200
24207
|
}
|
24201
24208
|
Object.values(saved).forEach(file => {
|
24202
|
-
const
|
24203
|
-
|
24204
|
-
|
24209
|
+
const viewUrl = new URL(window.location.origin + window.location.pathname);
|
24210
|
+
setTabInUrl(viewUrl, 'query');
|
24211
|
+
viewUrl.searchParams.set('file', file.filename);
|
24212
|
+
|
24213
|
+
const viewLinkElement = document.createElement('a');
|
24214
|
+
viewLinkElement.classList.add('view-link');
|
24215
|
+
viewLinkElement.innerText = 'view';
|
24216
|
+
viewLinkElement.href = viewUrl.pathname + viewUrl.search;
|
24217
|
+
viewLinkElement.addEventListener('click', function (event) {
|
24205
24218
|
clearResult();
|
24206
|
-
|
24207
|
-
setTabInUrl(url, 'query');
|
24208
|
-
url.searchParams.set('file', file.filename);
|
24209
|
-
route(event.target, event, url);
|
24219
|
+
route(event.target, event, viewUrl);
|
24210
24220
|
});
|
24221
|
+
|
24222
|
+
const runUrl = new URL(window.location.origin + window.location.pathname);
|
24223
|
+
setTabInUrl(runUrl, 'query');
|
24224
|
+
runUrl.searchParams.set('file', file.filename);
|
24225
|
+
runUrl.searchParams.set('run', 'true');
|
24226
|
+
|
24227
|
+
const runLinkElement = document.createElement('a');
|
24228
|
+
runLinkElement.classList.add('run-link');
|
24229
|
+
runLinkElement.innerText = 'run';
|
24230
|
+
runLinkElement.href = runUrl.pathname + runUrl.search;
|
24231
|
+
runLinkElement.addEventListener('click', function (event) {
|
24232
|
+
clearResult();
|
24233
|
+
route(event.target, event, runUrl);
|
24234
|
+
});
|
24235
|
+
|
24211
24236
|
const nameElement = document.createElement('h2');
|
24212
24237
|
nameElement.innerText = file.filename;
|
24213
|
-
|
24238
|
+
|
24239
|
+
const nameAndLinksElement = document.createElement('div');
|
24240
|
+
nameAndLinksElement.classList.add('name-and-links');
|
24241
|
+
nameAndLinksElement.appendChild(nameElement);
|
24242
|
+
nameAndLinksElement.appendChild(viewLinkElement);
|
24243
|
+
nameAndLinksElement.appendChild(runLinkElement);
|
24214
24244
|
|
24215
24245
|
const descriptionElement = document.createElement('p');
|
24216
24246
|
descriptionElement.innerText = file.description;
|
24247
|
+
|
24248
|
+
const divElement = document.createElement('div');
|
24249
|
+
divElement.classList.add('saved-list-item');
|
24250
|
+
divElement.appendChild(nameAndLinksElement);
|
24217
24251
|
divElement.appendChild(descriptionElement);
|
24218
24252
|
|
24219
24253
|
savedElement.appendChild(divElement);
|
@@ -24235,7 +24269,7 @@
|
|
24235
24269
|
let sql = getValue().trim();
|
24236
24270
|
sql = sql === '' ? null : sql;
|
24237
24271
|
|
24238
|
-
url.searchParams.
|
24272
|
+
url.searchParams.set('run', 'true');
|
24239
24273
|
|
24240
24274
|
if (url.searchParams.has('file')) {
|
24241
24275
|
if (window.metadata.saved[url.searchParams.get('file')].contents !== getValue()) {
|
@@ -24263,22 +24297,25 @@
|
|
24263
24297
|
url.searchParams.delete('selection');
|
24264
24298
|
url.searchParams.delete('sql');
|
24265
24299
|
url.searchParams.delete('file');
|
24300
|
+
url.searchParams.delete('run');
|
24266
24301
|
}
|
24267
24302
|
|
24268
24303
|
route(target, event, url);
|
24269
24304
|
}
|
24270
24305
|
|
24271
24306
|
function clearResult () {
|
24272
|
-
|
24273
|
-
|
24274
|
-
|
24275
|
-
|
24276
|
-
const existingRequest = window.sqlFetch;
|
24277
|
-
if (existingRequest?.state === 'pending') {
|
24278
|
-
existingRequest.state = 'aborted';
|
24279
|
-
existingRequest.fetchController.abort();
|
24307
|
+
const existingFetch = window.sqlFetch;
|
24308
|
+
if (existingFetch?.state === 'pending') {
|
24309
|
+
existingFetch.state = 'aborted';
|
24310
|
+
existingFetch.fetchController.abort();
|
24280
24311
|
}
|
24281
24312
|
window.sqlFetch = null;
|
24313
|
+
|
24314
|
+
clearGraphBox();
|
24315
|
+
clearGraphStatus();
|
24316
|
+
|
24317
|
+
clearResultBox();
|
24318
|
+
clearResultStatus();
|
24282
24319
|
}
|
24283
24320
|
|
24284
24321
|
function clearResultStatus () {
|
@@ -24303,7 +24340,7 @@
|
|
24303
24340
|
}
|
24304
24341
|
}
|
24305
24342
|
|
24306
|
-
function fetchSql (
|
24343
|
+
function fetchSql (sqlFetch, selection, callback) {
|
24307
24344
|
fetch('query', {
|
24308
24345
|
headers: {
|
24309
24346
|
Accept: 'application/json',
|
@@ -24311,64 +24348,65 @@
|
|
24311
24348
|
},
|
24312
24349
|
method: 'POST',
|
24313
24350
|
body: JSON.stringify({
|
24314
|
-
sql:
|
24351
|
+
sql: sqlFetch.sql,
|
24315
24352
|
selection
|
24316
24353
|
}),
|
24317
|
-
signal:
|
24354
|
+
signal: sqlFetch.fetchController.signal
|
24318
24355
|
})
|
24319
24356
|
.then((response) => {
|
24320
24357
|
const contentType = response.headers.get('content-type');
|
24321
24358
|
if (contentType && contentType.indexOf('application/json') !== -1) {
|
24322
24359
|
response.json().then((result) => {
|
24323
24360
|
if (result?.query) {
|
24324
|
-
|
24325
|
-
|
24361
|
+
sqlFetch.state = 'success';
|
24362
|
+
sqlFetch.result = result;
|
24326
24363
|
} else {
|
24327
|
-
|
24364
|
+
sqlFetch.state = 'error';
|
24328
24365
|
if (result?.error) {
|
24329
|
-
|
24330
|
-
|
24366
|
+
sqlFetch.error_message = result.error;
|
24367
|
+
sqlFetch.error_details = result.stacktrace;
|
24331
24368
|
} else if (result) {
|
24332
|
-
|
24333
|
-
|
24369
|
+
sqlFetch.error_message = 'failed to execute query';
|
24370
|
+
sqlFetch.error_details = result.toString();
|
24334
24371
|
} else {
|
24335
|
-
|
24372
|
+
sqlFetch.error_message = 'failed to execute query';
|
24336
24373
|
}
|
24337
24374
|
}
|
24338
|
-
callback(
|
24375
|
+
callback(sqlFetch);
|
24339
24376
|
});
|
24340
24377
|
} else {
|
24341
24378
|
response.text().then((result) => {
|
24342
|
-
|
24343
|
-
|
24344
|
-
|
24345
|
-
callback(
|
24379
|
+
sqlFetch.state = 'error';
|
24380
|
+
sqlFetch.error_message = 'failed to execute query';
|
24381
|
+
sqlFetch.error_details = result;
|
24382
|
+
callback(sqlFetch);
|
24346
24383
|
});
|
24347
24384
|
}
|
24348
24385
|
})
|
24349
24386
|
.catch(function (error) {
|
24350
|
-
if (
|
24351
|
-
|
24352
|
-
|
24353
|
-
|
24354
|
-
callback(request);
|
24387
|
+
if (sqlFetch.state === 'pending') {
|
24388
|
+
sqlFetch.state = 'error';
|
24389
|
+
sqlFetch.error_message = 'failed to execute query';
|
24390
|
+
sqlFetch.error_details = error;
|
24355
24391
|
}
|
24392
|
+
callback(sqlFetch);
|
24356
24393
|
});
|
24357
24394
|
}
|
24358
24395
|
|
24359
24396
|
function maybeFetchResult () {
|
24360
|
-
const
|
24397
|
+
const url = new URL(window.location);
|
24398
|
+
const params = url.searchParams;
|
24361
24399
|
const sql = params.get('sql');
|
24362
24400
|
const file = params.get('file');
|
24363
24401
|
const selection = params.get('selection');
|
24364
|
-
const run =
|
24402
|
+
const run = ['1', 'true'].includes(params.get('run')?.toLowerCase());
|
24365
24403
|
|
24366
24404
|
if (params.has('file') && params.has('sql')) {
|
24367
24405
|
// TODO: show an error.
|
24368
24406
|
throw new Error('You can only specify a file or sql, not both.')
|
24369
24407
|
}
|
24370
24408
|
|
24371
|
-
const
|
24409
|
+
const sqlFetch = {
|
24372
24410
|
fetchController: new AbortController(),
|
24373
24411
|
state: 'pending',
|
24374
24412
|
sql,
|
@@ -24381,10 +24419,10 @@
|
|
24381
24419
|
if (!fileDetails) {
|
24382
24420
|
throw new Error(`no such file: ${params.get('file')}`)
|
24383
24421
|
}
|
24384
|
-
|
24385
|
-
|
24422
|
+
sqlFetch.file = file;
|
24423
|
+
sqlFetch.sql = fileDetails.contents;
|
24386
24424
|
} else if (params.has('sql')) {
|
24387
|
-
|
24425
|
+
sqlFetch.sql = sql;
|
24388
24426
|
}
|
24389
24427
|
|
24390
24428
|
const existingRequest = window.sqlFetch;
|
@@ -24406,11 +24444,13 @@
|
|
24406
24444
|
clearResult();
|
24407
24445
|
|
24408
24446
|
if (params.has('sql') || params.has('file')) {
|
24409
|
-
setValue(
|
24447
|
+
setValue(sqlFetch.sql);
|
24410
24448
|
if (run) {
|
24411
|
-
|
24412
|
-
|
24413
|
-
|
24449
|
+
url.searchParams.delete('run');
|
24450
|
+
window.history.replaceState({}, '', url);
|
24451
|
+
window.sqlFetch = sqlFetch;
|
24452
|
+
displaySqlFetch(sqlFetch);
|
24453
|
+
fetchSql(sqlFetch, selection, displaySqlFetch);
|
24414
24454
|
}
|
24415
24455
|
}
|
24416
24456
|
if (params.has('selection')) {
|
@@ -24420,17 +24460,22 @@
|
|
24420
24460
|
}
|
24421
24461
|
|
24422
24462
|
function displaySqlFetchInResultTab (fetch) {
|
24423
|
-
const fetchSqlBoxElement = document.getElementById('fetch-sql-box');
|
24424
|
-
const resultBoxElement = document.getElementById('result-box');
|
24425
24463
|
if (fetch.state === 'pending') {
|
24426
24464
|
clearResultBox();
|
24427
|
-
|
24428
|
-
|
24465
|
+
document.getElementById('cancel-button').style.display = 'flex';
|
24466
|
+
document.getElementById('result-box').style.display = 'none';
|
24467
|
+
document.getElementById('fetch-sql-box').style.display = 'flex';
|
24429
24468
|
return
|
24430
24469
|
}
|
24431
24470
|
|
24432
|
-
|
24433
|
-
|
24471
|
+
document.getElementById('cancel-button').style.display = 'none';
|
24472
|
+
document.getElementById('fetch-sql-box').style.display = 'none';
|
24473
|
+
document.getElementById('result-box').style.display = 'flex';
|
24474
|
+
|
24475
|
+
if (fetch.state === 'aborted') {
|
24476
|
+
clearResultBox();
|
24477
|
+
return
|
24478
|
+
}
|
24434
24479
|
|
24435
24480
|
if (fetch.state === 'error') {
|
24436
24481
|
clearResultBox();
|
@@ -24458,7 +24503,7 @@
|
|
24458
24503
|
theadElement.appendChild(headerElement);
|
24459
24504
|
tableElement.appendChild(theadElement);
|
24460
24505
|
tableElement.appendChild(tbodyElement);
|
24461
|
-
|
24506
|
+
document.getElementById('result-box').appendChild(tableElement);
|
24462
24507
|
|
24463
24508
|
fetch.result.columns.forEach(column => {
|
24464
24509
|
const template = document.createElement('template');
|
@@ -24504,17 +24549,22 @@
|
|
24504
24549
|
}
|
24505
24550
|
|
24506
24551
|
function displaySqlFetchInGraphTab (fetch) {
|
24507
|
-
const graphBoxElement = document.getElementById('graph-box');
|
24508
|
-
const fetchSqlBoxElement = document.getElementById('fetch-sql-box');
|
24509
24552
|
if (fetch.state === 'pending') {
|
24510
24553
|
clearGraphBox();
|
24511
|
-
|
24512
|
-
|
24554
|
+
document.getElementById('cancel-button').style.display = 'flex';
|
24555
|
+
document.getElementById('graph-box').style.display = 'none';
|
24556
|
+
document.getElementById('fetch-sql-box').style.display = 'flex';
|
24513
24557
|
return
|
24514
24558
|
}
|
24515
24559
|
|
24516
|
-
|
24517
|
-
|
24560
|
+
document.getElementById('cancel-button').style.display = 'none';
|
24561
|
+
document.getElementById('fetch-sql-box').style.display = 'none';
|
24562
|
+
document.getElementById('graph-box').style.display = 'flex';
|
24563
|
+
|
24564
|
+
if (fetch.state === 'aborted') {
|
24565
|
+
clearGraphBox();
|
24566
|
+
return
|
24567
|
+
}
|
24518
24568
|
|
24519
24569
|
if (fetch.state === 'error') {
|
24520
24570
|
clearGraphBox();
|
@@ -24553,7 +24603,7 @@
|
|
24553
24603
|
dataTable.addRow(rowValues);
|
24554
24604
|
});
|
24555
24605
|
|
24556
|
-
const chart = new google.visualization.LineChart(
|
24606
|
+
const chart = new google.visualization.LineChart(document.getElementById('graph-box'));
|
24557
24607
|
const options = {
|
24558
24608
|
hAxis: {
|
24559
24609
|
title: fetch.result.columns[0]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqlui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.26
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Dower
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mysql2
|