@carlonicora/nextjs-jsonapi 1.110.0 → 1.111.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 (123) hide show
  1. package/dist/scripts/generate-web-module/__tests__/container.spec.d.ts +2 -0
  2. package/dist/scripts/generate-web-module/__tests__/container.spec.d.ts.map +1 -0
  3. package/dist/scripts/generate-web-module/__tests__/container.spec.js +54 -0
  4. package/dist/scripts/generate-web-module/__tests__/container.spec.js.map +1 -0
  5. package/dist/scripts/generate-web-module/__tests__/data-service.spec.d.ts +2 -0
  6. package/dist/scripts/generate-web-module/__tests__/data-service.spec.d.ts.map +1 -0
  7. package/dist/scripts/generate-web-module/__tests__/data-service.spec.js +19 -0
  8. package/dist/scripts/generate-web-module/__tests__/data-service.spec.js.map +1 -0
  9. package/dist/scripts/generate-web-module/__tests__/editor.spec.d.ts +2 -0
  10. package/dist/scripts/generate-web-module/__tests__/editor.spec.d.ts.map +1 -0
  11. package/dist/scripts/generate-web-module/__tests__/editor.spec.js +35 -0
  12. package/dist/scripts/generate-web-module/__tests__/editor.spec.js.map +1 -0
  13. package/dist/scripts/generate-web-module/__tests__/fixtures.d.ts +4 -0
  14. package/dist/scripts/generate-web-module/__tests__/fixtures.d.ts.map +1 -0
  15. package/dist/scripts/generate-web-module/__tests__/fixtures.js +45 -0
  16. package/dist/scripts/generate-web-module/__tests__/fixtures.js.map +1 -0
  17. package/dist/scripts/generate-web-module/__tests__/model-interface.spec.d.ts +2 -0
  18. package/dist/scripts/generate-web-module/__tests__/model-interface.spec.d.ts.map +1 -0
  19. package/dist/scripts/generate-web-module/__tests__/model-interface.spec.js +74 -0
  20. package/dist/scripts/generate-web-module/__tests__/model-interface.spec.js.map +1 -0
  21. package/dist/scripts/generate-web-module/__tests__/plumbing.spec.d.ts +2 -0
  22. package/dist/scripts/generate-web-module/__tests__/plumbing.spec.d.ts.map +1 -0
  23. package/dist/scripts/generate-web-module/__tests__/plumbing.spec.js +21 -0
  24. package/dist/scripts/generate-web-module/__tests__/plumbing.spec.js.map +1 -0
  25. package/dist/scripts/generate-web-module/__tests__/selector.spec.d.ts +2 -0
  26. package/dist/scripts/generate-web-module/__tests__/selector.spec.d.ts.map +1 -0
  27. package/dist/scripts/generate-web-module/__tests__/selector.spec.js +25 -0
  28. package/dist/scripts/generate-web-module/__tests__/selector.spec.js.map +1 -0
  29. package/dist/scripts/generate-web-module/__tests__/table-module-list.spec.d.ts +2 -0
  30. package/dist/scripts/generate-web-module/__tests__/table-module-list.spec.d.ts.map +1 -0
  31. package/dist/scripts/generate-web-module/__tests__/table-module-list.spec.js +55 -0
  32. package/dist/scripts/generate-web-module/__tests__/table-module-list.spec.js.map +1 -0
  33. package/dist/scripts/generate-web-module/generator.d.ts.map +1 -1
  34. package/dist/scripts/generate-web-module/generator.js +14 -11
  35. package/dist/scripts/generate-web-module/generator.js.map +1 -1
  36. package/dist/scripts/generate-web-module/templates/components/container.template.d.ts +5 -1
  37. package/dist/scripts/generate-web-module/templates/components/container.template.d.ts.map +1 -1
  38. package/dist/scripts/generate-web-module/templates/components/container.template.js +43 -63
  39. package/dist/scripts/generate-web-module/templates/components/container.template.js.map +1 -1
  40. package/dist/scripts/generate-web-module/templates/components/content.template.d.ts +7 -4
  41. package/dist/scripts/generate-web-module/templates/components/content.template.d.ts.map +1 -1
  42. package/dist/scripts/generate-web-module/templates/components/content.template.js +103 -14
  43. package/dist/scripts/generate-web-module/templates/components/content.template.js.map +1 -1
  44. package/dist/scripts/generate-web-module/templates/components/editor.template.d.ts +1 -1
  45. package/dist/scripts/generate-web-module/templates/components/editor.template.js +139 -150
  46. package/dist/scripts/generate-web-module/templates/components/editor.template.js.map +1 -1
  47. package/dist/scripts/generate-web-module/templates/components/index.d.ts +0 -1
  48. package/dist/scripts/generate-web-module/templates/components/index.d.ts.map +1 -1
  49. package/dist/scripts/generate-web-module/templates/components/index.js +1 -3
  50. package/dist/scripts/generate-web-module/templates/components/index.js.map +1 -1
  51. package/dist/scripts/generate-web-module/templates/components/list-container.template.js +2 -2
  52. package/dist/scripts/generate-web-module/templates/components/list.template.d.ts.map +1 -1
  53. package/dist/scripts/generate-web-module/templates/components/list.template.js +6 -1
  54. package/dist/scripts/generate-web-module/templates/components/list.template.js.map +1 -1
  55. package/dist/scripts/generate-web-module/templates/components/selector.template.d.ts.map +1 -1
  56. package/dist/scripts/generate-web-module/templates/components/selector.template.js +48 -52
  57. package/dist/scripts/generate-web-module/templates/components/selector.template.js.map +1 -1
  58. package/dist/scripts/generate-web-module/templates/data/interface.template.d.ts.map +1 -1
  59. package/dist/scripts/generate-web-module/templates/data/interface.template.js +38 -11
  60. package/dist/scripts/generate-web-module/templates/data/interface.template.js.map +1 -1
  61. package/dist/scripts/generate-web-module/templates/data/model.template.d.ts.map +1 -1
  62. package/dist/scripts/generate-web-module/templates/data/model.template.js +83 -26
  63. package/dist/scripts/generate-web-module/templates/data/model.template.js.map +1 -1
  64. package/dist/scripts/generate-web-module/templates/data/service.template.d.ts.map +1 -1
  65. package/dist/scripts/generate-web-module/templates/data/service.template.js +21 -1
  66. package/dist/scripts/generate-web-module/templates/data/service.template.js.map +1 -1
  67. package/dist/scripts/generate-web-module/templates/index.d.ts +1 -1
  68. package/dist/scripts/generate-web-module/templates/index.d.ts.map +1 -1
  69. package/dist/scripts/generate-web-module/templates/index.js +1 -2
  70. package/dist/scripts/generate-web-module/templates/index.js.map +1 -1
  71. package/dist/scripts/generate-web-module/templates/module.template.d.ts.map +1 -1
  72. package/dist/scripts/generate-web-module/templates/module.template.js +11 -3
  73. package/dist/scripts/generate-web-module/templates/module.template.js.map +1 -1
  74. package/dist/scripts/generate-web-module/templates/table-hook.template.js +31 -1
  75. package/dist/scripts/generate-web-module/templates/table-hook.template.js.map +1 -1
  76. package/dist/scripts/generate-web-module/transformers/import-resolver.d.ts +0 -1
  77. package/dist/scripts/generate-web-module/transformers/import-resolver.d.ts.map +1 -1
  78. package/dist/scripts/generate-web-module/transformers/import-resolver.js +0 -1
  79. package/dist/scripts/generate-web-module/transformers/import-resolver.js.map +1 -1
  80. package/dist/scripts/generate-web-module/transformers/relationship-key.d.ts +5 -0
  81. package/dist/scripts/generate-web-module/transformers/relationship-key.d.ts.map +1 -0
  82. package/dist/scripts/generate-web-module/transformers/relationship-key.js +21 -0
  83. package/dist/scripts/generate-web-module/transformers/relationship-key.js.map +1 -0
  84. package/dist/scripts/generate-web-module/transformers/relationship-resolver.d.ts.map +1 -1
  85. package/dist/scripts/generate-web-module/transformers/relationship-resolver.js +2 -0
  86. package/dist/scripts/generate-web-module/transformers/relationship-resolver.js.map +1 -1
  87. package/dist/scripts/generate-web-module/types/json-schema.interface.d.ts +21 -0
  88. package/dist/scripts/generate-web-module/types/json-schema.interface.d.ts.map +1 -1
  89. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts +17 -0
  90. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts.map +1 -1
  91. package/package.json +1 -1
  92. package/scripts/generate-web-module/__tests__/container.spec.ts +58 -0
  93. package/scripts/generate-web-module/__tests__/data-service.spec.ts +18 -0
  94. package/scripts/generate-web-module/__tests__/editor.spec.ts +36 -0
  95. package/scripts/generate-web-module/__tests__/fixtures.ts +43 -0
  96. package/scripts/generate-web-module/__tests__/model-interface.spec.ts +77 -0
  97. package/scripts/generate-web-module/__tests__/plumbing.spec.ts +21 -0
  98. package/scripts/generate-web-module/__tests__/selector.spec.ts +24 -0
  99. package/scripts/generate-web-module/__tests__/table-module-list.spec.ts +59 -0
  100. package/scripts/generate-web-module/generator.ts +14 -13
  101. package/scripts/generate-web-module/templates/components/container.template.ts +51 -66
  102. package/scripts/generate-web-module/templates/components/content.template.ts +107 -15
  103. package/scripts/generate-web-module/templates/components/editor.template.ts +140 -152
  104. package/scripts/generate-web-module/templates/components/index.ts +0 -1
  105. package/scripts/generate-web-module/templates/components/list-container.template.ts +2 -2
  106. package/scripts/generate-web-module/templates/components/list.template.ts +6 -1
  107. package/scripts/generate-web-module/templates/components/selector.template.ts +48 -52
  108. package/scripts/generate-web-module/templates/data/interface.template.ts +44 -12
  109. package/scripts/generate-web-module/templates/data/model.template.ts +88 -28
  110. package/scripts/generate-web-module/templates/data/service.template.ts +23 -1
  111. package/scripts/generate-web-module/templates/index.ts +0 -1
  112. package/scripts/generate-web-module/templates/module.template.ts +13 -3
  113. package/scripts/generate-web-module/templates/table-hook.template.ts +31 -2
  114. package/scripts/generate-web-module/transformers/import-resolver.ts +0 -2
  115. package/scripts/generate-web-module/transformers/relationship-key.ts +18 -0
  116. package/scripts/generate-web-module/transformers/relationship-resolver.ts +2 -0
  117. package/scripts/generate-web-module/types/json-schema.interface.ts +9 -0
  118. package/scripts/generate-web-module/types/template-data.interface.ts +7 -0
  119. package/dist/scripts/generate-web-module/templates/components/details.template.d.ts +0 -14
  120. package/dist/scripts/generate-web-module/templates/components/details.template.d.ts.map +0 -1
  121. package/dist/scripts/generate-web-module/templates/components/details.template.js +0 -112
  122. package/dist/scripts/generate-web-module/templates/components/details.template.js.map +0 -1
  123. package/scripts/generate-web-module/templates/components/details.template.ts +0 -116
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { FrontendTemplateData, FrontendField } from "../types/template-data.interface";
8
- import { toCamelCase } from "../transformers/name-transformer";
8
+ import { toCamelCase, pluralize } from "../transformers/name-transformer";
9
9
 
