@cosmicdrift/kumiko-samples 0.398.0 → 0.400.0
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/package.json +1 -1
- package/packages/bundled-features/package.json +6 -1
- package/packages/bundled-features/src/billing-foundation/changes.json +6 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-text.ts +4 -6
- package/packages/bundled-features/src/channel-in-app/changes.json +6 -0
- package/packages/bundled-features/src/channel-in-app/constants.ts +9 -9
- package/packages/bundled-features/src/channel-in-app/feature.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/inbox.query.ts +31 -7
- package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +6 -9
- package/packages/bundled-features/src/channel-in-app/in-app-channel.ts +25 -11
- package/packages/bundled-features/src/channel-in-app/in-app-target.ts +37 -0
- package/packages/bundled-features/src/channel-in-app/index.ts +1 -0
- package/packages/bundled-features/src/documents/aggregate-id.ts +20 -0
- package/packages/bundled-features/src/documents/capture.ts +125 -0
- package/packages/bundled-features/src/documents/constants.ts +31 -0
- package/packages/bundled-features/src/documents/ensure-link.ts +35 -0
- package/packages/bundled-features/src/documents/entity.ts +103 -0
- package/packages/bundled-features/src/documents/executor.ts +13 -0
- package/packages/bundled-features/src/documents/expiry.ts +32 -0
- package/packages/bundled-features/src/documents/feature.ts +197 -0
- package/packages/bundled-features/src/documents/handlers/import.write.ts +157 -0
- package/packages/bundled-features/src/documents/handlers/link.write.ts +103 -0
- package/packages/bundled-features/src/documents/i18n.ts +35 -0
- package/packages/bundled-features/src/documents/index.ts +22 -0
- package/packages/bundled-features/src/documents/pending-file-guard.ts +36 -0
- package/packages/bundled-features/src/documents/queries/expiry-overview.query.ts +46 -0
- package/packages/bundled-features/src/documents/queries/for-record.query.ts +74 -0
- package/packages/bundled-features/src/documents/queries/list-page.ts +51 -0
- package/packages/bundled-features/src/documents/queries/overview.query.ts +45 -0
- package/packages/bundled-features/src/documents/schemas.ts +66 -0
- package/packages/bundled-features/src/documents/screens.ts +86 -0
- package/packages/bundled-features/src/documents/tab.ts +46 -0
- package/packages/bundled-features/src/documents/target-write-check.ts +41 -0
- package/packages/bundled-features/src/documents/write-guard.ts +59 -0
- package/packages/bundled-features/src/metrics/changes.json +6 -0
- package/packages/bundled-features/src/metrics/compute.ts +19 -2
- package/packages/bundled-features/src/metrics/feature.ts +14 -1
- package/packages/bundled-features/src/metrics/types.ts +3 -1
- package/packages/bundled-features/src/metrics/validate.ts +3 -0
- package/packages/bundled-features/src/shared/purge-row-file-refs.ts +5 -4
- package/samples/apps/styleguide/src/app/seed.ts +102 -1
- package/samples/apps/styleguide/src/app/server.ts +2 -2
- package/samples/apps/styleguide/src/features/examples/feature.ts +97 -0
- package/samples/apps/styleguide/src/features/examples/i18n.ts +47 -0
- package/samples/apps/use-all-bundled/feature-manifest.json +31 -2
- package/samples/apps/use-all-bundled/kumiko/migrations/0058_documents.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +11 -2
- package/samples/apps/use-all-bundled/src/run-config.ts +7 -0
- package/samples/recipes/derived-fields-sql/README.md +27 -0
- package/samples/recipes/derived-fields-sql/package.json +11 -0
- package/samples/recipes/derived-fields-sql/src/feature.ts +98 -0
- package/samples/recipes/documents/package.json +12 -0
- package/samples/recipes/documents/src/feature.ts +66 -0
- package/samples/recipes/inspection-checklist/README.md +27 -0
- package/samples/recipes/inspection-checklist/package.json +12 -0
- package/samples/recipes/inspection-checklist/src/entities/inspection-plan.ts +24 -0
- package/samples/recipes/inspection-checklist/src/entities/inspection-protocol.ts +72 -0
- package/samples/recipes/inspection-checklist/src/feature.ts +33 -0
- package/samples/recipes/inspection-checklist/src/handlers/create-from-plan.write.ts +38 -0
- package/samples/recipes/inspection-checklist/src/screens/inspection-protocol-edit.screen.ts +27 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cosmicdrift/kumiko-sample-inspection-checklist",
|
|
3
|
+
"description": "Embedded list as a phone inspection checklist: conditional fields, derived pass/fail, photos per row.",
|
|
4
|
+
"private": true,
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@cosmicdrift/kumiko-bundled-features": "workspace:*",
|
|
7
|
+
"@cosmicdrift/kumiko-framework": "workspace:*"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"@cosmicdrift/kumiko-testing": "workspace:*"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
+
import {
|
|
3
|
+
createEmbeddedListField,
|
|
4
|
+
createEntity,
|
|
5
|
+
createTextField,
|
|
6
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
7
|
+
|
|
8
|
+
export const inspectionPlanEntity = createEntity({
|
|
9
|
+
table: "read_sample_inspection_plans",
|
|
10
|
+
fields: {
|
|
11
|
+
name: createTextField({ personal: false, reason: "is_business_data", required: true }),
|
|
12
|
+
checkpoints: createEmbeddedListField(
|
|
13
|
+
{
|
|
14
|
+
label: { type: "text", required: true },
|
|
15
|
+
kind: { type: "select", options: ["check", "measurement"], required: true },
|
|
16
|
+
min: { type: "number" },
|
|
17
|
+
max: { type: "number" },
|
|
18
|
+
},
|
|
19
|
+
{ personal: false, reason: "is_business_data" },
|
|
20
|
+
),
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const inspectionPlanTable = buildEntityTable("inspection-plan", inspectionPlanEntity);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
+
import {
|
|
3
|
+
createEmbeddedListField,
|
|
4
|
+
createEntity,
|
|
5
|
+
createSelectField,
|
|
6
|
+
createTextField,
|
|
7
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
8
|
+
|
|
9
|
+
const isMeasurement = { field: "kind", eq: "measurement" } as const;
|
|
10
|
+
const isNotOk = { field: "result", eq: "not_ok" } as const;
|
|
11
|
+
|
|
12
|
+
export const inspectionProtocolEntity = createEntity({
|
|
13
|
+
table: "read_sample_inspection_protocols",
|
|
14
|
+
fields: {
|
|
15
|
+
measuringDevice: createTextField({ personal: false, reason: "is_business_data" }),
|
|
16
|
+
checkpoints: createEmbeddedListField(
|
|
17
|
+
{
|
|
18
|
+
label: { type: "text", required: true },
|
|
19
|
+
kind: { type: "select", options: ["check", "measurement"], required: true },
|
|
20
|
+
min: { type: "number", visibleWhen: isMeasurement },
|
|
21
|
+
max: { type: "number", visibleWhen: isMeasurement },
|
|
22
|
+
measured: { type: "number", visibleWhen: isMeasurement },
|
|
23
|
+
result: {
|
|
24
|
+
type: "select",
|
|
25
|
+
options: ["ok", "not_ok"],
|
|
26
|
+
display: "radio",
|
|
27
|
+
optionTones: { ok: "ok", not_ok: "bad" },
|
|
28
|
+
},
|
|
29
|
+
finding: { type: "text", visibleWhen: isNotOk, requiredWhen: isNotOk },
|
|
30
|
+
photos: {
|
|
31
|
+
type: "images",
|
|
32
|
+
capture: "environment",
|
|
33
|
+
maxCount: 5,
|
|
34
|
+
accept: ["jpg", "jpeg", "png"],
|
|
35
|
+
visibleWhen: isNotOk,
|
|
36
|
+
requiredWhen: isNotOk,
|
|
37
|
+
},
|
|
38
|
+
documents: { type: "files", maxCount: 3 },
|
|
39
|
+
approvedBy: { type: "text", access: { write: ["Admin"] } },
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
personal: false,
|
|
43
|
+
reason: "is_business_data",
|
|
44
|
+
derived: {
|
|
45
|
+
result: {
|
|
46
|
+
op: "inRange",
|
|
47
|
+
from: ["measured", "min", "max"],
|
|
48
|
+
inside: "ok",
|
|
49
|
+
outside: "not_ok",
|
|
50
|
+
when: isMeasurement,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
),
|
|
55
|
+
continuedOperation: createSelectField({
|
|
56
|
+
options: ["yes", "with_condition", "no"],
|
|
57
|
+
display: "radio",
|
|
58
|
+
optionTones: { yes: "ok", with_condition: "warn", no: "bad" },
|
|
59
|
+
}),
|
|
60
|
+
condition: createTextField({
|
|
61
|
+
personal: false,
|
|
62
|
+
reason: "is_business_data",
|
|
63
|
+
visibleWhen: { field: "continuedOperation", eq: "with_condition" },
|
|
64
|
+
requiredWhen: { field: "continuedOperation", eq: "with_condition" },
|
|
65
|
+
}),
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export const inspectionProtocolTable = buildEntityTable(
|
|
70
|
+
"inspection-protocol",
|
|
71
|
+
inspectionProtocolEntity,
|
|
72
|
+
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Inspection Checklist Sample
|
|
2
|
+
// Shows: an embedded list as a phone inspection checklist.
|
|
3
|
+
// - visibleWhen / requiredWhen on cells and top-level fields (server-enforced)
|
|
4
|
+
// - a derived pass/fail cell (inRange) that the server recomputes
|
|
5
|
+
// - an images cell per row, uploaded with the `subField` multipart part
|
|
6
|
+
// - fixed rows copied from a plan, only the result cells stay editable
|
|
7
|
+
|
|
8
|
+
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
9
|
+
import { inspectionPlanEntity } from "./entities/inspection-plan";
|
|
10
|
+
import { inspectionProtocolEntity } from "./entities/inspection-protocol";
|
|
11
|
+
import { createFromPlan } from "./handlers/create-from-plan.write";
|
|
12
|
+
import { inspectionProtocolEditScreen } from "./screens/inspection-protocol-edit.screen";
|
|
13
|
+
|
|
14
|
+
export { inspectionPlanEntity } from "./entities/inspection-plan";
|
|
15
|
+
export { inspectionProtocolEntity } from "./entities/inspection-protocol";
|
|
16
|
+
|
|
17
|
+
const inspectorAccess = { access: { roles: ["Admin", "Inspector"] } } as const;
|
|
18
|
+
|
|
19
|
+
export const inspectionChecklistFeature = defineFeature("inspection-checklist", (r) => {
|
|
20
|
+
r.requires({ features: ["files"] });
|
|
21
|
+
|
|
22
|
+
r.crud("inspection-plan", inspectionPlanEntity, {
|
|
23
|
+
write: inspectorAccess,
|
|
24
|
+
read: inspectorAccess,
|
|
25
|
+
});
|
|
26
|
+
r.crud("inspection-protocol", inspectionProtocolEntity, {
|
|
27
|
+
write: inspectorAccess,
|
|
28
|
+
read: inspectorAccess,
|
|
29
|
+
});
|
|
30
|
+
r.writeHandler(createFromPlan);
|
|
31
|
+
|
|
32
|
+
r.screen(inspectionProtocolEditScreen);
|
|
33
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createEntityExecutor, defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
import { failNotFound } from "@cosmicdrift/kumiko-framework/errors";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { inspectionPlanEntity } from "../entities/inspection-plan";
|
|
5
|
+
import { inspectionProtocolEntity } from "../entities/inspection-protocol";
|
|
6
|
+
|
|
7
|
+
const { executor: planExecutor } = createEntityExecutor("inspection-plan", inspectionPlanEntity);
|
|
8
|
+
const { executor: protocolExecutor } = createEntityExecutor(
|
|
9
|
+
"inspection-protocol",
|
|
10
|
+
inspectionProtocolEntity,
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const planRows = z.array(
|
|
14
|
+
z.object({
|
|
15
|
+
label: z.string(),
|
|
16
|
+
kind: z.enum(["check", "measurement"]),
|
|
17
|
+
min: z.number().optional(),
|
|
18
|
+
max: z.number().optional(),
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// Copies only the plan's fixed columns; result, finding and photos stay empty for the inspector.
|
|
23
|
+
export const createFromPlan = defineWriteHandler({
|
|
24
|
+
name: "inspection-protocol:create-from-plan",
|
|
25
|
+
schema: z.object({ planId: z.uuid() }),
|
|
26
|
+
access: { roles: ["Admin", "Inspector"] },
|
|
27
|
+
handler: async (event, ctx) => {
|
|
28
|
+
const plan = await planExecutor.detail({ id: event.payload.planId }, event.user, ctx.db);
|
|
29
|
+
if (!plan) return failNotFound("inspection-plan", event.payload.planId);
|
|
30
|
+
const checkpoints = planRows.parse(plan["checkpoints"]).map(({ label, kind, min, max }) => ({
|
|
31
|
+
label,
|
|
32
|
+
kind,
|
|
33
|
+
...(min !== undefined ? { min } : {}),
|
|
34
|
+
...(max !== undefined ? { max } : {}),
|
|
35
|
+
}));
|
|
36
|
+
return protocolExecutor.create({ checkpoints }, event.user, ctx.db);
|
|
37
|
+
},
|
|
38
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { EntityEditScreenDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
|
|
3
|
+
export const inspectionProtocolEditScreen: EntityEditScreenDefinition = {
|
|
4
|
+
id: "inspection-protocol-edit",
|
|
5
|
+
type: "entityEdit",
|
|
6
|
+
entity: "inspection-protocol",
|
|
7
|
+
layout: {
|
|
8
|
+
width: "full",
|
|
9
|
+
sections: [
|
|
10
|
+
{
|
|
11
|
+
columns: 1,
|
|
12
|
+
fields: [
|
|
13
|
+
"measuringDevice",
|
|
14
|
+
{
|
|
15
|
+
field: "checkpoints",
|
|
16
|
+
embeddedList: {
|
|
17
|
+
readOnlyCells: ["label", "kind", "min", "max"],
|
|
18
|
+
cardHiddenCells: ["kind"],
|
|
19
|
+
fixedRows: true,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
{ columns: 1, fields: ["continuedOperation", "condition"] },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
};
|