@hotstaq/admin-panel 0.4.0 → 0.4.2
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/assets/css/freelight-panel.css +18 -3
- package/build/components/admin-add-panel.d.ts +32 -32
- package/build/components/admin-add-panel.d.ts.map +1 -1
- package/build/components/admin-add-panel.js +74 -69
- package/build/components/admin-add-panel.js.map +1 -1
- package/build-web/AdminPanelComponents.js +2 -2
- package/package.json +1 -1
- package/src/components/admin-add-panel.ts +81 -82
package/package.json
CHANGED
|
@@ -1,42 +1,43 @@
|
|
|
1
1
|
import { HotStaq, Hot, HotAPI, HotComponent, HotComponentOutput } from "hotstaq";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* <admin-edit hot-type="add"
|
|
6
|
-
*
|
|
4
|
+
* Self-contained inline add form. Replaces the modal opened by
|
|
5
|
+
* <admin-edit hot-type="add"> with a Bootstrap-collapse card that
|
|
6
|
+
* lives directly on the page — header carries the "+ Add" toggle,
|
|
7
|
+
* body holds the form fields. No cross-component DOM injection.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Place this above an <admin-card-table>; when the user clicks the
|
|
10
|
+
* header toggle, the form panel slides down. On Save, the paired
|
|
11
|
+
* table is asked to refresh via `attached_list`.
|
|
11
12
|
*
|
|
12
13
|
* Usage:
|
|
13
|
-
* <admin-add-panel name="bankAccountsAdd"
|
|
14
|
-
* hot-
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* }Ra>"
|
|
19
|
-
* hot-attached_list="bankAccountsList">
|
|
14
|
+
* <admin-add-panel name="bankAccountsAdd"
|
|
15
|
+
* hot-title="Add a bank account"
|
|
16
|
+
* hot-attached_list="bankAccountsList"
|
|
17
|
+
* hot-add_text="+ Add bank account"
|
|
18
|
+
* hot-button_title="Create"
|
|
19
|
+
* hot-onsave="<(values) => {...}Ra>">
|
|
20
20
|
* <admin-form-field hot-field="name" hot-label="Name" hot-required="1"
|
|
21
21
|
* hot-col="col-md-6"></admin-form-field>
|
|
22
|
-
*
|
|
22
|
+
* <admin-form-field hot-field="bankSyncAPIType" hot-label="Sync type"
|
|
23
|
+
* hot-control="select"
|
|
24
|
+
* hot-options="paypal_webhooks:PayPal Webhooks"
|
|
25
|
+
* hot-col="col-md-6"></admin-form-field>
|
|
23
26
|
* </admin-add-panel>
|
|
24
27
|
*/
|
|
25
28
|
export class AdminAddPanel extends HotComponent
|
|
26
29
|
{
|
|
27
|
-
/** Title shown
|
|
30
|
+
/** Title shown in the card header (next to the toggle button). */
|
|
28
31
|
title: string;
|
|
29
32
|
/** Submit button label. */
|
|
30
33
|
button_title: string;
|
|
31
|
-
/** Cancel button label. Empty
|
|
34
|
+
/** Cancel button label. Empty hides the cancel button. */
|
|
32
35
|
cancel_text: string;
|
|
33
|
-
/** Optional id of the
|
|
36
|
+
/** Optional id of the partner <admin-card-table>; refreshList() is called after a successful save. */
|
|
34
37
|
attached_list: string;
|
|
35
|
-
/**
|
|
36
|
-
add_place_here: string;
|
|
37
|
-
/** Text shown on the toggle button. */
|
|
38
|
+
/** Text shown on the header toggle button. */
|
|
38
39
|
add_text: string;
|
|
39
|
-
/**
|
|
40
|
+
/** "1" / "true" → panel starts expanded. */
|
|
40
41
|
start_open: string;
|
|
41
42
|
/** What to run when the user clicks Save. Receives a values object built from hot-field inputs. Return false to keep the panel open. */
|
|
42
43
|
onsave: (values: any) => Promise<boolean | void>;
|
|
@@ -53,33 +54,52 @@ export class AdminAddPanel extends HotComponent
|
|
|
53
54
|
this.button_title = "Save";
|
|
54
55
|
this.cancel_text = "Cancel";
|
|
55
56
|
this.attached_list = "";
|
|
56
|
-
this.add_place_here = "";
|
|
57
57
|
this.add_text = "+ Add";
|
|
58
58
|
this.start_open = "0";
|
|
59
59
|
this.onsave = null;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
63
|
+
* Wire submit + cancel handlers after the DOM is in place.
|
|
64
|
+
* Bootstrap's data-bs-toggle handles open/close automatically.
|
|
65
|
+
*
|
|
66
|
+
* Also relocates any child elements (admin-form-fields, etc.) that
|
|
67
|
+
* the framework appended to the card root into the collapse panel's
|
|
68
|
+
* form-row. Without this, children would render OUTSIDE the
|
|
69
|
+
* collapsible body (siblings of the card-header and the collapse
|
|
70
|
+
* div), visible on the page even when the panel is collapsed.
|
|
66
71
|
*/
|
|
67
72
|
onPostPlace (parentHtmlElement: HTMLElement, htmlElement: HTMLElement): HTMLElement
|
|
68
73
|
{
|
|
69
74
|
const self = this;
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
75
|
+
const root = document.getElementById (this.name);
|
|
76
|
+
if (root == null)
|
|
72
77
|
return (null);
|
|
73
78
|
|
|
74
|
-
const submitBtn =
|
|
75
|
-
const cancelBtn =
|
|
79
|
+
const submitBtn = root.querySelector (".fl-add-panel-submit") as HTMLButtonElement | null;
|
|
80
|
+
const cancelBtn = root.querySelector (".fl-add-panel-cancel") as HTMLButtonElement | null;
|
|
81
|
+
|
|
82
|
+
// Auto-relocate stray children into the form-row. The framework
|
|
83
|
+
// appends children that lack `hot-place-parent` directly under
|
|
84
|
+
// compHtmlElement2 (the card root). Move them inside the form.
|
|
85
|
+
const row = root.querySelector (".fl-add-panel-form .row") as HTMLElement | null;
|
|
86
|
+
const collapse = document.getElementById (this.panelId);
|
|
87
|
+
const header = root.querySelector (":scope > .card-header") as HTMLElement | null;
|
|
88
|
+
if (row != null)
|
|
89
|
+
{
|
|
90
|
+
Array.from (root.children).forEach ((child) =>
|
|
91
|
+
{
|
|
92
|
+
if (child === header || child === collapse) return;
|
|
93
|
+
row.appendChild (child as Element);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
76
96
|
|
|
77
97
|
if (submitBtn != null)
|
|
78
98
|
{
|
|
79
99
|
submitBtn.addEventListener ("click", async (e) =>
|
|
80
100
|
{
|
|
81
101
|
e.preventDefault ();
|
|
82
|
-
const values = self.collectFieldValues (
|
|
102
|
+
const values = self.collectFieldValues (root);
|
|
83
103
|
submitBtn.disabled = true;
|
|
84
104
|
try
|
|
85
105
|
{
|
|
@@ -89,7 +109,7 @@ export class AdminAddPanel extends HotComponent
|
|
|
89
109
|
|
|
90
110
|
if (keepOpen === false || keepOpen == null)
|
|
91
111
|
{
|
|
92
|
-
self.resetFields (
|
|
112
|
+
self.resetFields (root);
|
|
93
113
|
self.collapsePanel ();
|
|
94
114
|
self.refreshAttachedList ();
|
|
95
115
|
}
|
|
@@ -110,7 +130,7 @@ export class AdminAddPanel extends HotComponent
|
|
|
110
130
|
cancelBtn.addEventListener ("click", (e) =>
|
|
111
131
|
{
|
|
112
132
|
e.preventDefault ();
|
|
113
|
-
self.resetFields (
|
|
133
|
+
self.resetFields (root);
|
|
114
134
|
self.collapsePanel ();
|
|
115
135
|
});
|
|
116
136
|
}
|
|
@@ -118,11 +138,10 @@ export class AdminAddPanel extends HotComponent
|
|
|
118
138
|
return (null);
|
|
119
139
|
}
|
|
120
140
|
|
|
121
|
-
|
|
122
|
-
protected collectFieldValues (panel: HTMLElement): any
|
|
141
|
+
protected collectFieldValues (root: HTMLElement): any
|
|
123
142
|
{
|
|
124
143
|
const out: any = {};
|
|
125
|
-
const nodes =
|
|
144
|
+
const nodes = root.querySelectorAll ("[hot-field]");
|
|
126
145
|
for (let i = 0; i < nodes.length; i++)
|
|
127
146
|
{
|
|
128
147
|
const el = nodes[i] as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
@@ -139,9 +158,9 @@ export class AdminAddPanel extends HotComponent
|
|
|
139
158
|
return (out);
|
|
140
159
|
}
|
|
141
160
|
|
|
142
|
-
protected resetFields (
|
|
161
|
+
protected resetFields (root: HTMLElement): void
|
|
143
162
|
{
|
|
144
|
-
const nodes =
|
|
163
|
+
const nodes = root.querySelectorAll ("[hot-field]");
|
|
145
164
|
for (let i = 0; i < nodes.length; i++)
|
|
146
165
|
{
|
|
147
166
|
const el = nodes[i] as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
@@ -155,19 +174,11 @@ export class AdminAddPanel extends HotComponent
|
|
|
155
174
|
{
|
|
156
175
|
const panel = document.getElementById (this.panelId);
|
|
157
176
|
if (panel == null) return;
|
|
158
|
-
// Bootstrap collapse hide — works without importing Bootstrap JS
|
|
159
|
-
// directly by toggling the .show class and aria-expanded on any
|
|
160
|
-
// trigger pointed at us.
|
|
161
177
|
panel.classList.remove ("show");
|
|
162
178
|
const triggers = document.querySelectorAll (`[data-bs-target="#${this.panelId}"]`);
|
|
163
179
|
triggers.forEach (t => t.setAttribute ("aria-expanded", "false"));
|
|
164
180
|
}
|
|
165
181
|
|
|
166
|
-
/**
|
|
167
|
-
* Best-effort refresh of the paired <admin-card-table>. The table
|
|
168
|
-
* exposes a `refreshList` method on the rendered element when its
|
|
169
|
-
* data is loaded; calling it re-fetches without a page reload.
|
|
170
|
-
*/
|
|
171
182
|
protected refreshAttachedList (): void
|
|
172
183
|
{
|
|
173
184
|
if (this.attached_list === "") return;
|
|
@@ -185,48 +196,36 @@ export class AdminAddPanel extends HotComponent
|
|
|
185
196
|
this.formId = `${this.name}Form`;
|
|
186
197
|
|
|
187
198
|
const showClass = (this.start_open === "1" || this.start_open === "true") ? " show" : "";
|
|
188
|
-
const
|
|
199
|
+
const ariaExp = showClass ? "true" : "false";
|
|
200
|
+
const titleHtml = this.title ? `<strong class="fl-add-panel-title">${this.title}</strong>` : `<span></span>`;
|
|
189
201
|
const cancelHtml = this.cancel_text
|
|
190
202
|
? `<button type="button" class="btn btn-sm btn-link text-muted fl-add-panel-cancel">${this.cancel_text}</button>`
|
|
191
203
|
: "";
|
|
192
204
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
205
|
+
// Single self-contained card. Header has the toggle, body is the
|
|
206
|
+
// collapse panel containing the form. Bootstrap's data-bs-toggle
|
|
207
|
+
// drives the open/close — no JS wiring needed for that.
|
|
208
|
+
return (`
|
|
209
|
+
<div id="${this.name}" class="card fl-add-panel mb-3">
|
|
210
|
+
<div class="card-header d-flex justify-content-between align-items-center">
|
|
196
211
|
${titleHtml}
|
|
197
|
-
<
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
</div>
|
|
201
|
-
<div class="d-flex justify-content-end gap-2 mt-3">
|
|
202
|
-
${cancelHtml}
|
|
203
|
-
<button type="submit" class="btn btn-sm btn-success fl-add-panel-submit">${this.button_title}</button>
|
|
204
|
-
</div>
|
|
205
|
-
</form>
|
|
212
|
+
<button type="button" class="btn btn-sm btn-primary fl-add-panel-toggle"
|
|
213
|
+
data-bs-toggle="collapse" data-bs-target="#${this.panelId}"
|
|
214
|
+
aria-expanded="${ariaExp}" aria-controls="${this.panelId}">${this.add_text}</button>
|
|
206
215
|
</div>
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
else if (this.add_place_here !== "")
|
|
223
|
-
{
|
|
224
|
-
outputs.push ({
|
|
225
|
-
html: toggleBtn,
|
|
226
|
-
documentSelector: `hot-place-here[name="${this.add_place_here}"]`
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return (outputs);
|
|
216
|
+
<div id="${this.panelId}" class="collapse fl-add-panel-body${showClass}">
|
|
217
|
+
<div class="card-body border-top">
|
|
218
|
+
<form id="${this.formId}" class="fl-add-panel-form">
|
|
219
|
+
<div class="row g-2 align-items-end">
|
|
220
|
+
<hot-place-here name="panelBody"></hot-place-here>
|
|
221
|
+
</div>
|
|
222
|
+
<div class="d-flex justify-content-end gap-2 mt-3">
|
|
223
|
+
${cancelHtml}
|
|
224
|
+
<button type="submit" class="btn btn-sm btn-success fl-add-panel-submit">${this.button_title}</button>
|
|
225
|
+
</div>
|
|
226
|
+
</form>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</div>`);
|
|
231
230
|
}
|
|
232
231
|
}
|