admindb 2.1.0 → 2.2.1
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.
- package/README.md +41 -12
- package/dist/app.d.ts +1 -69
- package/dist/app.js +3 -30
- package/dist/auth/config.d.ts +1 -19
- package/dist/auth/config.js +0 -26
- package/dist/auth/crypto.d.ts +1 -27
- package/dist/auth/crypto.js +1 -26
- package/dist/auth/index.d.ts +1 -5
- package/dist/auth/index.js +0 -1
- package/dist/auth/middleware.d.ts +1 -14
- package/dist/auth/middleware.js +0 -15
- package/dist/auth/routes.d.ts +1 -7
- package/dist/auth/routes.js +0 -8
- package/dist/auth/types.d.ts +1 -35
- package/dist/auth/types.js +1 -5
- package/dist/cli/args.d.ts +1 -45
- package/dist/cli/args.js +3 -11
- package/dist/cli/config.d.ts +1 -56
- package/dist/cli/config.js +0 -5
- package/dist/cli/index.d.ts +1 -4
- package/dist/cli/index.js +0 -1
- package/dist/cli/runner.d.ts +1 -1
- package/dist/cli/runner.js +6 -17
- package/dist/cli.d.ts +1 -2
- package/dist/cli.js +0 -1
- package/dist/data/chain.d.ts +1 -0
- package/dist/data/chain.js +707 -0
- package/dist/data/datasets.d.ts +1 -17
- package/dist/data/datasets.js +0 -4
- package/dist/data/detector.d.ts +1 -30
- package/dist/data/detector.js +53 -14
- package/dist/data/engine.d.ts +1 -10
- package/dist/data/engine.js +82 -48
- package/dist/data/index.d.ts +1 -5
- package/dist/data/index.js +1 -1
- package/dist/data/strategies.d.ts +1 -30
- package/dist/data/strategies.js +4 -8
- package/dist/data/types.d.ts +1 -73
- package/dist/data/types.js +0 -3
- package/dist/db/database.d.ts +1 -119
- package/dist/db/database.js +20 -14
- package/dist/db/export.d.ts +1 -12
- package/dist/db/export.js +54 -6
- package/dist/db/filters.d.ts +1 -22
- package/dist/db/filters.js +0 -16
- package/dist/db/index.d.ts +1 -8
- package/dist/db/index.js +0 -1
- package/dist/db/introspection.d.ts +1 -6
- package/dist/db/introspection.js +0 -5
- package/dist/db/manager.d.ts +1 -81
- package/dist/db/manager.js +13 -59
- package/dist/db/migrations.d.ts +1 -5
- package/dist/db/migrations.js +2 -5
- package/dist/db/postgres.d.ts +1 -85
- package/dist/db/postgres.js +21 -31
- package/dist/db/types.d.ts +1 -206
- package/dist/db/types.js +0 -1
- package/dist/index.d.ts +1 -23
- package/dist/index.js +0 -14
- package/dist/public/css/app.css +1 -1
- package/dist/public/js/api.js +1 -47
- package/dist/public/js/app.js +1 -262
- package/dist/public/js/browse.js +1 -1371
- package/dist/public/js/common.js +1 -0
- package/dist/public/js/databases.js +1 -235
- package/dist/public/js/designer.js +1 -258
- package/dist/public/js/forms.js +1 -826
- package/dist/public/js/home.js +1 -0
- package/dist/public/js/inspector.js +1 -638
- package/dist/public/js/query.js +1 -322
- package/dist/public/js/schema.js +1 -447
- package/dist/public/js/seed.js +1 -1090
- package/dist/routes/api/erd.d.ts +1 -0
- package/dist/routes/api/erd.js +50 -0
- package/dist/routes/api/helpers.d.ts +1 -42
- package/dist/routes/api/helpers.js +33 -3
- package/dist/routes/api/import-export.d.ts +1 -3
- package/dist/routes/api/import-export.js +0 -2
- package/dist/routes/api/index.d.ts +1 -4
- package/dist/routes/api/index.js +15 -4
- package/dist/routes/api/query.d.ts +1 -3
- package/dist/routes/api/query.js +13 -11
- package/dist/routes/api/rows.d.ts +1 -3
- package/dist/routes/api/rows.js +0 -11
- package/dist/routes/api/seed.d.ts +1 -3
- package/dist/routes/api/seed.js +79 -8
- package/dist/routes/api/tables.d.ts +1 -3
- package/dist/routes/api/tables.js +77 -6
- package/dist/routes/databases.d.ts +1 -26
- package/dist/routes/databases.js +1 -3
- package/dist/routes/index.d.ts +1 -3
- package/dist/routes/index.js +0 -1
- package/dist/routes/pages.d.ts +1 -9
- package/dist/routes/pages.js +18 -11
- package/dist/serverless.d.ts +1 -40
- package/dist/serverless.js +3 -39
- package/dist/sql/classifier.d.ts +1 -19
- package/dist/sql/classifier.js +0 -13
- package/dist/sql/error-analyzer.d.ts +1 -0
- package/dist/sql/error-analyzer.js +550 -0
- package/dist/sql/generator.d.ts +1 -81
- package/dist/sql/generator.js +0 -29
- package/dist/sql/index.d.ts +1 -2
- package/dist/sql/index.js +0 -1
- package/dist/types/api.d.ts +1 -412
- package/dist/types/api.js +0 -7
- package/dist/utils/colors.d.ts +1 -40
- package/dist/utils/colors.js +0 -10
- package/dist/utils/common.d.ts +1 -50
- package/dist/utils/common.js +19 -23
- package/dist/utils/csv.d.ts +1 -15
- package/dist/utils/csv.js +0 -13
- package/dist/utils/datatype.d.ts +1 -49
- package/dist/utils/datatype.js +0 -41
- package/dist/utils/icons.d.ts +1 -11
- package/dist/utils/icons.js +25 -16
- package/dist/utils/index.d.ts +1 -4
- package/dist/utils/index.js +0 -1
- package/dist/utils/logger.d.ts +1 -10
- package/dist/utils/logger.js +0 -4
- package/dist/views/layouts/main.hbs +14 -5
- package/dist/views/pages/databases.hbs +0 -18
- package/dist/views/pages/designer.hbs +0 -10
- package/dist/views/pages/erd.hbs +1241 -0
- package/dist/views/pages/error.hbs +0 -2
- package/dist/views/pages/form.hbs +0 -5
- package/dist/views/pages/home.hbs +98 -10
- package/dist/views/pages/info.hbs +107 -0
- package/dist/views/pages/login.hbs +0 -13
- package/dist/views/pages/query.hbs +54 -21
- package/dist/views/pages/schema.hbs +0 -20
- package/dist/views/pages/seed.hbs +435 -202
- package/dist/views/pages/table.hbs +0 -14
- package/dist/views/partials/icon.hbs +0 -1
- package/dist/views/partials/navbar.hbs +0 -6
- package/dist/views/partials/sidebar.hbs +12 -8
- package/docs/API.md +6 -1
- package/docs/EXAMPLES.md +3 -0
- package/package.json +7 -5
- package/dist/app.js.map +0 -1
- package/dist/auth/config.js.map +0 -1
- package/dist/auth/crypto.js.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/middleware.js.map +0 -1
- package/dist/auth/routes.js.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/cli/args.js.map +0 -1
- package/dist/cli/config.js.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/runner.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/data/datasets.js.map +0 -1
- package/dist/data/detector.js.map +0 -1
- package/dist/data/engine.js.map +0 -1
- package/dist/data/index.js.map +0 -1
- package/dist/data/strategies.js.map +0 -1
- package/dist/data/types.js.map +0 -1
- package/dist/db/database.js.map +0 -1
- package/dist/db/export.js.map +0 -1
- package/dist/db/filters.js.map +0 -1
- package/dist/db/index.js.map +0 -1
- package/dist/db/introspection.js.map +0 -1
- package/dist/db/manager.js.map +0 -1
- package/dist/db/migrations.js.map +0 -1
- package/dist/db/postgres.js.map +0 -1
- package/dist/db/types.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/public/css/input.css +0 -302
- package/dist/public/js/icons.js +0 -51
- package/dist/routes/api/helpers.js.map +0 -1
- package/dist/routes/api/import-export.js.map +0 -1
- package/dist/routes/api/index.js.map +0 -1
- package/dist/routes/api/query.js.map +0 -1
- package/dist/routes/api/rows.js.map +0 -1
- package/dist/routes/api/seed.js.map +0 -1
- package/dist/routes/api/tables.js.map +0 -1
- package/dist/routes/databases.js.map +0 -1
- package/dist/routes/index.js.map +0 -1
- package/dist/routes/pages.js.map +0 -1
- package/dist/serverless.js.map +0 -1
- package/dist/sql/classifier.js.map +0 -1
- package/dist/sql/generator.js.map +0 -1
- package/dist/sql/index.js.map +0 -1
- package/dist/types/api.js.map +0 -1
- package/dist/utils/colors.js.map +0 -1
- package/dist/utils/common.js.map +0 -1
- package/dist/utils/csv.js.map +0 -1
- package/dist/utils/datatype.js.map +0 -1
- package/dist/utils/icons.js.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/logger.js.map +0 -1
package/dist/public/js/api.js
CHANGED
|
@@ -1,47 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* consistent { success, data?, error? } envelope, or throws with the message. */
|
|
3
|
-
(function () {
|
|
4
|
-
'use strict';
|
|
5
|
-
const base = (window.APP && window.APP.basePath) || '';
|
|
6
|
-
|
|
7
|
-
function url(path) {
|
|
8
|
-
return base + path;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
window.Api = {
|
|
12
|
-
basePath: base,
|
|
13
|
-
url: url,
|
|
14
|
-
|
|
15
|
-
async request(method, path, body) {
|
|
16
|
-
const opts = { method, headers: {} };
|
|
17
|
-
if (body !== undefined) {
|
|
18
|
-
opts.headers['Content-Type'] = 'application/json';
|
|
19
|
-
opts.body = JSON.stringify(body);
|
|
20
|
-
}
|
|
21
|
-
let res;
|
|
22
|
-
try {
|
|
23
|
-
res = await fetch(url(path), opts);
|
|
24
|
-
} catch (e) {
|
|
25
|
-
throw new Error('Network error: ' + e.message);
|
|
26
|
-
}
|
|
27
|
-
let data = null;
|
|
28
|
-
try {
|
|
29
|
-
data = await res.json();
|
|
30
|
-
} catch (e) {
|
|
31
|
-
data = null;
|
|
32
|
-
}
|
|
33
|
-
if (!res.ok) {
|
|
34
|
-
throw new Error((data && data.error) || 'Request failed (' + res.status + ')');
|
|
35
|
-
}
|
|
36
|
-
if (!data || data.success === false) {
|
|
37
|
-
throw new Error((data && data.error) || 'Request failed');
|
|
38
|
-
}
|
|
39
|
-
return data.data;
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
get(path) { return this.request('GET', path); },
|
|
43
|
-
post(path, body) { return this.request('POST', path, body); },
|
|
44
|
-
put(path, body) { return this.request('PUT', path, body); },
|
|
45
|
-
del(path) { return this.request('DELETE', path); },
|
|
46
|
-
};
|
|
47
|
-
})();
|
|
1
|
+
!function(){"use strict";const t=window.APP&&window.APP.basePath||"";function e(e){return t+e}window.Api={basePath:t,url:e,async request(t,r,s){const a={method:t,headers:{}};let n;void 0!==s&&(a.headers["Content-Type"]="application/json",a.body=JSON.stringify(s));try{n=await fetch(e(r),a)}catch(t){throw new Error("Network error: "+t.message)}let i=null;try{i=await n.json()}catch(t){i=null}if(!n.ok){const t=i&&i.error||"Request failed ("+n.status+")",e=new Error(t);throw e.status=n.status,i&&i.details&&(e.details=i.details),e.data=i,e}if(!i||!1===i.success){const t=i&&i.error||"Request failed",e=new Error(t);throw i&&i.details&&(e.details=i.details),e.data=i,e}return i.data},get(t){return this.request("GET",t)},post(t,e){return this.request("POST",t,e)},put(t,e){return this.request("PUT",t,e)},del(t){return this.request("DELETE",t)}}}();
|
package/dist/public/js/app.js
CHANGED
|
@@ -1,262 +1 @@
|
|
|
1
|
-
|
|
2
|
-
(function () {
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
function escapeHtml(s) {
|
|
6
|
-
return String(s == null ? '' : s)
|
|
7
|
-
.replace(/&/g, '&')
|
|
8
|
-
.replace(/</g, '<')
|
|
9
|
-
.replace(/>/g, '>')
|
|
10
|
-
.replace(/"/g, '"')
|
|
11
|
-
.replace(/'/g, ''');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
var ICONS = {
|
|
15
|
-
error:
|
|
16
|
-
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>',
|
|
17
|
-
success:
|
|
18
|
-
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /></svg>',
|
|
19
|
-
info:
|
|
20
|
-
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>',
|
|
21
|
-
warning:
|
|
22
|
-
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>',
|
|
23
|
-
sun:
|
|
24
|
-
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /></svg>',
|
|
25
|
-
moon:
|
|
26
|
-
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" /></svg>',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
var PALETTES = {
|
|
30
|
-
error: 'border-error/40 bg-error/10 text-error',
|
|
31
|
-
success: 'border-success/40 bg-success/10 text-success',
|
|
32
|
-
info: 'border-info/40 bg-info/10 text-info',
|
|
33
|
-
warning: 'border-warning/40 bg-warning/10 text-warning',
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
function showToast(message, type) {
|
|
37
|
-
var container = document.getElementById('toast-container');
|
|
38
|
-
if (!container) return;
|
|
39
|
-
type = type || 'info';
|
|
40
|
-
var el = document.createElement('div');
|
|
41
|
-
el.className =
|
|
42
|
-
'toast-item pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-xl border bg-base-100 px-4 py-3 shadow-lift ' +
|
|
43
|
-
(PALETTES[type] || PALETTES.info);
|
|
44
|
-
el.innerHTML =
|
|
45
|
-
'<span class="mt-0.5 shrink-0">' + (ICONS[type] || ICONS.info) + '</span>' +
|
|
46
|
-
'<span class="flex-1 text-sm font-medium text-base-content">' + escapeHtml(message) + '</span>' +
|
|
47
|
-
'<button type="button" class="toast-close mt-0.5 shrink-0 text-base-content/40 transition-colors hover:text-base-content" aria-label="Dismiss">×</button>';
|
|
48
|
-
container.appendChild(el);
|
|
49
|
-
|
|
50
|
-
var remove = function () {
|
|
51
|
-
el.style.transition = 'opacity .18s ease, transform .18s ease';
|
|
52
|
-
el.style.opacity = '0';
|
|
53
|
-
el.style.transform = 'translateY(-6px) scale(0.98)';
|
|
54
|
-
setTimeout(function () { el.remove(); }, 180);
|
|
55
|
-
};
|
|
56
|
-
el.querySelector('.toast-close').addEventListener('click', remove);
|
|
57
|
-
setTimeout(remove, 4200);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ---- Theme -------------------------------------------------------------
|
|
61
|
-
|
|
62
|
-
function applyTheme(dark) {
|
|
63
|
-
document.documentElement.setAttribute('data-theme', dark ? 'admindbDark' : 'admindb');
|
|
64
|
-
try {
|
|
65
|
-
localStorage.setItem('admindb-theme', dark ? 'dark' : 'light');
|
|
66
|
-
} catch (e) { /* ignore */ }
|
|
67
|
-
var btn = document.getElementById('theme-toggle');
|
|
68
|
-
if (btn) btn.innerHTML = dark ? ICONS.sun : ICONS.moon;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function initTheme() {
|
|
72
|
-
var stored = null;
|
|
73
|
-
try {
|
|
74
|
-
stored = localStorage.getItem('admindb-theme');
|
|
75
|
-
} catch (e) { /* ignore */ }
|
|
76
|
-
var dark = stored === 'dark' ||
|
|
77
|
-
(!stored && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
|
78
|
-
applyTheme(dark);
|
|
79
|
-
var btn = document.getElementById('theme-toggle');
|
|
80
|
-
if (btn) {
|
|
81
|
-
btn.addEventListener('click', function () {
|
|
82
|
-
var current = document.documentElement.getAttribute('data-theme') === 'admindbDark';
|
|
83
|
-
applyTheme(!current);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// ---- Sidebar table filter ----------------------------------------------
|
|
89
|
-
|
|
90
|
-
function initTableFilter() {
|
|
91
|
-
var input = document.getElementById('table-search');
|
|
92
|
-
var list = document.getElementById('table-list');
|
|
93
|
-
var countEl = document.getElementById('table-count');
|
|
94
|
-
if (!input || !list) return;
|
|
95
|
-
var items = Array.prototype.slice.call(list.querySelectorAll('.table-item'));
|
|
96
|
-
input.addEventListener('input', function () {
|
|
97
|
-
var q = input.value.trim().toLowerCase();
|
|
98
|
-
var shown = 0;
|
|
99
|
-
items.forEach(function (item) {
|
|
100
|
-
var name = (item.getAttribute('data-name') || '').toLowerCase();
|
|
101
|
-
var show = !q || name.indexOf(q) !== -1;
|
|
102
|
-
item.style.display = show ? '' : 'none';
|
|
103
|
-
if (show) shown += 1;
|
|
104
|
-
});
|
|
105
|
-
if (countEl) countEl.textContent = String(shown);
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// ---- Universal Confirm Dialog -------------------------------------------
|
|
110
|
-
|
|
111
|
-
function confirmDialog(options) {
|
|
112
|
-
return new Promise(function (resolve) {
|
|
113
|
-
if (typeof options === 'string') {
|
|
114
|
-
options = { message: options };
|
|
115
|
-
}
|
|
116
|
-
options = options || {};
|
|
117
|
-
var title = options.title || 'Confirm action';
|
|
118
|
-
var message = options.message || 'Are you sure you want to proceed?';
|
|
119
|
-
var confirmText = options.confirmText || (options.danger !== false ? 'Delete' : 'Confirm');
|
|
120
|
-
var cancelText = options.cancelText || 'Cancel';
|
|
121
|
-
var isDanger = options.danger !== false;
|
|
122
|
-
var requireMatch = options.requireInputMatch ? String(options.requireInputMatch).trim() : null;
|
|
123
|
-
|
|
124
|
-
var overlay = document.createElement('div');
|
|
125
|
-
overlay.className =
|
|
126
|
-
'fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-xs p-4 opacity-0 transition-opacity duration-200';
|
|
127
|
-
overlay.setAttribute('role', 'dialog');
|
|
128
|
-
overlay.setAttribute('aria-modal', 'true');
|
|
129
|
-
|
|
130
|
-
var card = document.createElement('div');
|
|
131
|
-
card.className =
|
|
132
|
-
'app-card w-full max-w-lg overflow-hidden shadow-2xl border border-base-300 transform scale-95 transition-transform duration-200';
|
|
133
|
-
|
|
134
|
-
var badgeColor = isDanger ? 'bg-error/10 text-error border-error/20' : 'bg-warning/10 text-warning border-warning/20';
|
|
135
|
-
var confirmBtnClass = isDanger ? 'btn-error text-white' : 'btn-primary';
|
|
136
|
-
|
|
137
|
-
var itemHtml = '';
|
|
138
|
-
if (options.item) {
|
|
139
|
-
var itemTypeLabel = options.itemType ? escapeHtml(options.itemType) + ': ' : '';
|
|
140
|
-
itemHtml =
|
|
141
|
-
'<div class="mb-3.5 flex items-center gap-2 rounded-xl border border-base-300 bg-base-200/60 px-3.5 py-2.5">' +
|
|
142
|
-
'<span class="text-xs font-semibold uppercase tracking-wider text-base-content/50">' + itemTypeLabel + '</span>' +
|
|
143
|
-
'<span class="font-mono text-sm font-bold text-base-content break-all">' + escapeHtml(options.item) + '</span>' +
|
|
144
|
-
'</div>';
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
var inputMatchHtml = '';
|
|
148
|
-
if (requireMatch) {
|
|
149
|
-
inputMatchHtml =
|
|
150
|
-
'<div class="mt-4 space-y-1.5">' +
|
|
151
|
-
'<label class="text-xs font-medium text-base-content/70">To confirm, type <span class="font-mono font-bold text-base-content select-all">' + escapeHtml(requireMatch) + '</span> below:</label>' +
|
|
152
|
-
'<input type="text" class="field-input font-mono js-confirm-input" placeholder="' + escapeHtml(options.requireInputPlaceholder || requireMatch) + '" autocomplete="off" spellcheck="false" />' +
|
|
153
|
-
'</div>';
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
var detailsHtml = options.detailsHtml ? '<div class="mt-3.5 max-h-48 overflow-y-auto rounded-xl border border-base-200 bg-base-200/40 p-3 text-xs leading-relaxed text-base-content/75">' + options.detailsHtml + '</div>' : '';
|
|
157
|
-
|
|
158
|
-
card.innerHTML =
|
|
159
|
-
'<div class="flex items-start justify-between gap-3 border-b border-base-200 px-6 py-4">' +
|
|
160
|
-
' <div class="flex items-center gap-3">' +
|
|
161
|
-
' <div class="grid h-10 w-10 shrink-0 place-items-center rounded-xl border ' + badgeColor + '">' +
|
|
162
|
-
(isDanger ? ICONS.warning : ICONS.info) +
|
|
163
|
-
' </div>' +
|
|
164
|
-
' <div>' +
|
|
165
|
-
' <h3 class="text-base font-bold text-base-content">' + escapeHtml(title) + '</h3>' +
|
|
166
|
-
' <p class="text-xs text-base-content/50 font-medium">' + (isDanger ? 'Destructive Action' : 'Action Confirmation') + '</p>' +
|
|
167
|
-
' </div>' +
|
|
168
|
-
' </div>' +
|
|
169
|
-
' <button type="button" class="btn btn-ghost btn-xs btn-circle js-modal-cancel text-base-content/40 hover:text-base-content" aria-label="Close">×</button>' +
|
|
170
|
-
'</div>' +
|
|
171
|
-
'<div class="px-6 py-5">' +
|
|
172
|
-
itemHtml +
|
|
173
|
-
' <p class="text-sm text-base-content/80 leading-relaxed">' + escapeHtml(message) + '</p>' +
|
|
174
|
-
detailsHtml +
|
|
175
|
-
inputMatchHtml +
|
|
176
|
-
'</div>' +
|
|
177
|
-
'<div class="flex flex-wrap items-center justify-end gap-2.5 border-t border-base-200 bg-base-200/30 px-6 py-4">' +
|
|
178
|
-
' <button type="button" class="btn btn-ghost btn-sm js-modal-cancel">' + escapeHtml(cancelText) + '</button>' +
|
|
179
|
-
' <button type="button" class="btn ' + confirmBtnClass + ' btn-sm js-modal-confirm" ' + (requireMatch ? 'disabled' : '') + '>' + escapeHtml(confirmText) + '</button>' +
|
|
180
|
-
'</div>';
|
|
181
|
-
|
|
182
|
-
overlay.appendChild(card);
|
|
183
|
-
document.body.appendChild(overlay);
|
|
184
|
-
|
|
185
|
-
requestAnimationFrame(function () {
|
|
186
|
-
overlay.classList.remove('opacity-0');
|
|
187
|
-
overlay.classList.add('opacity-100');
|
|
188
|
-
card.classList.remove('scale-95');
|
|
189
|
-
card.classList.add('scale-100');
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
var confirmBtn = card.querySelector('.js-modal-confirm');
|
|
193
|
-
var cancelBtns = card.querySelectorAll('.js-modal-cancel');
|
|
194
|
-
var inputEl = card.querySelector('.js-confirm-input');
|
|
195
|
-
|
|
196
|
-
if (inputEl) {
|
|
197
|
-
inputEl.addEventListener('input', function () {
|
|
198
|
-
var val = inputEl.value.trim();
|
|
199
|
-
confirmBtn.disabled = val !== requireMatch;
|
|
200
|
-
});
|
|
201
|
-
inputEl.addEventListener('keydown', function (e) {
|
|
202
|
-
if (e.key === 'Enter' && !confirmBtn.disabled) {
|
|
203
|
-
e.preventDefault();
|
|
204
|
-
finish(true);
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
setTimeout(function () { inputEl.focus(); }, 50);
|
|
208
|
-
} else {
|
|
209
|
-
var cancelBtn = card.querySelector('.js-modal-cancel');
|
|
210
|
-
if (cancelBtn) setTimeout(function () { cancelBtn.focus(); }, 50);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
var finished = false;
|
|
214
|
-
function finish(result) {
|
|
215
|
-
if (finished) return;
|
|
216
|
-
finished = true;
|
|
217
|
-
document.removeEventListener('keydown', onKeyDown);
|
|
218
|
-
overlay.classList.remove('opacity-100');
|
|
219
|
-
overlay.classList.add('opacity-0');
|
|
220
|
-
card.classList.remove('scale-100');
|
|
221
|
-
card.classList.add('scale-95');
|
|
222
|
-
setTimeout(function () {
|
|
223
|
-
overlay.remove();
|
|
224
|
-
resolve(result);
|
|
225
|
-
}, 180);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function onKeyDown(e) {
|
|
229
|
-
if (e.key === 'Escape') {
|
|
230
|
-
e.preventDefault();
|
|
231
|
-
finish(false);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
document.addEventListener('keydown', onKeyDown);
|
|
235
|
-
|
|
236
|
-
cancelBtns.forEach(function (btn) {
|
|
237
|
-
btn.addEventListener('click', function () { finish(false); });
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
confirmBtn.addEventListener('click', function () {
|
|
241
|
-
if (!confirmBtn.disabled) finish(true);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
overlay.addEventListener('click', function (e) {
|
|
245
|
-
if (e.target === overlay) finish(false);
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
document.addEventListener('DOMContentLoaded', function () {
|
|
251
|
-
initTheme();
|
|
252
|
-
initTableFilter();
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
window.UI = {
|
|
256
|
-
escapeHtml: escapeHtml,
|
|
257
|
-
showToast: showToast,
|
|
258
|
-
showError: function (message) { showToast(message, 'error'); },
|
|
259
|
-
confirm: confirmDialog,
|
|
260
|
-
applyTheme: applyTheme,
|
|
261
|
-
};
|
|
262
|
-
})();
|
|
1
|
+
!function(){"use strict";function e(e){return String(null==e?"":e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}var t={error:'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>',success:'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /></svg>',info:'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>',warning:'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>',sun:'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /></svg>',moon:'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" /></svg>'},n={error:"border-error/40 bg-error/10 text-error",success:"border-success/40 bg-success/10 text-success",info:"border-info/40 bg-info/10 text-info",warning:"border-warning/40 bg-warning/10 text-warning"};function o(o,r){var s=document.getElementById("toast-container");if(s){r=r||"info";var a=document.createElement("div");a.className="toast-item pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-xl border bg-base-100 px-4 py-3 shadow-lift "+(n[r]||n.info),a.innerHTML='<span class="mt-0.5 shrink-0">'+(t[r]||t.info)+'</span><span class="flex-1 text-sm font-medium text-base-content">'+e(o)+'</span><button type="button" class="toast-close mt-0.5 shrink-0 text-base-content/40 transition-colors hover:text-base-content" aria-label="Dismiss">×</button>',s.appendChild(a);var i=function(){a.style.transition="opacity .18s ease, transform .18s ease",a.style.opacity="0",a.style.transform="translateY(-6px) scale(0.98)",setTimeout(function(){a.remove()},180)};a.querySelector(".toast-close").addEventListener("click",i),setTimeout(i,4200)}}function r(e){document.documentElement.setAttribute("data-theme",e?"admindbDark":"admindb");try{localStorage.setItem("admindb-theme",e?"dark":"light")}catch(e){}var n=document.getElementById("theme-toggle");n&&(n.innerHTML=e?t.sun:t.moon)}document.addEventListener("DOMContentLoaded",function(){!function(){var e=null;try{e=localStorage.getItem("admindb-theme")}catch(e){}r("dark"===e||!e&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches);var t=document.getElementById("theme-toggle");t&&t.addEventListener("click",function(){r(!("admindbDark"===document.documentElement.getAttribute("data-theme")))})}(),function(){var e=document.getElementById("table-search"),t=document.getElementById("table-list"),n=document.getElementById("table-count");if(e&&t){var o=Array.prototype.slice.call(t.querySelectorAll(".table-item"));e.addEventListener("input",function(){var t=e.value.trim().toLowerCase(),r=0;o.forEach(function(e){var n=(e.getAttribute("data-name")||"").toLowerCase(),o=!t||-1!==n.indexOf(t);e.style.display=o?"":"none",o&&(r+=1)}),n&&(n.textContent=String(r))})}}()}),window.UI={escapeHtml:e,showToast:o,showError:function(e){o(e,"error")},confirm:function(n){return new Promise(function(o){"string"==typeof n&&(n={message:n});var r=(n=n||{}).title||"Confirm action",s=n.message||"Are you sure you want to proceed?",a=n.confirmText||(!1!==n.danger?"Delete":"Confirm"),i=n.cancelText||"Cancel",l=!1!==n.danger,c=n.requireInputMatch?String(n.requireInputMatch).trim():null,d=document.createElement("div");d.className="fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-xs p-4 opacity-0 transition-opacity duration-200",d.setAttribute("role","dialog"),d.setAttribute("aria-modal","true");var m=document.createElement("div");m.className="app-card w-full max-w-lg overflow-hidden shadow-2xl border border-base-300 transform scale-95 transition-transform duration-200";var u=l?"bg-error/10 text-error border-error/20":"bg-warning/10 text-warning border-warning/20",p=l?"btn-error text-white":"btn-primary",b="";n.item&&(b='<div class="mb-3.5 flex items-center gap-2 rounded-xl border border-base-300 bg-base-200/60 px-3.5 py-2.5"><span class="text-xs font-semibold uppercase tracking-wider text-base-content/50">'+(n.itemType?e(n.itemType)+": ":"")+'</span><span class="font-mono text-sm font-bold text-base-content break-all">'+e(n.item)+"</span></div>");var f="";c&&(f='<div class="mt-4 space-y-1.5"><label class="text-xs font-medium text-base-content/70">To confirm, type <span class="font-mono font-bold text-base-content select-all">'+e(c)+'</span> below:</label><input type="text" class="field-input font-mono js-confirm-input" placeholder="'+e(n.requireInputPlaceholder||c)+'" autocomplete="off" spellcheck="false" /></div>');var v=n.detailsHtml?'<div class="mt-3.5 max-h-48 overflow-y-auto rounded-xl border border-base-200 bg-base-200/40 p-3 text-xs leading-relaxed text-base-content/75">'+n.detailsHtml+"</div>":"";m.innerHTML='<div class="flex items-start justify-between gap-3 border-b border-base-200 px-6 py-4"> <div class="flex items-center gap-3"> <div class="grid h-10 w-10 shrink-0 place-items-center rounded-xl border '+u+'">'+(l?t.warning:t.info)+' </div> <div> <h3 class="text-base font-bold text-base-content">'+e(r)+'</h3> <p class="text-xs text-base-content/50 font-medium">'+(l?"Destructive Action":"Action Confirmation")+'</p> </div> </div> <button type="button" class="btn btn-ghost btn-xs btn-circle js-modal-cancel text-base-content/40 hover:text-base-content" aria-label="Close">×</button></div><div class="px-6 py-5">'+b+' <p class="text-sm text-base-content/80 leading-relaxed">'+e(s)+"</p>"+v+f+'</div><div class="flex flex-wrap items-center justify-end gap-2.5 border-t border-base-200 bg-base-200/30 px-6 py-4"> <button type="button" class="btn btn-ghost btn-sm js-modal-cancel">'+e(i)+'</button> <button type="button" class="btn '+p+' btn-sm js-modal-confirm" '+(c?"disabled":"")+">"+e(a)+"</button></div>",d.appendChild(m),document.body.appendChild(d),requestAnimationFrame(function(){d.classList.remove("opacity-0"),d.classList.add("opacity-100"),m.classList.remove("scale-95"),m.classList.add("scale-100")});var g=m.querySelector(".js-modal-confirm"),w=m.querySelectorAll(".js-modal-cancel"),x=m.querySelector(".js-confirm-input");if(x)x.addEventListener("input",function(){var e=x.value.trim();g.disabled=e!==c}),x.addEventListener("keydown",function(e){"Enter"!==e.key||g.disabled||(e.preventDefault(),k(!0))}),setTimeout(function(){x.focus()},50);else{var h=m.querySelector(".js-modal-cancel");h&&setTimeout(function(){h.focus()},50)}var y=!1;function k(e){y||(y=!0,document.removeEventListener("keydown",L),d.classList.remove("opacity-100"),d.classList.add("opacity-0"),m.classList.remove("scale-100"),m.classList.add("scale-95"),setTimeout(function(){d.remove(),o(e)},180))}function L(e){"Escape"===e.key&&(e.preventDefault(),k(!1))}document.addEventListener("keydown",L),w.forEach(function(e){e.addEventListener("click",function(){k(!1)})}),g.addEventListener("click",function(){g.disabled||k(!0)}),d.addEventListener("click",function(e){e.target===d&&k(!1)})})},applyTheme:r}}();
|