@webiny/app-headless-cms 6.5.0-beta.9 → 6.5.1-beta.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.
Files changed (88) hide show
  1. package/admin/components/ContentEntries/Filters/RefFieldRenderer.js +1 -0
  2. package/admin/components/ContentEntries/Filters/RefFieldRenderer.js.map +1 -1
  3. package/admin/plugins/editor/defaultBar/Name/Name.d.ts +0 -5
  4. package/admin/plugins/editor/defaultBar/Name/Name.js +0 -2
  5. package/admin/plugins/editor/defaultBar/Name/Name.js.map +1 -1
  6. package/features/contentEntry/feature.js +2 -0
  7. package/features/contentEntry/feature.js.map +1 -1
  8. package/features/contentEntry/referenceTitles/ReferenceTitles.d.ts +18 -0
  9. package/features/contentEntry/referenceTitles/ReferenceTitles.js +58 -0
  10. package/features/contentEntry/referenceTitles/ReferenceTitles.js.map +1 -0
  11. package/features/contentEntry/referenceTitles/ReferenceTitles.test.d.ts +1 -0
  12. package/features/contentEntry/referenceTitles/ReferenceTitles.test.js +173 -0
  13. package/features/contentEntry/referenceTitles/ReferenceTitles.test.js.map +1 -0
  14. package/features/contentEntry/referenceTitles/RememberTitlesDecorators.d.ts +22 -0
  15. package/features/contentEntry/referenceTitles/RememberTitlesDecorators.js +40 -0
  16. package/features/contentEntry/referenceTitles/RememberTitlesDecorators.js.map +1 -0
  17. package/features/contentEntry/referenceTitles/abstractions.d.ts +16 -0
  18. package/features/contentEntry/referenceTitles/abstractions.js +5 -0
  19. package/features/contentEntry/referenceTitles/abstractions.js.map +1 -0
  20. package/features/contentEntry/referenceTitles/feature.d.ts +3 -0
  21. package/features/contentEntry/referenceTitles/feature.js +20 -0
  22. package/features/contentEntry/referenceTitles/feature.js.map +1 -0
  23. package/features/formModel/CmsFormModelBuilder.test.js +213 -0
  24. package/features/formModel/CmsFormModelBuilder.test.js.map +1 -1
  25. package/features/formModel/CmsRefFieldValueFormatter.d.ts +12 -0
  26. package/features/formModel/CmsRefFieldValueFormatter.js +29 -0
  27. package/features/formModel/CmsRefFieldValueFormatter.js.map +1 -0
  28. package/features/formModel/CmsValidationMapper.d.ts +9 -0
  29. package/features/formModel/CmsValidationMapper.js +25 -19
  30. package/features/formModel/CmsValidationMapper.js.map +1 -1
  31. package/features/formModel/feature.js +2 -0
  32. package/features/formModel/feature.js.map +1 -1
  33. package/features/formModel/mappers/DateTimeFieldMapper.js +3 -0
  34. package/features/formModel/mappers/DateTimeFieldMapper.js.map +1 -1
  35. package/package.json +22 -22
  36. package/presentation/contentEntries/form/ContentEntryFormPresenter.js +30 -30
  37. package/presentation/contentEntries/form/ContentEntryFormPresenter.js.map +1 -1
  38. package/presentation/contentEntries/form/ContentEntryFormPresenter.test.js +144 -10
  39. package/presentation/contentEntries/form/ContentEntryFormPresenter.test.js.map +1 -1
  40. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js +1 -1
  41. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js.map +1 -1
  42. package/presentation/contentEntries/preview/PreviewDecorator.js +9 -3
  43. package/presentation/contentEntries/preview/PreviewDecorator.js.map +1 -1
  44. package/presentation/contentEntries/preview/PreviewDomainStatus.d.ts +10 -0
  45. package/presentation/contentEntries/preview/PreviewDomainStatus.js +19 -0
  46. package/presentation/contentEntries/preview/PreviewDomainStatus.js.map +1 -0
  47. package/presentation/contentEntries/preview/PreviewPane.d.ts +6 -1
  48. package/presentation/contentEntries/preview/PreviewPane.js +80 -44
  49. package/presentation/contentEntries/preview/PreviewPane.js.map +1 -1
  50. package/presentation/contentEntries/views/ContentEntryFormView.js +1 -0
  51. package/presentation/contentEntries/views/ContentEntryFormView.js.map +1 -1
  52. package/presentation/fieldEditor/groups/AppearanceGroup.js +12 -0
  53. package/presentation/fieldEditor/groups/AppearanceGroup.js.map +1 -1
  54. package/presentation/fieldEditor/groups/ValidationsGroup.d.ts +2 -0
  55. package/presentation/fieldEditor/groups/ValidationsGroup.js +20 -6
  56. package/presentation/fieldEditor/groups/ValidationsGroup.js.map +1 -1
  57. package/presentation/fieldEditor/renderers/CmsValidatorsRenderer.js +2 -2
  58. package/presentation/fieldEditor/renderers/CmsValidatorsRenderer.js.map +1 -1
  59. package/presentation/fieldRenderers/feature.js +2 -1
  60. package/presentation/fieldRenderers/feature.js.map +1 -1
  61. package/presentation/fieldRenderers/ref/CmsRefInputRenderer.js +1 -0
  62. package/presentation/fieldRenderers/ref/CmsRefInputRenderer.js.map +1 -1
  63. package/presentation/fieldRenderers/ref/CmsRefInputsRenderer.js +1 -0
  64. package/presentation/fieldRenderers/ref/CmsRefInputsRenderer.js.map +1 -1
  65. package/presentation/fieldRenderers/ref/autocomplete/BaseAutocompletePresenter.d.ts +1 -0
  66. package/presentation/fieldRenderers/ref/autocomplete/BaseAutocompletePresenter.js +8 -2
  67. package/presentation/fieldRenderers/ref/autocomplete/BaseAutocompletePresenter.js.map +1 -1
  68. package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.js +52 -0
  69. package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.js.map +1 -1
  70. package/presentation/fieldTypes/renderers/dateTime/BirthdayInputRenderer.d.ts +15 -0
  71. package/presentation/fieldTypes/renderers/dateTime/BirthdayInputRenderer.js +19 -0
  72. package/presentation/fieldTypes/renderers/dateTime/BirthdayInputRenderer.js.map +1 -0
  73. package/presentation/fieldTypes/renderers/index.d.ts +1 -0
  74. package/presentation/fieldTypes/renderers/index.js +1 -0
  75. package/presentation/fieldValidators/abstractions.d.ts +7 -0
  76. package/presentation/fieldValidators/abstractions.js.map +1 -1
  77. package/presentation/fieldValidators/validators/DateGteValidator.d.ts +6 -0
  78. package/presentation/fieldValidators/validators/DateGteValidator.js +17 -25
  79. package/presentation/fieldValidators/validators/DateGteValidator.js.map +1 -1
  80. package/presentation/fieldValidators/validators/DateLteValidator.d.ts +6 -0
  81. package/presentation/fieldValidators/validators/DateLteValidator.js +17 -25
  82. package/presentation/fieldValidators/validators/DateLteValidator.js.map +1 -1
  83. package/presentation/fieldValidators/validators/dateLimitSettings.d.ts +20 -0
  84. package/presentation/fieldValidators/validators/dateLimitSettings.js +124 -0
  85. package/presentation/fieldValidators/validators/dateLimitSettings.js.map +1 -0
  86. package/presentation/fieldValidators/validators/dateLimitSettings.test.d.ts +1 -0
  87. package/presentation/fieldValidators/validators/dateLimitSettings.test.js +111 -0
  88. package/presentation/fieldValidators/validators/dateLimitSettings.test.js.map +1 -0
