admindb 1.0.1 → 1.0.3

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.
@@ -1,155 +1,155 @@
1
- /* Triggers page: create / drop triggers with a live SQL preview. */
2
- (function () {
3
- 'use strict';
4
- const cfgEl = document.getElementById('triggers-config');
5
- if (!cfgEl) return;
6
-
7
- function escapeHtml(s) {
8
- return (window.UI && UI.escapeHtml) ? UI.escapeHtml(s) : String(s == null ? '' : s);
9
- }
10
-
11
- function showError(el, msg) {
12
- el.classList.remove('hidden');
13
- el.innerHTML = '<div class="flex items-start gap-2.5 rounded-xl border border-error/40 bg-error/10 px-4 py-3 text-sm font-medium text-error"><span>' + escapeHtml(msg) + '</span></div>';
14
- }
15
-
16
- // ---- Editor gutter ------------------------------------------------------
17
-
18
- const editor = document.getElementById('trigger-body');
19
- const gutter = document.getElementById('trigger-gutter');
20
- function updateGutter() {
21
- if (!gutter || !editor) return;
22
- const lines = editor.value.split('\n').length;
23
- let html = '';
24
- for (let i = 1; i <= lines; i++) html += i + '\n';
25
- gutter.textContent = html;
26
- gutter.scrollTop = editor.scrollTop;
27
- }
28
- if (editor && gutter) {
29
- editor.addEventListener('scroll', () => { gutter.scrollTop = editor.scrollTop; });
30
- editor.addEventListener('input', updateGutter);
31
- updateGutter();
32
- }
33
-
34
- // ---- New trigger form ---------------------------------------------------
35
-
36
- const newBtn = document.getElementById('new-trigger');
37
- const panel = document.getElementById('new-trigger-panel');
38
- const nameInput = document.getElementById('trigger-name');
39
- const tableInput = document.getElementById('trigger-table');
40
- const timingInput = document.getElementById('trigger-timing');
41
- const eventInput = document.getElementById('trigger-event');
42
- const whenInput = document.getElementById('trigger-when');
43
- const bodyInput = document.getElementById('trigger-body');
44
- const errEl = document.getElementById('trigger-error');
45
- const createBtn = document.getElementById('create-trigger');
46
- const cancelBtn = document.getElementById('cancel-trigger');
47
- const preview = document.getElementById('trigger-preview');
48
- const previewCode = document.getElementById('trigger-preview-code');
49
- const previewHint = document.getElementById('trigger-preview-hint');
50
- let previewTimer = null;
51
-
52
- function currentEvent() {
53
- return eventInput ? eventInput.value : 'INSERT';
54
- }
55
-
56
- function renderPreview() {
57
- clearTimeout(previewTimer);
58
- const name = (nameInput.value || '').trim();
59
- const table = tableInput.value || '';
60
- const event = currentEvent();
61
- if (!name && !table && !(bodyInput.value || '').trim()) {
62
- preview.classList.add('hidden');
63
- previewCode.textContent = '';
64
- if (previewHint) previewHint.classList.remove('hidden');
65
- return;
66
- }
67
- previewTimer = setTimeout(async () => {
68
- try {
69
- const data = await Api.post('/api/triggers/generate', {
70
- name,
71
- table,
72
- timing: timingInput.value,
73
- event,
74
- when: (whenInput.value || '').trim() || undefined,
75
- body: bodyInput.value,
76
- });
77
- previewCode.textContent = data.sql;
78
- preview.classList.remove('hidden');
79
- if (previewHint) previewHint.classList.add('hidden');
80
- } catch (e) {
81
- preview.classList.add('hidden');
82
- previewCode.textContent = '';
83
- if (previewHint) previewHint.classList.remove('hidden');
84
- }
85
- }, 250);
86
- }
87
-
88
- if (newBtn && panel) {
89
- newBtn.addEventListener('click', () => {
90
- panel.classList.toggle('hidden');
91
- if (!panel.classList.contains('hidden')) {
92
- errEl.classList.add('hidden');
93
- nameInput.focus();
94
- renderPreview();
95
- }
96
- });
97
- }
98
- [nameInput, tableInput, timingInput, eventInput, whenInput, bodyInput].forEach((el) => {
99
- if (el) el.addEventListener('input', renderPreview);
100
- });
101
-
102
- if (cancelBtn) {
103
- cancelBtn.addEventListener('click', () => {
104
- panel.classList.add('hidden');
105
- errEl.classList.add('hidden');
106
- });
107
- }
108
-
109
- if (createBtn) {
110
- createBtn.addEventListener('click', async () => {
111
- errEl.classList.add('hidden');
112
- const name = (nameInput.value || '').trim();
113
- const table = tableInput.value || '';
114
- const body = (bodyInput.value || '').trim();
115
- const event = currentEvent();
116
- if (!name) return showError(errEl, 'Trigger name is required.');
117
- if (!table) return showError(errEl, 'Select a table for the trigger.');
118
- if (!body) return showError(errEl, 'Trigger body is required.');
119
- createBtn.disabled = true;
120
- try {
121
- const data = await Api.post('/api/triggers', {
122
- name,
123
- table,
124
- timing: timingInput.value,
125
- event,
126
- when: (whenInput.value || '').trim() || undefined,
127
- body,
128
- });
129
- UI.showToast(data.message || 'Trigger created.', 'success');
130
- window.location.reload();
131
- } catch (e) {
132
- showError(errEl, e.message);
133
- } finally {
134
- createBtn.disabled = false;
135
- }
136
- });
137
- }
138
-
139
- // ---- Drop trigger -------------------------------------------------------
140
-
141
- document.querySelectorAll('.trigger-drop').forEach((btn) => {
142
- btn.addEventListener('click', async () => {
143
- const name = btn.dataset.trigger;
144
- if (!name) return;
145
- if (!window.confirm('Drop trigger "' + name + '" permanently?')) return;
146
- try {
147
- const data = await Api.del('/api/triggers/' + encodeURIComponent(name));
148
- UI.showToast(data.message || 'Trigger dropped.', 'success');
149
- window.location.reload();
150
- } catch (e) {
151
- UI.showError(e.message);
152
- }
153
- });
154
- });
155
- })();
1
+ /* Triggers page: create / drop triggers with a live SQL preview. */
2
+ (function () {
3
+ 'use strict';
4
+ const cfgEl = document.getElementById('triggers-config');
5
+ if (!cfgEl) return;
6
+
7
+ function escapeHtml(s) {
8
+ return (window.UI && UI.escapeHtml) ? UI.escapeHtml(s) : String(s == null ? '' : s);
9
+ }
10
+
11
+ function showError(el, msg) {
12
+ el.classList.remove('hidden');
13
+ el.innerHTML = '<div class="flex items-start gap-2.5 rounded-xl border border-error/40 bg-error/10 px-4 py-3 text-sm font-medium text-error"><span>' + escapeHtml(msg) + '</span></div>';
14
+ }
15
+
16
+ // ---- Editor gutter ------------------------------------------------------
17
+
18
+ const editor = document.getElementById('trigger-body');
19
+ const gutter = document.getElementById('trigger-gutter');
20
+ function updateGutter() {
21
+ if (!gutter || !editor) return;
22
+ const lines = editor.value.split('\n').length;
23
+ let html = '';
24
+ for (let i = 1; i <= lines; i++) html += i + '\n';
25
+ gutter.textContent = html;
26
+ gutter.scrollTop = editor.scrollTop;
27
+ }
28
+ if (editor && gutter) {
29
+ editor.addEventListener('scroll', () => { gutter.scrollTop = editor.scrollTop; });
30
+ editor.addEventListener('input', updateGutter);
31
+ updateGutter();
32
+ }
33
+
34
+ // ---- New trigger form ---------------------------------------------------
35
+
36
+ const newBtn = document.getElementById('new-trigger');
37
+ const panel = document.getElementById('new-trigger-panel');
38
+ const nameInput = document.getElementById('trigger-name');
39
+ const tableInput = document.getElementById('trigger-table');
40
+ const timingInput = document.getElementById('trigger-timing');
41
+ const eventInput = document.getElementById('trigger-event');
42
+ const whenInput = document.getElementById('trigger-when');
43
+ const bodyInput = document.getElementById('trigger-body');
44
+ const errEl = document.getElementById('trigger-error');
45
+ const createBtn = document.getElementById('create-trigger');
46
+ const cancelBtn = document.getElementById('cancel-trigger');
47
+ const preview = document.getElementById('trigger-preview');
48
+ const previewCode = document.getElementById('trigger-preview-code');
49
+ const previewHint = document.getElementById('trigger-preview-hint');
50
+ let previewTimer = null;
51
+
52
+ function currentEvent() {
53
+ return eventInput ? eventInput.value : 'INSERT';
54
+ }
55
+
56
+ function renderPreview() {
57
+ clearTimeout(previewTimer);
58
+ const name = (nameInput.value || '').trim();
59
+ const table = tableInput.value || '';
60
+ const event = currentEvent();
61
+ if (!name && !table && !(bodyInput.value || '').trim()) {
62
+ preview.classList.add('hidden');
63
+ previewCode.textContent = '';
64
+ if (previewHint) previewHint.classList.remove('hidden');
65
+ return;
66
+ }
67
+ previewTimer = setTimeout(async () => {
68
+ try {
69
+ const data = await Api.post('/api/triggers/generate', {
70
+ name,
71
+ table,
72
+ timing: timingInput.value,
73
+ event,
74
+ when: (whenInput.value || '').trim() || undefined,
75
+ body: bodyInput.value,
76
+ });
77
+ previewCode.textContent = data.sql;
78
+ preview.classList.remove('hidden');
79
+ if (previewHint) previewHint.classList.add('hidden');
80
+ } catch (e) {
81
+ preview.classList.add('hidden');
82
+ previewCode.textContent = '';
83
+ if (previewHint) previewHint.classList.remove('hidden');
84
+ }
85
+ }, 250);
86
+ }
87
+
88
+ if (newBtn && panel) {
89
+ newBtn.addEventListener('click', () => {
90
+ panel.classList.toggle('hidden');
91
+ if (!panel.classList.contains('hidden')) {
92
+ errEl.classList.add('hidden');
93
+ nameInput.focus();
94
+ renderPreview();
95
+ }
96
+ });
97
+ }
98
+ [nameInput, tableInput, timingInput, eventInput, whenInput, bodyInput].forEach((el) => {
99
+ if (el) el.addEventListener('input', renderPreview);
100
+ });
101
+
102
+ if (cancelBtn) {
103
+ cancelBtn.addEventListener('click', () => {
104
+ panel.classList.add('hidden');
105
+ errEl.classList.add('hidden');
106
+ });
107
+ }
108
+
109
+ if (createBtn) {
110
+ createBtn.addEventListener('click', async () => {
111
+ errEl.classList.add('hidden');
112
+ const name = (nameInput.value || '').trim();
113
+ const table = tableInput.value || '';
114
+ const body = (bodyInput.value || '').trim();
115
+ const event = currentEvent();
116
+ if (!name) return showError(errEl, 'Trigger name is required.');
117
+ if (!table) return showError(errEl, 'Select a table for the trigger.');
118
+ if (!body) return showError(errEl, 'Trigger body is required.');
119
+ createBtn.disabled = true;
120
+ try {
121
+ const data = await Api.post('/api/triggers', {
122
+ name,
123
+ table,
124
+ timing: timingInput.value,
125
+ event,
126
+ when: (whenInput.value || '').trim() || undefined,
127
+ body,
128
+ });
129
+ UI.showToast(data.message || 'Trigger created.', 'success');
130
+ window.location.reload();
131
+ } catch (e) {
132
+ showError(errEl, e.message);
133
+ } finally {
134
+ createBtn.disabled = false;
135
+ }
136
+ });
137
+ }
138
+
139
+ // ---- Drop trigger -------------------------------------------------------
140
+
141
+ document.querySelectorAll('.trigger-drop').forEach((btn) => {
142
+ btn.addEventListener('click', async () => {
143
+ const name = btn.dataset.trigger;
144
+ if (!name) return;
145
+ if (!window.confirm('Drop trigger "' + name + '" permanently?')) return;
146
+ try {
147
+ const data = await Api.del('/api/triggers/' + encodeURIComponent(name));
148
+ UI.showToast(data.message || 'Trigger dropped.', 'success');
149
+ window.location.reload();
150
+ } catch (e) {
151
+ UI.showError(e.message);
152
+ }
153
+ });
154
+ });
155
+ })();