@saltcorn/markup 0.6.2-beta.2 → 0.6.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/dist/builder.d.ts +18 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +57 -0
- package/dist/builder.js.map +1 -0
- package/dist/emergency_layout.d.ts +6 -0
- package/dist/emergency_layout.d.ts.map +1 -0
- package/dist/emergency_layout.js +38 -0
- package/dist/emergency_layout.js.map +1 -0
- package/dist/form.d.ts +12 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +372 -0
- package/dist/form.js.map +1 -0
- package/dist/helpers.d.ts +58 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +169 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +158 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +22 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +338 -0
- package/dist/layout.js.map +1 -0
- package/dist/layout_utils.d.ts +21 -0
- package/dist/layout_utils.d.ts.map +1 -0
- package/dist/layout_utils.js +272 -0
- package/dist/layout_utils.js.map +1 -0
- package/dist/mktag.d.ts +12 -0
- package/dist/mktag.d.ts.map +1 -0
- package/dist/mktag.js +100 -0
- package/dist/mktag.js.map +1 -0
- package/dist/table.d.ts +22 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/table.js +51 -0
- package/dist/table.js.map +1 -0
- package/dist/tabs.d.ts +7 -0
- package/dist/tabs.d.ts.map +1 -0
- package/dist/tabs.js +34 -0
- package/dist/tabs.js.map +1 -0
- package/dist/tags.d.ts +17 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/tags.js +71 -0
- package/dist/tags.js.map +1 -0
- package/dist/tsconfig.ref.tsbuildinfo +1 -0
- package/package.json +25 -6
- package/builder.js +0 -101
- package/emergency_layout.js +0 -54
- package/form.js +0 -603
- package/form.test.js +0 -98
- package/helpers.js +0 -268
- package/index.js +0 -226
- package/layout.js +0 -590
- package/layout.test.js +0 -39
- package/layout_utils.js +0 -394
- package/markup.test.js +0 -104
- package/mktag.js +0 -105
- package/table.js +0 -115
- package/tabs.js +0 -54
- package/tags.js +0 -56
package/form.test.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
const { a, input, div, ul, text, text_attr } = require("./tags");
|
|
2
|
-
const { renderForm } = require(".");
|
|
3
|
-
|
|
4
|
-
class Form {
|
|
5
|
-
constructor(o) {
|
|
6
|
-
Object.entries(o).forEach(([k, v]) => {
|
|
7
|
-
this[k] = v;
|
|
8
|
-
});
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const nolines = (s) => s.split("\n").join("");
|
|
13
|
-
|
|
14
|
-
describe("form render", () => {
|
|
15
|
-
it("renders a simple form", () => {
|
|
16
|
-
const form = new Form({
|
|
17
|
-
action: "/",
|
|
18
|
-
fields: [
|
|
19
|
-
{
|
|
20
|
-
name: "name",
|
|
21
|
-
label: "Name",
|
|
22
|
-
input_type: "text",
|
|
23
|
-
form_name: "name",
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
});
|
|
27
|
-
const want = `<form action="/" class="form-namespace " method="post">
|
|
28
|
-
<input type="hidden" name="_csrf" value=""><div class="form-group">
|
|
29
|
-
<div><label for="inputname">Name</label></div>
|
|
30
|
-
<div><input type="text" class="form-control " data-fieldname="name" name="name" id="inputname">
|
|
31
|
-
</div></div><div class="form-group row">
|
|
32
|
-
<div class="col-sm-12">
|
|
33
|
-
<button type="submit" class="btn btn-primary">Save</button>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
</form>`;
|
|
37
|
-
expect(nolines(renderForm(form, ""))).toBe(nolines(want));
|
|
38
|
-
});
|
|
39
|
-
it("renders a form with layout", () => {
|
|
40
|
-
const form = new Form({
|
|
41
|
-
action: "/",
|
|
42
|
-
fields: [
|
|
43
|
-
{
|
|
44
|
-
name: "name",
|
|
45
|
-
label: "Name",
|
|
46
|
-
input_type: "text",
|
|
47
|
-
form_name: "name",
|
|
48
|
-
},
|
|
49
|
-
],
|
|
50
|
-
values: {},
|
|
51
|
-
errors: {},
|
|
52
|
-
layout: {
|
|
53
|
-
above: [
|
|
54
|
-
{
|
|
55
|
-
type: "field",
|
|
56
|
-
block: false,
|
|
57
|
-
fieldview: "edit",
|
|
58
|
-
textStyle: "h2",
|
|
59
|
-
field_name: "name",
|
|
60
|
-
},
|
|
61
|
-
{ type: "line_break" },
|
|
62
|
-
],
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
const want = `<form action="/" class="form-namespace " method="post">
|
|
66
|
-
<input type="hidden" name="_csrf" value="">
|
|
67
|
-
<h2>
|
|
68
|
-
<input type="text" class="form-control " data-fieldname="name" name="name" id="inputname">
|
|
69
|
-
</h2><br /></form>`;
|
|
70
|
-
expect(nolines(renderForm(form, ""))).toBe(nolines(want));
|
|
71
|
-
});
|
|
72
|
-
it("renders a simple form with errors", () => {
|
|
73
|
-
const form = new Form({
|
|
74
|
-
action: "/",
|
|
75
|
-
errors: { name: "Not a foo" },
|
|
76
|
-
values: { name: "Bar" },
|
|
77
|
-
fields: [
|
|
78
|
-
{
|
|
79
|
-
name: "name",
|
|
80
|
-
label: "Name",
|
|
81
|
-
input_type: "text",
|
|
82
|
-
form_name: "name",
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
});
|
|
86
|
-
const want = `<form action="/" class="form-namespace " method="post">
|
|
87
|
-
<input type="hidden" name="_csrf" value=""><div class="form-group">
|
|
88
|
-
<div><label for="inputname">Name</label></div>
|
|
89
|
-
<div><input type="text" class="form-control is-invalid " data-fieldname="name" name="name" id="inputname" value="Bar"><div>Not a foo</div>
|
|
90
|
-
</div></div><div class="form-group row">
|
|
91
|
-
<div class="col-sm-12">
|
|
92
|
-
<button type="submit" class="btn btn-primary">Save</button>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
</form>`;
|
|
96
|
-
expect(nolines(renderForm(form, ""))).toBe(nolines(want));
|
|
97
|
-
});
|
|
98
|
-
});
|
package/helpers.js
DELETED
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @category saltcorn-markup
|
|
3
|
-
* @module helpers
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const {
|
|
7
|
-
a,
|
|
8
|
-
text,
|
|
9
|
-
div,
|
|
10
|
-
input,
|
|
11
|
-
text_attr,
|
|
12
|
-
ul,
|
|
13
|
-
li,
|
|
14
|
-
span,
|
|
15
|
-
label,
|
|
16
|
-
} = require("./tags");
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* checks if x is defined
|
|
20
|
-
* @param {*} x
|
|
21
|
-
* @returns {boolean}
|
|
22
|
-
*/
|
|
23
|
-
const isdef = (x) => typeof x !== "undefined";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @param {object|string} v
|
|
27
|
-
* @param {object} hdr
|
|
28
|
-
* @param {boolean} force_required
|
|
29
|
-
* @param {string} neutral_label
|
|
30
|
-
* @returns {string}
|
|
31
|
-
*/
|
|
32
|
-
const select_options = (v, hdr, force_required, neutral_label = "") => {
|
|
33
|
-
const options0 = hdr.options || [];
|
|
34
|
-
const options1 = force_required
|
|
35
|
-
? options0.filter((o) => (typeof o === "string" ? o : o.value))
|
|
36
|
-
: options0;
|
|
37
|
-
const options = options1.map((o) =>
|
|
38
|
-
o.value === "" ? { ...o, label: neutral_label } : o
|
|
39
|
-
);
|
|
40
|
-
const selected = typeof v === "object" ? (v ? v[hdr.name] : undefined) : v;
|
|
41
|
-
const isSelected = (value) =>
|
|
42
|
-
!selected
|
|
43
|
-
? false
|
|
44
|
-
: selected.length
|
|
45
|
-
? selected.includes(value)
|
|
46
|
-
: value === selected;
|
|
47
|
-
return options
|
|
48
|
-
.map((o) => {
|
|
49
|
-
const label = typeof o === "string" ? o : o.label;
|
|
50
|
-
const value = typeof o === "string" ? o : o.value;
|
|
51
|
-
return `<option value="${text_attr(value)}"${
|
|
52
|
-
isSelected(value) ? " selected" : ""
|
|
53
|
-
}>${text(label)}</option>`;
|
|
54
|
-
})
|
|
55
|
-
.join("");
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
*
|
|
60
|
-
* @param {object} opts
|
|
61
|
-
* @param {string} opts.name
|
|
62
|
-
* @param {object} [opts.options]
|
|
63
|
-
* @param {string} opts.value
|
|
64
|
-
* @param {object} opts.inline
|
|
65
|
-
* @param {string} opts.form_name
|
|
66
|
-
* @param {...*} opts.rest
|
|
67
|
-
* @returns {string}
|
|
68
|
-
*/
|
|
69
|
-
const radio_group = ({
|
|
70
|
-
name,
|
|
71
|
-
options,
|
|
72
|
-
value,
|
|
73
|
-
inline,
|
|
74
|
-
form_name,
|
|
75
|
-
onChange,
|
|
76
|
-
...rest
|
|
77
|
-
}) =>
|
|
78
|
-
div(
|
|
79
|
-
(options || [])
|
|
80
|
-
.filter((o) => (typeof o === "string" ? o : o.value))
|
|
81
|
-
.map((o, ix) => {
|
|
82
|
-
const myvalue = typeof o === "string" ? o : o.value;
|
|
83
|
-
const id = `input${text_attr(name)}${ix}`;
|
|
84
|
-
return div(
|
|
85
|
-
{ class: ["form-check", inline && "form-check-inline"] },
|
|
86
|
-
input({
|
|
87
|
-
class: ["form-check-input", rest.class],
|
|
88
|
-
type: "radio",
|
|
89
|
-
name,
|
|
90
|
-
onChange,
|
|
91
|
-
"data-fieldname": form_name,
|
|
92
|
-
id,
|
|
93
|
-
value: text_attr(myvalue),
|
|
94
|
-
checked: myvalue === value,
|
|
95
|
-
}),
|
|
96
|
-
label(
|
|
97
|
-
{ class: "form-check-label", for: id },
|
|
98
|
-
typeof o === "string" ? o : o.label
|
|
99
|
-
)
|
|
100
|
-
);
|
|
101
|
-
})
|
|
102
|
-
.join("")
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const checkbox_group = ({
|
|
106
|
-
name,
|
|
107
|
-
options,
|
|
108
|
-
value,
|
|
109
|
-
inline,
|
|
110
|
-
form_name,
|
|
111
|
-
onChange,
|
|
112
|
-
...rest
|
|
113
|
-
}) =>
|
|
114
|
-
div(
|
|
115
|
-
(options || [])
|
|
116
|
-
.filter((o) => (typeof o === "string" ? o : o.value))
|
|
117
|
-
.map((o, ix) => {
|
|
118
|
-
const myvalue = typeof o === "string" ? o : o.value;
|
|
119
|
-
const id = `input${text_attr(name)}${ix}`;
|
|
120
|
-
return div(
|
|
121
|
-
{ class: ["form-check", inline && "form-check-inline"] },
|
|
122
|
-
input({
|
|
123
|
-
class: ["form-check-input", rest.class],
|
|
124
|
-
type: "checkbox",
|
|
125
|
-
name,
|
|
126
|
-
onChange: `check_state_field(this)`,
|
|
127
|
-
"data-fieldname": form_name,
|
|
128
|
-
id,
|
|
129
|
-
value: text_attr(myvalue),
|
|
130
|
-
checked: Array.isArray(value)
|
|
131
|
-
? value.includes(myvalue)
|
|
132
|
-
: myvalue === value,
|
|
133
|
-
}),
|
|
134
|
-
label(
|
|
135
|
-
{ class: "form-check-label", for: id },
|
|
136
|
-
typeof o === "string" ? o : o.label
|
|
137
|
-
)
|
|
138
|
-
);
|
|
139
|
-
})
|
|
140
|
-
.join("")
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* @param {object} opts
|
|
145
|
-
* @param {number} opts.current_page
|
|
146
|
-
* @param {number} opts.pages
|
|
147
|
-
* @param {function} opts.get_page_link
|
|
148
|
-
* @param {boolean} opts.trailing_ellipsis
|
|
149
|
-
* @returns {string}
|
|
150
|
-
*/
|
|
151
|
-
const pagination = ({
|
|
152
|
-
current_page,
|
|
153
|
-
pages,
|
|
154
|
-
get_page_link,
|
|
155
|
-
trailing_ellipsis,
|
|
156
|
-
}) => {
|
|
157
|
-
const from = Math.max(1, current_page - 3);
|
|
158
|
-
const to = Math.min(pages, current_page + 3);
|
|
159
|
-
var lis = [];
|
|
160
|
-
if (from > 1) {
|
|
161
|
-
lis.push(
|
|
162
|
-
li(
|
|
163
|
-
{ class: `page-item` },
|
|
164
|
-
a({ class: "page-link", href: get_page_link(1) }, 1)
|
|
165
|
-
)
|
|
166
|
-
);
|
|
167
|
-
lis.push(li({ class: `page-item` }, span({ class: "page-link" }, "...")));
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
for (let index = from; index <= to; index++) {
|
|
171
|
-
lis.push(
|
|
172
|
-
li(
|
|
173
|
-
{ class: ["page-item", index === current_page && "active"] },
|
|
174
|
-
a({ class: "page-link", href: get_page_link(index) }, index)
|
|
175
|
-
)
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
if (to < pages) {
|
|
179
|
-
lis.push(li({ class: `page-item` }, span({ class: "page-link" }, "...")));
|
|
180
|
-
lis.push(
|
|
181
|
-
li(
|
|
182
|
-
{ class: `page-item` },
|
|
183
|
-
a({ class: "page-link", href: get_page_link(pages) }, pages)
|
|
184
|
-
)
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
if (trailing_ellipsis)
|
|
188
|
-
lis.push(li({ class: `page-item` }, span({ class: "page-link" }, "...")));
|
|
189
|
-
return ul({ class: "pagination" }, lis);
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* @param {string} name
|
|
194
|
-
* @param {object} v
|
|
195
|
-
* @param {object} param2
|
|
196
|
-
* @returns {string}
|
|
197
|
-
*/
|
|
198
|
-
const search_bar = (
|
|
199
|
-
name,
|
|
200
|
-
v,
|
|
201
|
-
{ placeHolder, has_dropdown, contents, badges, stateField, onClick } = {}
|
|
202
|
-
) => {
|
|
203
|
-
const rndid = Math.floor(Math.random() * 16777215).toString(16);
|
|
204
|
-
const clickHandler = stateField
|
|
205
|
-
? `(function(v){v ? set_state_field('${stateField}', v):unset_state_field('${stateField}');})($('input.search-bar').val())`
|
|
206
|
-
: onClick || "";
|
|
207
|
-
return `<div class="input-group search-bar">
|
|
208
|
-
<div class="input-group-prepend">
|
|
209
|
-
<button class="btn btn-outline-secondary search-bar" ${
|
|
210
|
-
clickHandler ? `onClick="${clickHandler}"` : ""
|
|
211
|
-
} type="submit" id="button-search-submit">
|
|
212
|
-
<i class="fas fa-search"></i>
|
|
213
|
-
</button>
|
|
214
|
-
</div>
|
|
215
|
-
<input type="search" class="form-control search-bar ${
|
|
216
|
-
(badges && badges.length > 0) || has_dropdown ? "br-none" : ""
|
|
217
|
-
}" placeholder="${placeHolder || "Search for..."}"
|
|
218
|
-
}"
|
|
219
|
-
}"
|
|
220
|
-
id="input${text_attr(name)}" name="${name}"
|
|
221
|
-
${
|
|
222
|
-
clickHandler
|
|
223
|
-
? `onsearch="${clickHandler}" onChange="${clickHandler}"`
|
|
224
|
-
: ""
|
|
225
|
-
}
|
|
226
|
-
aria-label="Search" aria-describedby="button-search-submit" ${
|
|
227
|
-
v ? `value="${text_attr(v)}"` : ""
|
|
228
|
-
}>
|
|
229
|
-
<div class="input-group-append">
|
|
230
|
-
${
|
|
231
|
-
badges && badges.length > 0
|
|
232
|
-
? `<div class="input-group-text">${badges
|
|
233
|
-
.map(
|
|
234
|
-
(b) =>
|
|
235
|
-
`<span class="badge badge-primary">${b.text}${
|
|
236
|
-
b.onclick
|
|
237
|
-
? `<a href="javascript:${b.onclick}"><i class="ml-1 fas fa-lg fa-times"></i></a> `
|
|
238
|
-
: ""
|
|
239
|
-
}</span>`
|
|
240
|
-
)
|
|
241
|
-
.join(" ")}
|
|
242
|
-
</div>`
|
|
243
|
-
: ""
|
|
244
|
-
}
|
|
245
|
-
${
|
|
246
|
-
has_dropdown
|
|
247
|
-
? `<button class="btn btn-outline-secondary dropdown-toggle search-bar" id="dd${rndid}" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" onclick="align_dropdown('${rndid}')"></button>`
|
|
248
|
-
: ""
|
|
249
|
-
}
|
|
250
|
-
${
|
|
251
|
-
has_dropdown
|
|
252
|
-
? `<div class="dropdown-menu search-bar p-2" id="dm${rndid}" aria-labelledby="dd${rndid}">
|
|
253
|
-
${contents}
|
|
254
|
-
</div>`
|
|
255
|
-
: ""
|
|
256
|
-
}
|
|
257
|
-
</div>
|
|
258
|
-
</div>`;
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
module.exports = {
|
|
262
|
-
isdef,
|
|
263
|
-
select_options,
|
|
264
|
-
search_bar,
|
|
265
|
-
pagination,
|
|
266
|
-
radio_group,
|
|
267
|
-
checkbox_group,
|
|
268
|
-
};
|
package/index.js
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @category saltcorn-markup
|
|
3
|
-
* @module saltcorn-markup/index
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* All files in the saltcorn-markup package.
|
|
8
|
-
* @namespace saltcorn-markup_overview
|
|
9
|
-
* @property {module:builder} builder
|
|
10
|
-
* @property {module:emergency_layout} emergency_layout
|
|
11
|
-
* @property {module:form} from
|
|
12
|
-
* @property {module:helpers} helpers
|
|
13
|
-
* @property {module:layout_utils} layout_utils
|
|
14
|
-
* @property {module:layout} layout
|
|
15
|
-
* @property {module:mktag} mktag
|
|
16
|
-
* @property {module:table} table
|
|
17
|
-
* @property {module:tabs} tabs
|
|
18
|
-
* @category saltcorn-markup
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
const renderForm = require("./form");
|
|
22
|
-
const renderBuilder = require("./builder");
|
|
23
|
-
const mkTable = require("./table");
|
|
24
|
-
const tabs = require("./tabs");
|
|
25
|
-
const { a, text, div, button, time } = require("./tags");
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {string} href
|
|
29
|
-
* @param {string} s
|
|
30
|
-
* @returns {string}
|
|
31
|
-
*/
|
|
32
|
-
const link = (href, s) => a({ href: text(href) }, text(s));
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @param {string} href
|
|
36
|
-
* @param {string} s
|
|
37
|
-
* @param {string} csrfToken
|
|
38
|
-
* @param {object} opts
|
|
39
|
-
* @param {string} [opts.btnClass = "btn-primary"]
|
|
40
|
-
* @param {string} [opts.onClick]
|
|
41
|
-
* @param {string} [opts.small]
|
|
42
|
-
* @param {string} [opts.style]
|
|
43
|
-
* @param {*} opts.ajax
|
|
44
|
-
* @param {string} opts.reload_on_done
|
|
45
|
-
* @param {string} opts.reload_delay
|
|
46
|
-
* @param {string} [opts.klass = "btn-primary"]
|
|
47
|
-
* @param {string} [opts.formClass]
|
|
48
|
-
* @param {string} opts.spinner
|
|
49
|
-
* @param {object} opts.req
|
|
50
|
-
* @param {boolean} opts.confirm
|
|
51
|
-
* @param {string} opts.icon
|
|
52
|
-
* @returns {string}
|
|
53
|
-
*/
|
|
54
|
-
const post_btn = (
|
|
55
|
-
href,
|
|
56
|
-
s,
|
|
57
|
-
csrfToken,
|
|
58
|
-
{
|
|
59
|
-
btnClass = "btn-primary",
|
|
60
|
-
onClick,
|
|
61
|
-
small,
|
|
62
|
-
style,
|
|
63
|
-
ajax,
|
|
64
|
-
reload_on_done,
|
|
65
|
-
reload_delay,
|
|
66
|
-
klass = "",
|
|
67
|
-
formClass,
|
|
68
|
-
spinner,
|
|
69
|
-
req,
|
|
70
|
-
confirm,
|
|
71
|
-
icon,
|
|
72
|
-
} = {}
|
|
73
|
-
) =>
|
|
74
|
-
`<form action="${text(href)}" method="post"${
|
|
75
|
-
formClass ? `class="${formClass}"` : ""
|
|
76
|
-
}>
|
|
77
|
-
<input type="hidden" name="_csrf" value="${csrfToken}">
|
|
78
|
-
<button ${ajax ? 'type="button"' : 'type="submit"'} ${
|
|
79
|
-
onClick
|
|
80
|
-
? `onclick="${spinner ? "press_store_button(this);" : ""}${onClick}"`
|
|
81
|
-
: ajax && confirm
|
|
82
|
-
? `onclick="if(confirm('${req.__("Are you sure?")}')) {${
|
|
83
|
-
spinner ? "press_store_button(this);" : ""
|
|
84
|
-
}ajax_post_btn(this, ${reload_on_done}, ${reload_delay})}"`
|
|
85
|
-
: ajax
|
|
86
|
-
? `onclick="${
|
|
87
|
-
spinner ? "press_store_button(this);" : ""
|
|
88
|
-
}ajax_post_btn(this, ${reload_on_done}, ${reload_delay})"`
|
|
89
|
-
: confirm
|
|
90
|
-
? `onclick="return confirm('${req.__("Are you sure?")}')"`
|
|
91
|
-
: ""
|
|
92
|
-
} class="${klass} btn ${small ? "btn-sm" : ""} ${btnClass}"${
|
|
93
|
-
style ? ` style="${style}"` : ""
|
|
94
|
-
}>${icon ? `<i class="${icon}"></i> ` : ""}${s}</button></form>`;
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* UI Form for Delete Item confirmation
|
|
98
|
-
* @param {string} href - href
|
|
99
|
-
* @param {string} req - Request
|
|
100
|
-
* @param {string} what - Item
|
|
101
|
-
* @returns {string} return html form
|
|
102
|
-
*/
|
|
103
|
-
const post_delete_btn = (href, req, what) =>
|
|
104
|
-
`<form action="${text(href)}" method="post" >
|
|
105
|
-
<input type="hidden" name="_csrf" value="${req.csrfToken()}">
|
|
106
|
-
<button type="submit" class="btn btn-danger btn-sm"
|
|
107
|
-
onclick="return confirm('${
|
|
108
|
-
what
|
|
109
|
-
? req.__("Are you sure you want to delete %s?", what)
|
|
110
|
-
: req.__("Are you sure?")
|
|
111
|
-
}')" />
|
|
112
|
-
<i class="fas fa-trash-alt"></i>
|
|
113
|
-
</button>
|
|
114
|
-
</form>`;
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* @param {string} href
|
|
118
|
-
* @param {string} s
|
|
119
|
-
* @param {object} req
|
|
120
|
-
* @param {boolean} confirm
|
|
121
|
-
* @param {string} what
|
|
122
|
-
* @returns {string}
|
|
123
|
-
*/
|
|
124
|
-
const post_dropdown_item = (href, s, req, confirm, what) => {
|
|
125
|
-
const id = href.split("/").join("");
|
|
126
|
-
return `<a class="dropdown-item" onclick="${
|
|
127
|
-
confirm
|
|
128
|
-
? `if(confirm('${
|
|
129
|
-
what
|
|
130
|
-
? req.__("Are you sure you want to delete %s?", what)
|
|
131
|
-
: req.__("Are you sure?")
|
|
132
|
-
}')) `
|
|
133
|
-
: ""
|
|
134
|
-
}$('#${id}').submit()">${s}</a>
|
|
135
|
-
<form id="${id}" action="${text(href)}" method="post">
|
|
136
|
-
<input type="hidden" name="_csrf" value="${req.csrfToken()}">
|
|
137
|
-
</form>`;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {string} id
|
|
142
|
-
* @param {*} elems
|
|
143
|
-
* @returns {div}
|
|
144
|
-
*/
|
|
145
|
-
const settingsDropdown = (id, elems) =>
|
|
146
|
-
div(
|
|
147
|
-
{ class: "dropdown" },
|
|
148
|
-
button(
|
|
149
|
-
{
|
|
150
|
-
class: "btn btn-sm btn-outline-secondary",
|
|
151
|
-
"data-boundary": "viewport",
|
|
152
|
-
type: "button",
|
|
153
|
-
id,
|
|
154
|
-
"data-toggle": "dropdown",
|
|
155
|
-
"aria-haspopup": "true",
|
|
156
|
-
"aria-expanded": "false",
|
|
157
|
-
},
|
|
158
|
-
'<i class="fas fa-ellipsis-h"></i>'
|
|
159
|
-
),
|
|
160
|
-
div(
|
|
161
|
-
{
|
|
162
|
-
class: "dropdown-menu dropdown-menu-right",
|
|
163
|
-
"aria-labelledby": id,
|
|
164
|
-
},
|
|
165
|
-
elems
|
|
166
|
-
)
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* @param {Date} date
|
|
171
|
-
* @param {object} opts
|
|
172
|
-
* @param {string} [opts.hour = "2-digit"]
|
|
173
|
-
* @param {string} [opts.minute = "2-digit"]
|
|
174
|
-
* @returns {string}
|
|
175
|
-
*/
|
|
176
|
-
const localeTime = (date, options = { hour: "2-digit", minute: "2-digit" }) =>
|
|
177
|
-
time(
|
|
178
|
-
{
|
|
179
|
-
datetime: date.toISOString(),
|
|
180
|
-
"locale-time-options": encodeURIComponent(JSON.stringify(options)),
|
|
181
|
-
},
|
|
182
|
-
date.toLocaleTimeString("en", options)
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* @param {Date} date
|
|
187
|
-
* @param {object} [options ={}]
|
|
188
|
-
* @returns {string}
|
|
189
|
-
*/
|
|
190
|
-
const localeDateTime = (date, options = {}) =>
|
|
191
|
-
time(
|
|
192
|
-
{
|
|
193
|
-
datetime: date.toISOString(),
|
|
194
|
-
"locale-options": encodeURIComponent(JSON.stringify(options)),
|
|
195
|
-
},
|
|
196
|
-
date.toLocaleString("en", options)
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* @param {Date} date
|
|
201
|
-
* @param {object} [options = {}]
|
|
202
|
-
* @returns {string}
|
|
203
|
-
*/
|
|
204
|
-
const localeDate = (date, options = {}) =>
|
|
205
|
-
time(
|
|
206
|
-
{
|
|
207
|
-
datetime: date.toISOString(),
|
|
208
|
-
"locale-date-options": encodeURIComponent(JSON.stringify(options)),
|
|
209
|
-
},
|
|
210
|
-
date.toLocaleDateString("en", options)
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
module.exports = {
|
|
214
|
-
mkTable,
|
|
215
|
-
renderForm,
|
|
216
|
-
settingsDropdown,
|
|
217
|
-
renderBuilder,
|
|
218
|
-
link,
|
|
219
|
-
post_btn,
|
|
220
|
-
post_delete_btn,
|
|
221
|
-
post_dropdown_item,
|
|
222
|
-
tabs,
|
|
223
|
-
localeTime,
|
|
224
|
-
localeDate,
|
|
225
|
-
localeDateTime,
|
|
226
|
-
};
|