@@ -0,0 +1,20 @@
1
+ import { type DateExpressionUnit } from "@webiny/utils";
2
+ import type { ICmsFieldValidatorFormBuilder, ICmsFieldValidatorContext } from "../abstractions.js";
3
+ /**
4
+ * The settings form of the `dateGte`/`dateLte` validators. On a date-only field, a limit is a
5
+ * fixed date or relative to today: a number, a unit and a direction, which the form turns into
6
+ * a date expression (`today-18y`) when the field is saved, and back when it's opened.
7
+ */
8
+ type DateLimitDirection = "before" | "after";
9
+ interface DateLimitFormOptions {
10
+ /** The Value field's description, for a fixed limit. */
11
+ valueDescription: string;
12
+ }
13
+ export declare function buildDateLimitSettingsForm(form: ICmsFieldValidatorFormBuilder, context: ICmsFieldValidatorContext, options: DateLimitFormOptions): void;
14
+ /** Stored settings (`{ value }` or `{ expression }`) as the settings form's values. */
15
+ export declare function dateLimitSettingsToForm(settings: Record<string, unknown>, context: ICmsFieldValidatorContext): Record<string, unknown>;
16
+ /** The settings form's values as stored settings: a fixed `value` or an `expression`. */
17
+ export declare function dateLimitSettingsFromForm(settings: Record<string, unknown>): Record<string, unknown>;
18
+ /** `today`, or `today` plus or minus the amount: 18 years before today is `today-18y`. */
19
+ export declare function toDateExpression(amount: number, unit: DateExpressionUnit, direction: DateLimitDirection): string;
20
+ export {};
@@ -0,0 +1,124 @@
1
+ import { z } from "zod";
2
+ import { parseDateExpression } from "@webiny/utils";
3
+ const isDateOnly = (field)=>{
4
+ const type = field.settings ? field.settings.type : "date";
5
+ return !type || "date" === type;
6
+ };
7
+ const isLiveDateOnly = (form)=>{
8
+ try {
9
+ const type = form.field("general.settingsType").getValue();
10
+ return "string" != typeof type || "date" === type;
11
+ } catch {
12
+ return true;
13
+ }
14
+ };
15
+ const isRelative = ({ field, form })=>isLiveDateOnly(form) && "relative" === field.parent().field("mode").getValue();
16
+ function buildDateLimitSettingsForm(form, context, options) {
17
+ const type = context.field.settings ? context.field.settings.type : "date";
18
+ const relativeAllowed = isDateOnly(context.field);
19
+ form.fields((fields)=>{
20
+ const valueField = fields.datetime().label("Value").description(options.valueDescription);
21
+ switch(type){
22
+ case "time":
23
+ valueField.timeOnly();
24
+ break;
25
+ case "dateTimeWithTimezone":
26
+ valueField.withTimezone();
27
+ break;
28
+ case "dateTimeWithoutTimezone":
29
+ valueField.withoutTimezone();
30
+ break;
31
+ default:
32
+ valueField.dateOnly();
33
+ break;
34
+ }
35
+ if (!relativeAllowed) return {
36
+ value: valueField
37
+ };
38
+ return {
39
+ mode: fields.text().label("Limit").description("A date relative to today is worked out from the current date every time the value is checked.").options([
40
+ {
41
+ value: "fixed",
42
+ label: "Fixed date"
43
+ },
44
+ {
45
+ value: "relative",
46
+ label: "Relative to today"
47
+ }
48
+ ]).defaultValue("fixed").hiddenWhen(({ form })=>!isLiveDateOnly(form)),
49
+ value: valueField.hiddenWhen(isRelative),
50
+ amount: fields.number().label("Amount").required("Enter a number.").schema(z.number().int("Use a whole number.").min(0, "Use 0 or more.")).hiddenWhen((params)=>!isRelative(params)),
51
+ unit: fields.text().label("Unit").options([
52
+ {
53
+ value: "d",
54
+ label: "Days"
55
+ },
56
+ {
57
+ value: "m",
58
+ label: "Months"
59
+ },
60
+ {
61
+ value: "y",
62
+ label: "Years"
63
+ }
64
+ ]).defaultValue("y").hiddenWhen((params)=>!isRelative(params)),
65
+ direction: fields.text().label("Direction").options([
66
+ {
67
+ value: "before",
68
+ label: "Before today"
69
+ },
70
+ {
71
+ value: "after",
72
+ label: "After today"
73
+ }
74
+ ]).defaultValue("before").hiddenWhen((params)=>!isRelative(params))
75
+ };
76
+ });
77
+ form.layout((layout)=>relativeAllowed ? [
78
+ layout.row("mode"),
79
+ layout.row("value"),
80
+ layout.row("amount", "unit", "direction")
81
+ ] : [
82
+ layout.row("value")
83
+ ]);
84
+ }
85
+ function dateLimitSettingsToForm(settings, context) {
86
+ if (!isDateOnly(context.field)) return settings;
87
+ const { expression, ...rest } = settings;
88
+ const parsed = "string" == typeof expression ? parseDateExpression(expression) : null;
89
+ if (!parsed) return {
90
+ ...rest,
91
+ mode: "fixed",
92
+ unit: "y",
93
+ direction: "before"
94
+ };
95
+ const direction = parsed.amount > 0 ? "after" : "before";
96
+ return {
97
+ ...rest,
98
+ mode: "relative",
99
+ amount: Math.abs(parsed.amount),
100
+ unit: 0 === parsed.amount ? "y" : parsed.unit,
101
+ direction
102
+ };
103
+ }
104
+ function dateLimitSettingsFromForm(settings) {
105
+ const { mode, amount, unit, direction, value, expression: _expression, ...rest } = settings;
106
+ if ("relative" === mode) {
107
+ if ("number" != typeof amount) return rest;
108
+ return {
109
+ ...rest,
110
+ expression: toDateExpression(amount, unit, direction)
111
+ };
112
+ }
113
+ return null == value ? rest : {
114
+ ...rest,
115
+ value
116
+ };
117
+ }
118
+ function toDateExpression(amount, unit, direction) {
119
+ if (0 === amount) return "today";
120
+ return `today${"after" === direction ? "+" : "-"}${amount}${unit}`;
121
+ }
122
+ export { buildDateLimitSettingsForm, dateLimitSettingsFromForm, dateLimitSettingsToForm, toDateExpression };
123
+
124
+ //# sourceMappingURL=dateLimitSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/fieldValidators/validators/dateLimitSettings.js","sources":["../../../../src/presentation/fieldValidators/validators/dateLimitSettings.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { parseDateExpression, type DateExpressionUnit } from \"@webiny/utils\";\nimport type { FormModel, FormModelFactory } from \"@webiny/app-admin\";\nimport type { CmsModelField } from \"~/types.js\";\nimport type { ICmsFieldValidatorFormBuilder, ICmsFieldValidatorContext } from \"../abstractions.js\";\n\n/**\n * The settings form of the `dateGte`/`dateLte` validators. On a date-only field, a limit is a\n * fixed date or relative to today: a number, a unit and a direction, which the form turns into\n * a date expression (`today-18y`) when the field is saved, and back when it's opened.\n */\n\ntype DateLimitDirection = \"before\" | \"after\";\n\ninterface DateLimitFormOptions {\n /** The Value field's description, for a fixed limit. */\n valueDescription: string;\n}\n\nconst isDateOnly = (field: Pick<CmsModelField, \"settings\">): boolean => {\n const type = field.settings ? field.settings.type : \"date\";\n return !type || type === \"date\";\n};\n\n/**\n * The field's Format as it is in the open dialog, which can differ from the saved one on a new\n * field. Only date/time fields have it, and `form.field()` throws for a path the form doesn't\n * have.\n */\nconst isLiveDateOnly = (form: FormModel.Interface): boolean => {\n try {\n const type = form.field(\"general.settingsType\").getValue();\n return typeof type !== \"string\" || type === \"date\";\n } catch {\n return true;\n }\n};\n\nconst isRelative = ({ field, form }: FormModel.CallbackParams): boolean =>\n isLiveDateOnly(form) && field.parent().field(\"mode\").getValue() === \"relative\";\n\nexport function buildDateLimitSettingsForm(\n form: ICmsFieldValidatorFormBuilder,\n context: ICmsFieldValidatorContext,\n options: DateLimitFormOptions\n): void {\n const type = context.field.settings ? context.field.settings.type : \"date\";\n const relativeAllowed = isDateOnly(context.field);\n\n form.fields((fields): Record<string, FormModelFactory.FieldBuilder> => {\n const valueField = fields.datetime().label(\"Value\").description(options.valueDescription);\n\n switch (type) {\n case \"time\":\n valueField.timeOnly();\n break;\n case \"dateTimeWithTimezone\":\n valueField.withTimezone();\n break;\n case \"dateTimeWithoutTimezone\":\n valueField.withoutTimezone();\n break;\n default:\n valueField.dateOnly();\n break;\n }\n\n if (!relativeAllowed) {\n return { value: valueField };\n }\n\n return {\n mode: fields\n .text()\n .label(\"Limit\")\n .description(\n \"A date relative to today is worked out from the current date every time the value is checked.\"\n )\n .options([\n { value: \"fixed\", label: \"Fixed date\" },\n { value: \"relative\", label: \"Relative to today\" }\n ])\n .defaultValue(\"fixed\")\n .hiddenWhen(({ form }: FormModel.CallbackParams) => !isLiveDateOnly(form)),\n value: valueField.hiddenWhen(isRelative),\n amount: fields\n .number()\n .label(\"Amount\")\n .required(\"Enter a number.\")\n .schema(z.number().int(\"Use a whole number.\").min(0, \"Use 0 or more.\"))\n .hiddenWhen(params => !isRelative(params)),\n unit: fields\n .text()\n .label(\"Unit\")\n .options([\n { value: \"d\", label: \"Days\" },\n { value: \"m\", label: \"Months\" },\n { value: \"y\", label: \"Years\" }\n ])\n .defaultValue(\"y\")\n .hiddenWhen(params => !isRelative(params)),\n direction: fields\n .text()\n .label(\"Direction\")\n .options([\n { value: \"before\", label: \"Before today\" },\n { value: \"after\", label: \"After today\" }\n ])\n .defaultValue(\"before\")\n .hiddenWhen(params => !isRelative(params))\n };\n });\n\n form.layout(layout =>\n relativeAllowed\n ? [layout.row(\"mode\"), layout.row(\"value\"), layout.row(\"amount\", \"unit\", \"direction\")]\n : [layout.row(\"value\")]\n );\n}\n\n/** Stored settings (`{ value }` or `{ expression }`) as the settings form's values. */\nexport function dateLimitSettingsToForm(\n settings: Record<string, unknown>,\n context: ICmsFieldValidatorContext\n): Record<string, unknown> {\n if (!isDateOnly(context.field)) {\n return settings;\n }\n const { expression, ...rest } = settings;\n const parsed = typeof expression === \"string\" ? parseDateExpression(expression) : null;\n if (!parsed) {\n return { ...rest, mode: \"fixed\", unit: \"y\", direction: \"before\" };\n }\n const direction: DateLimitDirection = parsed.amount > 0 ? \"after\" : \"before\";\n return {\n ...rest,\n mode: \"relative\",\n amount: Math.abs(parsed.amount),\n // Plain `today` parses as 0 days; years is the form's default unit.\n unit: parsed.amount === 0 ? \"y\" : parsed.unit,\n direction\n };\n}\n\n/** The settings form's values as stored settings: a fixed `value` or an `expression`. */\nexport function dateLimitSettingsFromForm(\n settings: Record<string, unknown>\n): Record<string, unknown> {\n const { mode, amount, unit, direction, value, expression: _expression, ...rest } = settings;\n if (mode === \"relative\") {\n if (typeof amount !== \"number\") {\n return rest;\n }\n return {\n ...rest,\n expression: toDateExpression(\n amount,\n unit as DateExpressionUnit,\n direction as DateLimitDirection\n )\n };\n }\n return value == null ? rest : { ...rest, value };\n}\n\n/** `today`, or `today` plus or minus the amount: 18 years before today is `today-18y`. */\nexport function toDateExpression(\n amount: number,\n unit: DateExpressionUnit,\n direction: DateLimitDirection\n): string {\n if (amount === 0) {\n return \"today\";\n }\n return `today${direction === \"after\" ? \"+\" : \"-\"}${amount}${unit}`;\n}\n"],"names":["isDateOnly","field","type","isLiveDateOnly","form","isRelative","buildDateLimitSettingsForm","context","options","relativeAllowed","fields","valueField","z","params","layout","dateLimitSettingsToForm","settings","expression","rest","parsed","parseDateExpression","direction","Math","dateLimitSettingsFromForm","mode","amount","unit","value","_expression","toDateExpression"],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { dateLimitSettingsFromForm, dateLimitSettingsToForm, toDateExpression } from "./dateLimitSettings.js";
3
+ const context = (type)=>({
4
+ field: {
5
+ type: "datetime",
6
+ settings: type ? {
7
+ type
8
+ } : {}
9
+ }
10
+ });
11
+ describe("date limit settings", ()=>{
12
+ it("opens a relative limit as an amount, a unit and a direction", ()=>{
13
+ expect(dateLimitSettingsToForm({
14
+ expression: "today-18y"
15
+ }, context("date"))).toEqual({
16
+ mode: "relative",
17
+ amount: 18,
18
+ unit: "y",
19
+ direction: "before"
20
+ });
21
+ expect(dateLimitSettingsToForm({
22
+ expression: "today+1d"
23
+ }, context("date"))).toEqual({
24
+ mode: "relative",
25
+ amount: 1,
26
+ unit: "d",
27
+ direction: "after"
28
+ });
29
+ expect(dateLimitSettingsToForm({
30
+ expression: "today"
31
+ }, context())).toMatchObject({
32
+ mode: "relative",
33
+ amount: 0
34
+ });
35
+ });
36
+ it("opens a fixed limit as a fixed date", ()=>{
37
+ expect(dateLimitSettingsToForm({
38
+ value: "2000-12-31"
39
+ }, context("date"))).toEqual({
40
+ value: "2000-12-31",
41
+ mode: "fixed",
42
+ unit: "y",
43
+ direction: "before"
44
+ });
45
+ });
46
+ it("leaves the settings of a time or datetime field as they are", ()=>{
47
+ expect(dateLimitSettingsToForm({
48
+ value: "10:00:00"
49
+ }, context("time"))).toEqual({
50
+ value: "10:00:00"
51
+ });
52
+ });
53
+ it("saves a relative limit as an expression, without the form's own values", ()=>{
54
+ expect(dateLimitSettingsFromForm({
55
+ mode: "relative",
56
+ value: "2000-12-31",
57
+ amount: 18,
58
+ unit: "y",
59
+ direction: "before"
60
+ })).toEqual({
61
+ expression: "today-18y"
62
+ });
63
+ expect(dateLimitSettingsFromForm({
64
+ mode: "relative",
65
+ amount: 0,
66
+ unit: "d",
67
+ direction: "after"
68
+ })).toEqual({
69
+ expression: "today"
70
+ });
71
+ });
72
+ it("saves a fixed limit as a value, dropping an earlier expression", ()=>{
73
+ expect(dateLimitSettingsFromForm({
74
+ mode: "fixed",
75
+ value: "2000-12-31",
76
+ expression: "today-18y",
77
+ amount: 18,
78
+ unit: "y",
79
+ direction: "before"
80
+ })).toEqual({
81
+ value: "2000-12-31"
82
+ });
83
+ expect(dateLimitSettingsFromForm({
84
+ value: "10:00:00"
85
+ })).toEqual({
86
+ value: "10:00:00"
87
+ });
88
+ });
89
+ it("round-trips what it opens", ()=>{
90
+ for (const expression of [
91
+ "today-18y",
92
+ "today+3m",
93
+ "today-100y",
94
+ "today+1d"
95
+ ]){
96
+ const form = dateLimitSettingsToForm({
97
+ expression
98
+ }, context("date"));
99
+ expect(dateLimitSettingsFromForm(form)).toEqual({
100
+ expression
101
+ });
102
+ }
103
+ });
104
+ it("builds expressions", ()=>{
105
+ expect(toDateExpression(18, "y", "before")).toBe("today-18y");
106
+ expect(toDateExpression(2, "m", "after")).toBe("today+2m");
107
+ expect(toDateExpression(0, "y", "before")).toBe("today");
108
+ });
109
+ });
110
+
111
+ //# sourceMappingURL=dateLimitSettings.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/fieldValidators/validators/dateLimitSettings.test.js","sources":["../../../../src/presentation/fieldValidators/validators/dateLimitSettings.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport type { CmsModelField } from \"~/types.js\";\nimport {\n dateLimitSettingsFromForm,\n dateLimitSettingsToForm,\n toDateExpression\n} from \"./dateLimitSettings.js\";\n\nconst context = (type?: string) => ({\n field: { type: \"datetime\", settings: type ? { type } : {} } as unknown as CmsModelField\n});\n\ndescribe(\"date limit settings\", () => {\n it(\"opens a relative limit as an amount, a unit and a direction\", () => {\n expect(dateLimitSettingsToForm({ expression: \"today-18y\" }, context(\"date\"))).toEqual({\n mode: \"relative\",\n amount: 18,\n unit: \"y\",\n direction: \"before\"\n });\n expect(dateLimitSettingsToForm({ expression: \"today+1d\" }, context(\"date\"))).toEqual({\n mode: \"relative\",\n amount: 1,\n unit: \"d\",\n direction: \"after\"\n });\n expect(dateLimitSettingsToForm({ expression: \"today\" }, context())).toMatchObject({\n mode: \"relative\",\n amount: 0\n });\n });\n\n it(\"opens a fixed limit as a fixed date\", () => {\n expect(dateLimitSettingsToForm({ value: \"2000-12-31\" }, context(\"date\"))).toEqual({\n value: \"2000-12-31\",\n mode: \"fixed\",\n unit: \"y\",\n direction: \"before\"\n });\n });\n\n it(\"leaves the settings of a time or datetime field as they are\", () => {\n expect(dateLimitSettingsToForm({ value: \"10:00:00\" }, context(\"time\"))).toEqual({\n value: \"10:00:00\"\n });\n });\n\n it(\"saves a relative limit as an expression, without the form's own values\", () => {\n expect(\n dateLimitSettingsFromForm({\n mode: \"relative\",\n value: \"2000-12-31\",\n amount: 18,\n unit: \"y\",\n direction: \"before\"\n })\n ).toEqual({ expression: \"today-18y\" });\n expect(\n dateLimitSettingsFromForm({\n mode: \"relative\",\n amount: 0,\n unit: \"d\",\n direction: \"after\"\n })\n ).toEqual({ expression: \"today\" });\n });\n\n it(\"saves a fixed limit as a value, dropping an earlier expression\", () => {\n expect(\n dateLimitSettingsFromForm({\n mode: \"fixed\",\n value: \"2000-12-31\",\n expression: \"today-18y\",\n amount: 18,\n unit: \"y\",\n direction: \"before\"\n })\n ).toEqual({ value: \"2000-12-31\" });\n // A time or datetime field's form has only the value.\n expect(dateLimitSettingsFromForm({ value: \"10:00:00\" })).toEqual({ value: \"10:00:00\" });\n });\n\n it(\"round-trips what it opens\", () => {\n for (const expression of [\"today-18y\", \"today+3m\", \"today-100y\", \"today+1d\"]) {\n const form = dateLimitSettingsToForm({ expression }, context(\"date\"));\n expect(dateLimitSettingsFromForm(form)).toEqual({ expression });\n }\n });\n\n it(\"builds expressions\", () => {\n expect(toDateExpression(18, \"y\", \"before\")).toBe(\"today-18y\");\n expect(toDateExpression(2, \"m\", \"after\")).toBe(\"today+2m\");\n expect(toDateExpression(0, \"y\", \"before\")).toBe(\"today\");\n });\n});\n"],"names":["context","type","describe","it","expect","dateLimitSettingsToForm","dateLimitSettingsFromForm","expression","form","toDateExpression"],"mappings":";;AAQA,MAAMA,UAAU,CAACC,OAAmB;QAChC,OAAO;YAAE,MAAM;YAAY,UAAUA,OAAO;gBAAEA;YAAK,IAAI,CAAC;QAAE;IAC9D;AAEAC,SAAS,uBAAuB;IAC5BC,GAAG,+DAA+D;QAC9DC,OAAOC,wBAAwB;YAAE,YAAY;QAAY,GAAGL,QAAQ,UAAU,OAAO,CAAC;YAClF,MAAM;YACN,QAAQ;YACR,MAAM;YACN,WAAW;QACf;QACAI,OAAOC,wBAAwB;YAAE,YAAY;QAAW,GAAGL,QAAQ,UAAU,OAAO,CAAC;YACjF,MAAM;YACN,QAAQ;YACR,MAAM;YACN,WAAW;QACf;QACAI,OAAOC,wBAAwB;YAAE,YAAY;QAAQ,GAAGL,YAAY,aAAa,CAAC;YAC9E,MAAM;YACN,QAAQ;QACZ;IACJ;IAEAG,GAAG,uCAAuC;QACtCC,OAAOC,wBAAwB;YAAE,OAAO;QAAa,GAAGL,QAAQ,UAAU,OAAO,CAAC;YAC9E,OAAO;YACP,MAAM;YACN,MAAM;YACN,WAAW;QACf;IACJ;IAEAG,GAAG,+DAA+D;QAC9DC,OAAOC,wBAAwB;YAAE,OAAO;QAAW,GAAGL,QAAQ,UAAU,OAAO,CAAC;YAC5E,OAAO;QACX;IACJ;IAEAG,GAAG,0EAA0E;QACzEC,OACIE,0BAA0B;YACtB,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,WAAW;QACf,IACF,OAAO,CAAC;YAAE,YAAY;QAAY;QACpCF,OACIE,0BAA0B;YACtB,MAAM;YACN,QAAQ;YACR,MAAM;YACN,WAAW;QACf,IACF,OAAO,CAAC;YAAE,YAAY;QAAQ;IACpC;IAEAH,GAAG,kEAAkE;QACjEC,OACIE,0BAA0B;YACtB,MAAM;YACN,OAAO;YACP,YAAY;YACZ,QAAQ;YACR,MAAM;YACN,WAAW;QACf,IACF,OAAO,CAAC;YAAE,OAAO;QAAa;QAEhCF,OAAOE,0BAA0B;YAAE,OAAO;QAAW,IAAI,OAAO,CAAC;YAAE,OAAO;QAAW;IACzF;IAEAH,GAAG,6BAA6B;QAC5B,KAAK,MAAMI,cAAc;YAAC;YAAa;YAAY;YAAc;SAAW,CAAE;YAC1E,MAAMC,OAAOH,wBAAwB;gBAAEE;YAAW,GAAGP,QAAQ;YAC7DI,OAAOE,0BAA0BE,OAAO,OAAO,CAAC;gBAAED;YAAW;QACjE;IACJ;IAEAJ,GAAG,sBAAsB;QACrBC,OAAOK,iBAAiB,IAAI,KAAK,WAAW,IAAI,CAAC;QACjDL,OAAOK,iBAAiB,GAAG,KAAK,UAAU,IAAI,CAAC;QAC/CL,OAAOK,iBAAiB,GAAG,KAAK,WAAW,IAAI,CAAC;IACpD;AACJ"}