@7365admin1/layer-common 4.107.0 → 4.108.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/CHANGELOG.md +6 -0
- package/components/OnlineFormFill.vue +11 -0
- package/package.json +1 -1
- package/utils/online-form-submission.ts +48 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @iservice365/layer-common
|
|
2
2
|
|
|
3
|
+
## 4.108.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6b9abd5: Online forms: an application whose form template was deleted can still be reviewed - new `definitionFromSubmission()` builds a read-only form from the submitted answers (keys turned into readable labels), and `OnlineFormFill` takes a `notice` shown above the form.
|
|
8
|
+
|
|
3
9
|
## 4.107.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
|
@@ -9,6 +9,15 @@
|
|
|
9
9
|
<slot name="title-actions" />
|
|
10
10
|
</v-card-title>
|
|
11
11
|
|
|
12
|
+
<v-alert
|
|
13
|
+
v-if="notice"
|
|
14
|
+
type="info"
|
|
15
|
+
variant="tonal"
|
|
16
|
+
density="compact"
|
|
17
|
+
class="mx-6 mt-2"
|
|
18
|
+
data-test="online-form-notice"
|
|
19
|
+
>{{ notice }}</v-alert>
|
|
20
|
+
|
|
12
21
|
<!-- Submission metadata bar (readonly only). Shown for an actual
|
|
13
22
|
submission (submissionStatus) OR a pure template preview that
|
|
14
23
|
requires payment — a preview has no submission yet, but should
|
|
@@ -481,6 +490,8 @@ const props = defineProps({
|
|
|
481
490
|
submissionStatus: { type: String, default: "" },
|
|
482
491
|
submissionUnit: { type: String, default: "" },
|
|
483
492
|
approvalMode: { type: Boolean, default: false },
|
|
493
|
+
/** A short note above the form, e.g. that its template was deleted. */
|
|
494
|
+
notice: { type: String, default: "" },
|
|
484
495
|
initialManagementValues: { type: Object as PropType<Record<string, string>>, default: () => ({}) },
|
|
485
496
|
formType: { type: String, default: "" },
|
|
486
497
|
paymentAmount: { type: Number, default: 0 },
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@7365admin1/layer-common",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "4.
|
|
5
|
+
"version": "4.108.0",
|
|
6
6
|
"author": "7365admin1",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
8
8
|
"//files": "What a consumer extending this layer actually loads. Without this npm ships the whole working tree - the changesets, the CI workflows, the render harness in tools/ and any scratch directory that happened to exist at publish time. Nuxt resolves a layer by directory, so every runtime directory below has to stay listed; adding a new top-level runtime directory means adding it here too.",
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An application whose form template was deleted (owner 2026-10-06, option A):
|
|
3
|
+
* the review screen still shows what the resident sent, built from the
|
|
4
|
+
* submission alone. The submission stores answers by key only, so each key is
|
|
5
|
+
* turned into a readable label ("unitOwnerName" -> "Unit Owner Name").
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Shown in the meta bar already, or a machine value - not repeated as an answer. */
|
|
9
|
+
const SKIP = new Set(["formDate", "formTo", "block", "level"]);
|
|
10
|
+
|
|
11
|
+
export function readableKey(key: string): string {
|
|
12
|
+
return key
|
|
13
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
14
|
+
.replace(/[_-]+/g, " ")
|
|
15
|
+
.replace(/\s+/g, " ")
|
|
16
|
+
.trim()
|
|
17
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const isImage = (v: unknown) =>
|
|
21
|
+
typeof v === "string" && (/^data:image\//.test(v) || /^https?:\/\/\S+\.(png|jpe?g|webp)(\?|$)/i.test(v));
|
|
22
|
+
|
|
23
|
+
function asText(v: unknown): string {
|
|
24
|
+
if (v === true) return "Yes";
|
|
25
|
+
if (v === false) return "No";
|
|
26
|
+
if (Array.isArray(v)) return v.map(asText).join(", ");
|
|
27
|
+
if (v && typeof v === "object") return Object.entries(v).map(([k, x]) => `${readableKey(k)}: ${asText(x)}`).join(", ");
|
|
28
|
+
return v == null ? "" : String(v);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** A read-only form definition + display values made from the submitted answers. */
|
|
32
|
+
export function definitionFromSubmission(title: string, fields: Record<string, unknown> = {}) {
|
|
33
|
+
const blocks: Array<Record<string, any>> = [];
|
|
34
|
+
const values: Record<string, unknown> = { ...fields };
|
|
35
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
36
|
+
if (SKIP.has(key) || value === "" || value == null) continue;
|
|
37
|
+
if (isImage(value)) {
|
|
38
|
+
blocks.push({ type: "signature-row", label: readableKey(key), key });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const text = asText(value);
|
|
42
|
+
values[key] = text;
|
|
43
|
+
blocks.push({ type: "field", field: { key, label: readableKey(key), fieldType: text.length > 80 ? "textarea" : "text" } });
|
|
44
|
+
}
|
|
45
|
+
return { definition: { title, blocks }, values };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const DELETED_TEMPLATE_NOTICE = "This form has since been deleted - showing the answers as submitted.";
|