@sealcode/sealgen 0.14.10 → 0.14.11
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/@types/src/forms/controls/checkboxed-list-input.d.ts +3 -3
- package/@types/src/forms/controls/checkboxed-list-input.test.d.ts +1 -0
- package/@types/src/forms/fields/checkboxed-list.d.ts +9 -7
- package/dist/forms/controls/checkboxed-list-input.js +8 -8
- package/dist/forms/controls/checkboxed-list-input.test.js +62 -0
- package/dist/forms/fields/checkboxed-list.js +2 -2
- package/package.json +1 -1
- package/src/forms/controls/checkboxed-list-input.test.ts +70 -0
- package/src/forms/controls/checkboxed-list-input.ts +11 -9
- package/src/forms/fields/checkboxed-list.ts +2 -2
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import {
|
|
2
|
+
import { CheckboxedListField } from "../fields/checkboxed-list.js";
|
|
3
3
|
import { FormControlContext } from "./form-control.js";
|
|
4
4
|
import { FormFieldControl } from "./form-field-control.js";
|
|
5
5
|
export declare class CheckboxedListInput extends FormFieldControl {
|
|
6
|
-
field:
|
|
6
|
+
field: CheckboxedListField<boolean>;
|
|
7
7
|
options: {
|
|
8
8
|
label: string;
|
|
9
9
|
};
|
|
10
|
-
constructor(field:
|
|
10
|
+
constructor(field: CheckboxedListField<boolean>, options?: {
|
|
11
11
|
label: string;
|
|
12
12
|
});
|
|
13
13
|
render(fctx: FormControlContext): Promise<import("stream").Readable>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Context } from "koa";
|
|
2
2
|
import { FormDataValue } from "../form-types.js";
|
|
3
3
|
import { FieldParseResult, FormField, FormFieldValidationResponse } from "./field.js";
|
|
4
|
-
export declare class
|
|
4
|
+
export declare class CheckboxedListField<Required extends boolean> extends FormField<Required, Record<string, "on">> {
|
|
5
5
|
required: Required;
|
|
6
|
-
generateOptions: (ctx: Context) => Promise<
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
generateOptions: (ctx: Context) => Promise<{
|
|
7
|
+
value: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
}[]>;
|
|
9
10
|
isVisible: (ctx: Context) => Promise<boolean>;
|
|
10
|
-
constructor(required: Required, generateOptions: (ctx: Context) => Promise<
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
constructor(required: Required, generateOptions: (ctx: Context) => Promise<{
|
|
12
|
+
value: string;
|
|
13
|
+
label?: string;
|
|
14
|
+
}[]>, isVisible?: (ctx: Context) => Promise<boolean>);
|
|
13
15
|
predicate: (v: unknown, w: unknown) => {
|
|
14
16
|
readonly match: boolean;
|
|
15
17
|
readonly wildcard: string[];
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
1
|
import { tempstream } from "tempstream";
|
|
3
2
|
import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
|
|
4
3
|
import { FormFieldControl } from "./form-field-control.js";
|
|
@@ -9,20 +8,18 @@ class CheckboxedListInput extends FormFieldControl {
|
|
|
9
8
|
this.options = options;
|
|
10
9
|
}
|
|
11
10
|
async render(fctx) {
|
|
12
|
-
const { parsed:
|
|
11
|
+
const { parsed: currentValue } = await this.field.getValue(
|
|
13
12
|
fctx.ctx,
|
|
14
13
|
fctx.data
|
|
15
14
|
);
|
|
16
|
-
|
|
17
|
-
throw new Error("picked values is not an array of strings");
|
|
18
|
-
}
|
|
15
|
+
const pickedValues = Object.entries(currentValue).filter(([, is_on]) => is_on).map(([key]) => key);
|
|
19
16
|
const [options, isVisible] = await Promise.all([
|
|
20
17
|
this.field.generateOptions(fctx.ctx),
|
|
21
18
|
this.field.isVisible(fctx.ctx)
|
|
22
19
|
]);
|
|
23
20
|
const { name, required } = this.field;
|
|
24
|
-
return tempstream`${isVisible ?
|
|
25
|
-
(
|
|
21
|
+
return tempstream`${isVisible ? options.map(
|
|
22
|
+
({ value, label }) => inputWrapper(
|
|
26
23
|
[name, getRequiredClass(required)],
|
|
27
24
|
/* HTML */
|
|
28
25
|
`
|
|
@@ -31,8 +28,11 @@ class CheckboxedListInput extends FormFieldControl {
|
|
|
31
28
|
id="${name}.${value}"
|
|
32
29
|
name="${name}.${value}"
|
|
33
30
|
${pickedValues.includes(value) ? "checked" : ""}
|
|
31
|
+
form=${fctx.form_id}
|
|
34
32
|
/>
|
|
35
|
-
<label for="${name}.${value}"
|
|
33
|
+
<label for="${name}.${value}"
|
|
34
|
+
>${label || value}</label
|
|
35
|
+
>
|
|
36
36
|
`
|
|
37
37
|
)
|
|
38
38
|
) : ""}`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import Router from "@koa/router";
|
|
2
|
+
import getPort from "get-port";
|
|
3
|
+
import Koa from "koa";
|
|
4
|
+
import { mount } from "../../mount.js";
|
|
5
|
+
import { CheckboxedListField } from "../fields/checkboxed-list.js";
|
|
6
|
+
import { Form } from "../form.js";
|
|
7
|
+
import { CheckboxedListInput } from "./checkboxed-list-input.js";
|
|
8
|
+
import { getBrowser } from "../../utils/browser-creator.js";
|
|
9
|
+
describe.only("checkboxed-list", () => {
|
|
10
|
+
describe("basic tests", async () => {
|
|
11
|
+
let server;
|
|
12
|
+
let browser;
|
|
13
|
+
let page;
|
|
14
|
+
afterAll(() => {
|
|
15
|
+
server.close();
|
|
16
|
+
});
|
|
17
|
+
it("sends the values", async () => {
|
|
18
|
+
const port = await getPort();
|
|
19
|
+
console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
|
|
20
|
+
const app = new Koa();
|
|
21
|
+
const router = new Router();
|
|
22
|
+
const fields = {
|
|
23
|
+
syllables: new CheckboxedListField(true, async () => {
|
|
24
|
+
return ["sa", "mple", "co", "de"].map((s) => ({
|
|
25
|
+
value: s,
|
|
26
|
+
label: s.toLocaleUpperCase()
|
|
27
|
+
}));
|
|
28
|
+
})
|
|
29
|
+
};
|
|
30
|
+
let received_values;
|
|
31
|
+
mount(
|
|
32
|
+
router,
|
|
33
|
+
"/",
|
|
34
|
+
new class extends Form {
|
|
35
|
+
constructor() {
|
|
36
|
+
super(...arguments);
|
|
37
|
+
this.fields = fields;
|
|
38
|
+
this.controls = [new CheckboxedListInput(fields.syllables)];
|
|
39
|
+
}
|
|
40
|
+
async onSubmit(ctx) {
|
|
41
|
+
received_values = await this.getParsedValues(ctx);
|
|
42
|
+
}
|
|
43
|
+
async canAccess(_) {
|
|
44
|
+
return { canAccess: true, message: "" };
|
|
45
|
+
}
|
|
46
|
+
}(),
|
|
47
|
+
true
|
|
48
|
+
);
|
|
49
|
+
app.use(router.routes()).use(router.allowedMethods());
|
|
50
|
+
server = app.listen(port);
|
|
51
|
+
browser = await getBrowser();
|
|
52
|
+
const context = await browser.newContext();
|
|
53
|
+
page = await context.newPage();
|
|
54
|
+
await page.goto(`http://localhost:${port}`);
|
|
55
|
+
await page.getByLabel("CO").check();
|
|
56
|
+
await page.getByLabel("DE").check();
|
|
57
|
+
await page.getByRole("button", { name: "Wy\u015Blij" }).click();
|
|
58
|
+
assert.deepStrictEqual(received_values, { syllables: { co: "on", de: "on" } });
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=checkboxed-list-input.test.js.map
|
|
@@ -2,7 +2,7 @@ import { is, predicates } from "@sealcode/ts-predicates";
|
|
|
2
2
|
import {
|
|
3
3
|
FormField
|
|
4
4
|
} from "./field.js";
|
|
5
|
-
class
|
|
5
|
+
class CheckboxedListField extends FormField {
|
|
6
6
|
constructor(required, generateOptions, isVisible = () => Promise.resolve(true)) {
|
|
7
7
|
super(required);
|
|
8
8
|
this.required = required;
|
|
@@ -44,6 +44,6 @@ class ChekboxedListField extends FormField {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
export {
|
|
47
|
-
|
|
47
|
+
CheckboxedListField
|
|
48
48
|
};
|
|
49
49
|
//# sourceMappingURL=checkboxed-list.js.map
|
package/package.json
CHANGED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import Router from "@koa/router";
|
|
2
|
+
import getPort from "get-port";
|
|
3
|
+
import { Browser, Page } from "playwright";
|
|
4
|
+
import type { Context } from "koa";
|
|
5
|
+
import Koa from "koa";
|
|
6
|
+
import { mount } from "../../mount.js";
|
|
7
|
+
import { CheckboxedListField } from "../fields/checkboxed-list.js";
|
|
8
|
+
import { Form } from "../form.js";
|
|
9
|
+
import { CheckboxedListInput } from "./checkboxed-list-input.js";
|
|
10
|
+
import { getBrowser } from "../../utils/browser-creator.js";
|
|
11
|
+
import { sleep } from "../../utils/sleep.js";
|
|
12
|
+
|
|
13
|
+
describe.only("checkboxed-list", () => {
|
|
14
|
+
describe("basic tests", async () => {
|
|
15
|
+
let server: ReturnType<Koa["listen"]>;
|
|
16
|
+
let browser: Browser;
|
|
17
|
+
let page: Page;
|
|
18
|
+
|
|
19
|
+
afterAll(() => {
|
|
20
|
+
server.close();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("sends the values", async () => {
|
|
24
|
+
const port = await getPort();
|
|
25
|
+
console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
|
|
26
|
+
const app = new Koa();
|
|
27
|
+
const router = new Router();
|
|
28
|
+
|
|
29
|
+
const fields = {
|
|
30
|
+
syllables: new CheckboxedListField(true, async () => {
|
|
31
|
+
return ["sa", "mple", "co", "de"].map((s) => ({
|
|
32
|
+
value: s,
|
|
33
|
+
label: s.toLocaleUpperCase(),
|
|
34
|
+
}));
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
let received_values: unknown;
|
|
39
|
+
|
|
40
|
+
mount(
|
|
41
|
+
router,
|
|
42
|
+
"/",
|
|
43
|
+
new (class extends Form<typeof fields, unknown> {
|
|
44
|
+
fields = fields;
|
|
45
|
+
controls = [new CheckboxedListInput(fields.syllables)];
|
|
46
|
+
|
|
47
|
+
async onSubmit(ctx: Context) {
|
|
48
|
+
received_values = await this.getParsedValues(ctx);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async canAccess(_: Context) {
|
|
52
|
+
return { canAccess: true, message: "" };
|
|
53
|
+
}
|
|
54
|
+
})(),
|
|
55
|
+
true
|
|
56
|
+
);
|
|
57
|
+
app.use(router.routes()).use(router.allowedMethods());
|
|
58
|
+
server = app.listen(port);
|
|
59
|
+
|
|
60
|
+
browser = await getBrowser();
|
|
61
|
+
const context = await browser.newContext();
|
|
62
|
+
page = await context.newPage();
|
|
63
|
+
await page.goto(`http://localhost:${port}`);
|
|
64
|
+
await page.getByLabel("CO").check();
|
|
65
|
+
await page.getByLabel("DE").check();
|
|
66
|
+
await page.getByRole("button", { name: "Wyślij" }).click();
|
|
67
|
+
assert.deepStrictEqual(received_values, { syllables: { co: "on", de: "on" } });
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -1,35 +1,34 @@
|
|
|
1
1
|
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
2
|
import { tempstream } from "tempstream";
|
|
3
3
|
import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
|
|
4
|
-
import {
|
|
4
|
+
import { CheckboxedListField } from "../fields/checkboxed-list.js";
|
|
5
5
|
import { FormControlContext } from "./form-control.js";
|
|
6
6
|
import { FormFieldControl } from "./form-field-control.js";
|
|
7
7
|
|
|
8
8
|
export class CheckboxedListInput extends FormFieldControl {
|
|
9
9
|
constructor(
|
|
10
|
-
public field:
|
|
10
|
+
public field: CheckboxedListField<boolean>,
|
|
11
11
|
public options: { label: string } = { label: field.name }
|
|
12
12
|
) {
|
|
13
13
|
super([field]);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
async render(fctx: FormControlContext) {
|
|
17
|
-
const { parsed:
|
|
17
|
+
const { parsed: currentValue } = await this.field.getValue(
|
|
18
18
|
fctx.ctx,
|
|
19
19
|
fctx.data
|
|
20
20
|
);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
const pickedValues = Object.entries(currentValue)
|
|
22
|
+
.filter(([, is_on]) => is_on)
|
|
23
|
+
.map(([key]) => key);
|
|
24
24
|
const [options, isVisible] = await Promise.all([
|
|
25
25
|
this.field.generateOptions(fctx.ctx),
|
|
26
26
|
this.field.isVisible(fctx.ctx),
|
|
27
27
|
]);
|
|
28
28
|
|
|
29
29
|
const { name, required } = this.field;
|
|
30
|
-
|
|
31
30
|
return tempstream/* HTML */ `${isVisible
|
|
32
|
-
?
|
|
31
|
+
? options.map(({ value, label }) =>
|
|
33
32
|
inputWrapper(
|
|
34
33
|
[name, getRequiredClass(required)],
|
|
35
34
|
/* HTML */ `
|
|
@@ -38,8 +37,11 @@ export class CheckboxedListInput extends FormFieldControl {
|
|
|
38
37
|
id="${name}.${value}"
|
|
39
38
|
name="${name}.${value}"
|
|
40
39
|
${pickedValues.includes(value) ? "checked" : ""}
|
|
40
|
+
form=${fctx.form_id}
|
|
41
41
|
/>
|
|
42
|
-
<label for="${name}.${value}"
|
|
42
|
+
<label for="${name}.${value}"
|
|
43
|
+
>${label || value}</label
|
|
44
|
+
>
|
|
43
45
|
`
|
|
44
46
|
)
|
|
45
47
|
)
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
FormFieldValidationResponse,
|
|
8
8
|
} from "./field.js";
|
|
9
9
|
|
|
10
|
-
export class
|
|
10
|
+
export class CheckboxedListField<Required extends boolean> extends FormField<
|
|
11
11
|
Required,
|
|
12
12
|
Record<string, "on">
|
|
13
13
|
> {
|
|
@@ -15,7 +15,7 @@ export class ChekboxedListField<Required extends boolean> extends FormField<
|
|
|
15
15
|
public required: Required,
|
|
16
16
|
public generateOptions: (
|
|
17
17
|
ctx: Context
|
|
18
|
-
) => Promise<
|
|
18
|
+
) => Promise<{ value: string; label?: string }[]>,
|
|
19
19
|
public isVisible: (ctx: Context) => Promise<boolean> = () =>
|
|
20
20
|
Promise.resolve(true)
|
|
21
21
|
) {
|