10
10
  /**
11
11
  * Generate the table structure hook file content
@@ -96,7 +96,7 @@ registerTableGenerator(Modules.${names.pascalCase}, use${names.pascalCase}TableS
96
96
  * Generate field column map entries
97
97
  */
98
98
  function generateFieldColumnEntries(data: FrontendTemplateData): string {
99
- const { names, fields, extendsContent } = data;
99
+ const { names, fields, extendsContent, relationships } = data;
100
100
  const entries: string[] = [];
101
101
 
102
102
  // Name field (with link and tooltip for tldr if Content-extending)
@@ -183,8 +183,37 @@ function generateFieldColumnEntries(data: FrontendTemplateData): string {
183
183
  enableSorting: false,
184
184
  enableHiding: false,
185
185
  }),`);
186
+ } else if (field.type === "date" || field.type === "datetime") {
187
+ entries.push(` [${names.pascalCase}Fields.${field.name}]: () =>
188
+ cellDate({
189
+ name: "${field.name}",
190
+ title: t(\`features.${names.camelCase}.fields.${field.name}.label\`),
191
+ }),`);
186
192
  }
187
193
  });
188
194
 
195
+ // Relationship columns (rendered when flagged for table display)
196
+ relationships
197
+ .filter((rel) => rel.showInTable)
198
+ .forEach((rel) => {
199
+ const key = rel.single
200
+ ? toCamelCase(rel.alias || rel.variant || rel.name)
201
+ : pluralize(toCamelCase(rel.alias || rel.name));
202
+ const accessor = rel.single
203
+ ? `${names.camelCase}.${key}?.name ?? ""`
204
+ : `${names.camelCase}.${key}.map((r) => r.name).join(", ")`;
205
+ entries.push(` [${names.pascalCase}Fields.${key}]: () => ({
206
+ id: "${key}",
207
+ accessorKey: "${key}",
208
+ header: t(\`generic.relationships.${key}.label\`),
209
+ cell: ({ row }: { row: TableContent<${names.pascalCase}Interface> }) => {
210
+ const ${names.camelCase}: ${names.pascalCase}Interface = row.original.jsonApiData;
211
+ return <span>{${accessor}}</span>;
212
+ },
213
+ enableSorting: false,
214
+ enableHiding: false,
215
+ }),`);
216
+ });
217
+
189
218
  return entries.join("\n");
190
219
  }
@@ -177,7 +177,6 @@ export interface ModuleFilePaths {
177
177
  selector: string;
178
178
  multiSelector: string;
179
179
  list: string;
180
- details: string;
181
180
  content: string;
182
181
  container: string;
183
182
  listContainer: string;
@@ -220,7 +219,6 @@ export function buildFilePaths(
220
219
  selector: `${basePath}/components/forms/${names.pascalCase}Selector.tsx`,
221
220
  multiSelector: `${basePath}/components/forms/${names.pascalCase}MultiSelector.tsx`,
222
221
  list: `${basePath}/components/lists/${names.pascalCase}List.tsx`,
223
- details: `${basePath}/components/details/${names.pascalCase}Details.tsx`,
224
222
  content: `${basePath}/components/details/${names.pascalCase}Content.tsx`,
225
223
  container: `${basePath}/components/containers/${names.pascalCase}Container.tsx`,
226
224
  listContainer: `${basePath}/components/containers/${names.pascalCase}ListContainer.tsx`,
@@ -0,0 +1,18 @@
1
+ import { FrontendRelationship } from "../types/template-data.interface";
2
+ import { toKebabCase, pluralize } from "./name-transformer";
3
+
4
+ /** JSON:API wire key for a relationship. Schema dtoKey wins; otherwise derive
5
+ * identically to the backend mapper so both sides of the wire agree. */
6
+ export function resolveRelationshipKey(rel: FrontendRelationship): string {
7
+ if (rel.dtoKey) return rel.dtoKey;
8
+ // NOTE: Author relationships are normally NOT serialized through this helper — the backend
9
+ // special-cases Author via contextKey/currentUser and the model template skips Author
10
+ // serialization, so callers must not rely on this helper for Author wire keys.
11
+ if (rel.variant) {
12
+ return rel.single ? rel.variant.toLowerCase() : pluralize(rel.variant.toLowerCase());
13
+ }
14
+ if (rel.alias) {
15
+ return rel.single ? toKebabCase(rel.alias) : pluralize(toKebabCase(rel.alias));
16
+ }
17
+ return rel.single ? rel.name.toLowerCase() : pluralize(rel.name.toLowerCase());
18
+ }
@@ -122,6 +122,8 @@ export function resolveRelationship(rel: JsonRelationshipDefinition, targetHasNa
122
122
  modelKebab,
123
123
  fields,
124
124
  targetHasName: targetHasNameMap?.get(rel.name) ?? true, // Foundation entities default to true
125
+ dtoKey: rel.dtoKey ?? "",
126
+ showInTable: rel.showInTable === true,
125
127
  };
126
128
  }
127
129
 
@@ -13,6 +13,7 @@ export interface JsonFieldDefinition {
13
13
  name: string;
14
14
  type: string;
15
15
  nullable: boolean;
16
+ readOnly?: boolean;
16
17
  }
17
18
 
18
19
  /**
@@ -29,6 +30,10 @@ export interface JsonRelationshipDefinition {
29
30
  toNode: boolean; // Backend-specific, ignored in frontend
30
31
  nullable: boolean;
31
32
  fields?: JsonFieldDefinition[]; // Relationship property fields (stored on edges)
33
+ /** Explicit JSON:API wire key. When absent it is derived identically to the backend mapper. */
34
+ dtoKey?: string;
35
+ description?: string;
36
+ showInTable?: boolean;
32
37
  }
33
38
 
34
39
  /**
@@ -44,4 +49,8 @@ export interface JsonModuleDefinition {
44
49
  relationships: JsonRelationshipDefinition[];
45
50
  /** Explicitly set whether this module extends Content. If not set, auto-detects based on fields. */
46
51
  extendsContent?: boolean;
52
+ featureId?: string;
53
+ displayProp?: string;
54
+ containerTabs?: { activity?: boolean; relations?: { module: string; listProp: string; directory: string }[] };
55
+ inclusions?: { related?: { endpoint: string; fields: string[] }[] };
47
56
  }
@@ -30,6 +30,7 @@ export interface FrontendField {
30
30
  formComponent: FormComponentType;
31
31
  nullable: boolean;
32
32
  isContentField: boolean; // Indicates BlockNoteEditor
33
+ readOnly?: boolean;
33
34
  }
34
35
 
35
36
  /**
@@ -68,6 +69,8 @@ export interface FrontendRelationship {
68
69
  modelKebab: string; // e.g., "user"
69
70
  fields?: FrontendField[]; // Relationship property fields (stored on edges)
70
71
  targetHasName: boolean; // Whether the target entity has a "name" field (or extends Content)
72
+ dtoKey: string; // resolved wire key; "" means derive at use-site
73
+ showInTable: boolean;
71
74
  }
72
75
 
73
76
  /**
@@ -153,6 +156,10 @@ export interface FrontendTemplateData {
153
156
 
154
157
  // For service generation
155
158
  relationshipServiceMethods: RelationshipServiceMethod[];
159
+ featureId?: string;
160
+ displayProp: string;
161
+ containerTabs: { activity: boolean; relations: { module: string; listProp: string; directory: string }[] };
162
+ relatedInclusions: { endpoint: string; fields: string[] }[];
156
163
  }
157
164
 
158
165
  /**
@@ -1,14 +0,0 @@
1
- /**
2
- * Details Template
3
- *
4
- * Generates {Module}Details.tsx component for displaying item details.
5
- */
6
- import { FrontendTemplateData } from "../../types/template-data.interface";
7
- /**
8
- * Generate the details component file content
9
- *
10
- * @param data - Frontend template data
11
- * @returns Generated file content
12
- */
13
- export declare function generateDetailsTemplate(data: FrontendTemplateData): string;
14
- //# sourceMappingURL=details.template.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"details.template.d.ts","sourceRoot":"","sources":["../../../../../scripts/generate-web-module/templates/components/details.template.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAE3E;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAmC1E"}
@@ -1,112 +0,0 @@
1
- "use strict";
2
- /**
3
- * Details Template
4
- *
5
- * Generates {Module}Details.tsx component for displaying item details.
6
- */
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.generateDetailsTemplate = generateDetailsTemplate;
9
- const name_transformer_1 = require("../../transformers/name-transformer");
10
- /**
11
- * Generate the details component file content
12
- *
13
- * @param data - Frontend template data
14
- * @returns Generated file content
15
- */
16
- function generateDetailsTemplate(data) {
17
- const { names, fields, relationships, extendsContent } = data;
18
- const attributeElements = generateAttributeElements(data);
19
- return `"use client";
20
-
21
- import { use${names.pascalCase}Context } from "@/features/${data.importTargetDir}/${names.kebabCase}/contexts/${names.pascalCase}Context";
22
- import { AttributeElement, ContentTitle, ReactMarkdownContainer } from "@carlonicora/nextjs-jsonapi/components";
23
- import { useSharedContext } from "@carlonicora/nextjs-jsonapi/contexts";
24
- import { Modules } from "@carlonicora/nextjs-jsonapi/core";
25
- import { useTranslations } from "next-intl";
26
-
27
- function ${names.pascalCase}DetailsInternal() {
28
- const { ${names.camelCase}, reload${names.pascalCase} } = use${names.pascalCase}Context();
29
- const t = useTranslations();
30
- const { title } = useSharedContext();
31
-
32
- if (!${names.camelCase}) return null;
33
-
34
- return (
35
- <div className="flex w-full flex-col gap-y-2">
36
- <ContentTitle type={title.type} element={title.element} functions={title.functions} module={Modules.${names.pascalCase}} />
37
- ${attributeElements}
38
- </div>
39
- );
40
- }
41
-
42
- export default function ${names.pascalCase}Details() {
43
- const { ${names.camelCase} } = use${names.pascalCase}Context();
44
- if (!${names.camelCase}) return null;
45
-
46
- return <${names.pascalCase}DetailsInternal />;
47
- }
48
- `;
49
- }
50
- /**
51
- * Generate attribute elements for display fields
52
- */
53
- function generateAttributeElements(data) {
54
- const { names, fields, relationships, extendsContent } = data;
55
- const elements = [];
56
- // Show abstract if Content-extending
57
- if (extendsContent) {
58
- elements.push(` <AttributeElement
59
- title={t(\`generic.abstract\`)}
60
- value={<ReactMarkdownContainer size="small" content={${names.camelCase}.abstract} />}
61
- />`);
62
- }
63
- // Add custom fields (excluding name, tldr, abstract, content which are handled elsewhere)
64
- const displayableFields = fields.filter((f) => !["name", "tldr", "abstract", "content", "id"].includes(f.name));
65
- displayableFields.forEach((field) => {
66
- if (field.type === "string") {
67
- elements.push(` <AttributeElement
68
- title={t(\`features.${names.camelCase}.fields.${field.name}.label\`)}
69
- value={${names.camelCase}.${field.name}}
70
- />`);
71
- }
72
- else if (field.type === "boolean") {
73
- elements.push(` <AttributeElement
74
- title={t(\`features.${names.camelCase}.fields.${field.name}.label\`)}
75
- value={${names.camelCase}.${field.name} ? t(\`generic.yes\`) : t(\`generic.no\`)}
76
- />`);
77
- }
78
- else if (field.type === "number") {
79
- elements.push(` <AttributeElement
80
- title={t(\`features.${names.camelCase}.fields.${field.name}.label\`)}
81
- value={${names.camelCase}.${field.name}?.toString()}
82
- />`);
83
- }
84
- });
85
- // Add relationship displays (basic - can be enhanced manually)
86
- relationships
87
- .filter((rel) => rel.variant !== "Author") // Skip author, usually shown in title
88
- .forEach((rel) => {
89
- const displayProp = rel.targetHasName ? "name" : "id";
90
- if (rel.single) {
91
- const propName = (0, name_transformer_1.toCamelCase)(rel.alias || rel.variant || rel.name);
92
- elements.push(` {${names.camelCase}.${propName} && (
93
- <AttributeElement
94
- title={t(\`generic.relationships.${propName}.label\`)}
95
- value={${names.camelCase}.${propName}.${displayProp}}
96
- />
97
- )}`);
98
- }
99
- else {
100
- const effectiveMany = rel.alias || rel.name;
101
- const propName = (0, name_transformer_1.pluralize)((0, name_transformer_1.toCamelCase)(effectiveMany));
102
- elements.push(` {${names.camelCase}.${propName} && ${names.camelCase}.${propName}.length > 0 && (
103
- <AttributeElement
104
- title={t(\`entities.${(0, name_transformer_1.pluralize)(rel.name.toLowerCase())}\`, { count: 2 })}
105
- value={${names.camelCase}.${propName}.map((item) => item.${displayProp}).join(", ")}
106
- />
107
- )}`);
108
- }
109
- });
110
- return elements.join("\n");
111
- }
112
- //# sourceMappingURL=details.template.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"details.template.js","sourceRoot":"","sources":["../../../../../scripts/generate-web-module/templates/components/details.template.ts"],"names":[],"mappings":"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"}
@@ -1,116 +0,0 @@
1
- /**
2
- * Details Template
3
- *
4
- * Generates {Module}Details.tsx component for displaying item details.
5
- */
6
-
7
- import { pluralize, toCamelCase } from "../../transformers/name-transformer";
8
- import { FrontendTemplateData } from "../../types/template-data.interface";
9
-
10
- /**
11
- * Generate the details component file content
12
- *
13
- * @param data - Frontend template data
14
- * @returns Generated file content
15
- */
16
- export function generateDetailsTemplate(data: FrontendTemplateData): string {
17
- const { names, fields, relationships, extendsContent } = data;
18
-
19
- const attributeElements = generateAttributeElements(data);
20
-
21
- return `"use client";
22
-
23
- import { use${names.pascalCase}Context } from "@/features/${data.importTargetDir}/${names.kebabCase}/contexts/${names.pascalCase}Context";
24
- import { AttributeElement, ContentTitle, ReactMarkdownContainer } from "@carlonicora/nextjs-jsonapi/components";
25
- import { useSharedContext } from "@carlonicora/nextjs-jsonapi/contexts";
26
- import { Modules } from "@carlonicora/nextjs-jsonapi/core";
27
- import { useTranslations } from "next-intl";
28
-
29
- function ${names.pascalCase}DetailsInternal() {
30
- const { ${names.camelCase}, reload${names.pascalCase} } = use${names.pascalCase}Context();
31
- const t = useTranslations();
32
- const { title } = useSharedContext();
33
-
34
- if (!${names.camelCase}) return null;
35
-
36
- return (
37
- <div className="flex w-full flex-col gap-y-2">
38
- <ContentTitle type={title.type} element={title.element} functions={title.functions} module={Modules.${names.pascalCase}} />
39
- ${attributeElements}
40
- </div>
41
- );
42
- }
43
-
44
- export default function ${names.pascalCase}Details() {
45
- const { ${names.camelCase} } = use${names.pascalCase}Context();
46
- if (!${names.camelCase}) return null;
47
-
48
- return <${names.pascalCase}DetailsInternal />;
49
- }
50
- `;
51
- }
52
-
53
- /**
54
- * Generate attribute elements for display fields
55
- */
56
- function generateAttributeElements(data: FrontendTemplateData): string {
57
- const { names, fields, relationships, extendsContent } = data;
58
- const elements: string[] = [];
59
-
60
- // Show abstract if Content-extending
61
- if (extendsContent) {
62
- elements.push(` <AttributeElement
63
- title={t(\`generic.abstract\`)}
64
- value={<ReactMarkdownContainer size="small" content={${names.camelCase}.abstract} />}
65
- />`);
66
- }
67
-
68
- // Add custom fields (excluding name, tldr, abstract, content which are handled elsewhere)
69
- const displayableFields = fields.filter((f) => !["name", "tldr", "abstract", "content", "id"].includes(f.name));
70
-
71
- displayableFields.forEach((field) => {
72
- if (field.type === "string") {
73
- elements.push(` <AttributeElement
74
- title={t(\`features.${names.camelCase}.fields.${field.name}.label\`)}
75
- value={${names.camelCase}.${field.name}}
76
- />`);
77
- } else if (field.type === "boolean") {
78
- elements.push(` <AttributeElement
79
- title={t(\`features.${names.camelCase}.fields.${field.name}.label\`)}
80
- value={${names.camelCase}.${field.name} ? t(\`generic.yes\`) : t(\`generic.no\`)}
81
- />`);
82
- } else if (field.type === "number") {
83
- elements.push(` <AttributeElement
84
- title={t(\`features.${names.camelCase}.fields.${field.name}.label\`)}
85
- value={${names.camelCase}.${field.name}?.toString()}
86
- />`);
87
- }
88
- });
89
-
90
- // Add relationship displays (basic - can be enhanced manually)
91
- relationships
92
- .filter((rel) => rel.variant !== "Author") // Skip author, usually shown in title
93
- .forEach((rel) => {
94
- const displayProp = rel.targetHasName ? "name" : "id";
95
- if (rel.single) {
96
- const propName = toCamelCase(rel.alias || rel.variant || rel.name);
97
- elements.push(` {${names.camelCase}.${propName} && (
98
- <AttributeElement
99
- title={t(\`generic.relationships.${propName}.label\`)}
100
- value={${names.camelCase}.${propName}.${displayProp}}
101
- />
102
- )}`);
103
- } else {
104
- const effectiveMany = rel.alias || rel.name;
105
- const propName = pluralize(toCamelCase(effectiveMany));
106
- elements.push(` {${names.camelCase}.${propName} && ${names.camelCase}.${propName}.length > 0 && (
107
- <AttributeElement
108
- title={t(\`entities.${pluralize(rel.name.toLowerCase())}\`, { count: 2 })}
109
- value={${names.camelCase}.${propName}.map((item) => item.${displayProp}).join(", ")}
110
- />
111
- )}`);
112
- }
113
- });
114
-
115
- return elements.join("\n");
116
- }