@khester/create-dynamics-app 1.1.0 → 2.1.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 (210) hide show
  1. package/README.md +74 -0
  2. package/dist/artifacts/registry.d.ts +18 -0
  3. package/dist/artifacts/registry.d.ts.map +1 -0
  4. package/dist/artifacts/registry.js +340 -0
  5. package/dist/artifacts/registry.js.map +1 -0
  6. package/dist/artifacts/types.d.ts +122 -0
  7. package/dist/artifacts/types.d.ts.map +1 -0
  8. package/dist/artifacts/types.js +7 -0
  9. package/dist/artifacts/types.js.map +1 -0
  10. package/dist/artifacts/validators.d.ts +16 -0
  11. package/dist/artifacts/validators.d.ts.map +1 -0
  12. package/dist/artifacts/validators.js +45 -0
  13. package/dist/artifacts/validators.js.map +1 -0
  14. package/dist/fromDesign.d.ts +5 -0
  15. package/dist/fromDesign.d.ts.map +1 -0
  16. package/dist/fromDesign.js +98 -0
  17. package/dist/fromDesign.js.map +1 -0
  18. package/dist/index.js +129 -177
  19. package/dist/index.js.map +1 -1
  20. package/dist/injectDevTools.d.ts +28 -0
  21. package/dist/injectDevTools.d.ts.map +1 -0
  22. package/dist/injectDevTools.js +148 -0
  23. package/dist/injectDevTools.js.map +1 -0
  24. package/dist/scaffold.d.ts +48 -0
  25. package/dist/scaffold.d.ts.map +1 -0
  26. package/dist/scaffold.js +180 -0
  27. package/dist/scaffold.js.map +1 -0
  28. package/dist/templatePlan.d.ts +3 -0
  29. package/dist/templatePlan.d.ts.map +1 -0
  30. package/dist/templatePlan.js +43 -0
  31. package/dist/templatePlan.js.map +1 -0
  32. package/dist/utils/copyTemplate.d.ts +13 -1
  33. package/dist/utils/copyTemplate.d.ts.map +1 -1
  34. package/dist/utils/copyTemplate.js +98 -4
  35. package/dist/utils/copyTemplate.js.map +1 -1
  36. package/dist/utils/updatePackageJson.d.ts +11 -1
  37. package/dist/utils/updatePackageJson.d.ts.map +1 -1
  38. package/dist/utils/updatePackageJson.js +12 -10
  39. package/dist/utils/updatePackageJson.js.map +1 -1
  40. package/package.json +10 -7
  41. package/templates/_shared/dev-tools/auth/get-token.js +72 -0
  42. package/templates/_shared/dev-tools/dev/mock-xrm.js +42 -0
  43. package/templates/_shared/dev-tools/metadata-sync/index.js +152 -0
  44. package/templates/_shared/dev-tools/smoke/test-retrieve.js +44 -0
  45. package/templates/dialog-form/README.md +27 -0
  46. package/templates/dialog-form/_variants/App.v8.tsx +39 -0
  47. package/templates/dialog-form/_variants/App.v9.tsx +41 -0
  48. package/templates/dialog-form/gitignore +5 -0
  49. package/templates/dialog-form/package.json +27 -0
  50. package/templates/dialog-form/public/index.html +11 -0
  51. package/templates/dialog-form/src/index.tsx +10 -0
  52. package/templates/dialog-form/src/services/dataverse.ts +30 -0
  53. package/templates/dialog-form/tsconfig.json +15 -0
  54. package/templates/dialog-form/webpack.config.js +17 -0
  55. package/templates/grid-customizer/README.md +28 -0
  56. package/templates/grid-customizer/gitignore +4 -0
  57. package/templates/grid-customizer/package.json +25 -0
  58. package/templates/grid-customizer/src/GridCustomizer.ts +28 -0
  59. package/templates/grid-customizer/src/cell-renderers.tsx +35 -0
  60. package/templates/grid-customizer/src/index.ts +4 -0
  61. package/templates/grid-customizer/src/types/grid-types.ts +30 -0
  62. package/templates/grid-customizer/src/utils/color-utils.ts +24 -0
  63. package/templates/grid-customizer/tsconfig.json +15 -0
  64. package/templates/grid-customizer/webpack.config.js +17 -0
  65. package/templates/pcf-dataset/ControlManifest.Input.xml +16 -0
  66. package/templates/pcf-dataset/README.md +21 -0
  67. package/templates/pcf-dataset/gitignore +5 -0
  68. package/templates/pcf-dataset/index.ts +39 -0
  69. package/templates/pcf-dataset/package.json +30 -0
  70. package/templates/pcf-dataset/strings/{{componentName}}.1033.resx +47 -0
  71. package/templates/pcf-dataset/tsconfig.json +8 -0
  72. package/templates/pcf-dataset/{{componentName}}Component.tsx +39 -0
  73. package/templates/pcf-field/ControlManifest.Input.xml +17 -0
  74. package/templates/pcf-field/README.md +95 -0
  75. package/templates/pcf-field/_variants/ValueInput.boolean.tsx +24 -0
  76. package/templates/pcf-field/_variants/ValueInput.date.tsx +27 -0
  77. package/templates/pcf-field/_variants/ValueInput.number.tsx +35 -0
  78. package/templates/pcf-field/_variants/ValueInput.text.tsx +27 -0
  79. package/templates/pcf-field/gitignore +5 -0
  80. package/templates/pcf-field/index.ts +61 -0
  81. package/templates/pcf-field/package.json +30 -0
  82. package/templates/pcf-field/strings/{{componentName}}.1033.resx +47 -0
  83. package/templates/pcf-field/tsconfig.json +8 -0
  84. package/templates/pcf-field/{{componentName}}Component.tsx +35 -0
  85. package/templates/power-pages-starter/gitignore +5 -0
  86. package/templates/react-custom-page/gitignore +5 -0
  87. package/templates/{dynamics-365-starter → react-custom-page}/package.json +3 -3
  88. package/templates/react-custom-page/tools/metadata-sync/index.js +152 -0
  89. package/templates/static-web-app/README.md +36 -0
  90. package/templates/static-web-app/_variants/App.v8.tsx +32 -0
  91. package/templates/static-web-app/_variants/App.v9.tsx +31 -0
  92. package/templates/static-web-app/api/host.json +12 -0
  93. package/templates/static-web-app/api/package.json +19 -0
  94. package/templates/static-web-app/api/src/functions/hello.ts +16 -0
  95. package/templates/static-web-app/api/tsconfig.json +14 -0
  96. package/templates/static-web-app/frontend/index.html +12 -0
  97. package/templates/static-web-app/frontend/package.json +23 -0
  98. package/templates/static-web-app/frontend/src/index.tsx +8 -0
  99. package/templates/static-web-app/frontend/tsconfig.json +16 -0
  100. package/templates/static-web-app/frontend/vite.config.ts +13 -0
  101. package/templates/static-web-app/gitignore +8 -0
  102. package/templates/static-web-app/package.json +15 -0
  103. package/templates/static-web-app/staticwebapp.config.json +7 -0
  104. package/templates/teams-app/README.md +27 -0
  105. package/templates/teams-app/_variants/graph.off.ts +7 -0
  106. package/templates/teams-app/_variants/graph.on.ts +22 -0
  107. package/templates/teams-app/appPackage/manifest.json +26 -0
  108. package/templates/teams-app/gitignore +5 -0
  109. package/templates/teams-app/index.html +12 -0
  110. package/templates/teams-app/package.json +26 -0
  111. package/templates/teams-app/src/App.tsx +25 -0
  112. package/templates/teams-app/src/index.tsx +8 -0
  113. package/templates/teams-app/tsconfig.json +16 -0
  114. package/templates/teams-app/vite.config.ts +9 -0
  115. package/templates/web-resource/README.md +39 -0
  116. package/templates/web-resource/_variants/App.v8.tsx +29 -0
  117. package/templates/web-resource/_variants/App.v9.tsx +28 -0
  118. package/templates/web-resource/gitignore +5 -0
  119. package/templates/web-resource/package.json +27 -0
  120. package/templates/web-resource/public/index.html +11 -0
  121. package/templates/web-resource/src/index.tsx +10 -0
  122. package/templates/web-resource/src/services/dataverse.ts +30 -0
  123. package/templates/web-resource/tsconfig.json +15 -0
  124. package/templates/web-resource/webpack.config.js +17 -0
  125. package/dist/utils/consultingHelpers.d.ts +0 -13
  126. package/dist/utils/consultingHelpers.d.ts.map +0 -1
  127. package/dist/utils/consultingHelpers.js +0 -569
  128. package/dist/utils/consultingHelpers.js.map +0 -1
  129. package/templates/dynamics-365-starter/INTEGRATION_TEST_RESULTS.md +0 -302
  130. package/templates/dynamics-365-starter/PHASE_4_COMPLETION_SUMMARY.md +0 -305
  131. package/templates/dynamics-365-starter/deployment/QUICKSTART-MAC.md +0 -507
  132. package/templates/dynamics-365-starter/deployment/QUICKSTART-WINDOWS.md +0 -372
  133. package/templates/dynamics-365-starter/deployment/pipelines/README.md +0 -375
  134. package/templates/dynamics-365-starter/deployment/pipelines/azure-pipelines.yml +0 -330
  135. package/templates/dynamics-365-starter/deployment/pipelines/github-actions.yml +0 -422
  136. package/templates/dynamics-365-starter/deployment/pipelines/jenkins.groovy +0 -636
  137. package/templates/dynamics-365-starter/deployment/scripts/deploy.ps1 +0 -417
  138. package/templates/dynamics-365-starter/deployment/scripts/deploy.sh +0 -582
  139. package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.ps1 +0 -486
  140. package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.sh +0 -567
  141. package/templates/dynamics-365-starter/deployment/scripts/validate-setup.ps1 +0 -703
  142. package/templates/dynamics-365-starter/deployment/scripts/validate-setup.sh +0 -671
  143. package/templates/dynamics-365-starter/docs/team-standards/README.md +0 -273
  144. package/templates/dynamics-365-starter/docs/team-standards/client-onboarding.md +0 -577
  145. package/templates/dynamics-365-starter/docs/team-standards/code-review-checklist.md +0 -359
  146. package/templates/dynamics-365-starter/docs/team-standards/coding-standards.md +0 -700
  147. package/templates/dynamics-365-starter/docs/team-standards/cross-platform-team-guide.md +0 -736
  148. package/templates/dynamics-365-starter/docs/team-standards/development-workflows.md +0 -727
  149. package/templates/dynamics-365-starter/docs/troubleshooting/common-errors.md +0 -758
  150. package/templates/dynamics-365-starter/docs/troubleshooting/platform-specific-issues.md +0 -878
  151. package/templates/dynamics-365-starter/src/client-project-template/README.md +0 -234
  152. package/templates/dynamics-365-starter/src/client-project-template/config/client.template.json +0 -114
  153. package/templates/dynamics-365-starter/src/client-project-template/config/environments/template.json +0 -186
  154. package/templates/dynamics-365-starter/src/client-project-template/scripts/client-setup.js +0 -667
  155. package/templates/dynamics-365-starter/src/examples/README.md +0 -52
  156. package/templates/dynamics-365-starter/src/examples/component-examples/opportunity-management.tsx +0 -625
  157. package/templates/dynamics-365-starter/src/examples/entity-examples/opportunity-model.ts +0 -545
  158. package/templates/dynamics-365-starter/src/examples/integration-examples/custom-pcf-wrapper.tsx +0 -722
  159. package/templates/dynamics-365-starter/src/examples/workflow-examples/sales-workflow.ts +0 -662
  160. package/templates/dynamics-365-starter/src/page-templates/EntityDashboard.tsx +0 -519
  161. package/templates/dynamics-365-starter/src/page-templates/EntityDetailPage.tsx +0 -456
  162. package/templates/dynamics-365-starter/src/page-templates/EntityListPage.tsx +0 -406
  163. package/templates/dynamics-365-starter/src/page-templates/RelatedEntitiesPage.tsx +0 -578
  164. package/templates/dynamics-365-starter/src/page-templates/SearchPage.tsx +0 -629
  165. package/templates/dynamics-365-starter/tools/entity-generator/index.js +0 -168
  166. package/templates/dynamics-365-starter/tools/entity-generator/templates/constants.template.ts +0 -124
  167. package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.css +0 -283
  168. package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.tsx +0 -275
  169. package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.css +0 -204
  170. package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.tsx +0 -413
  171. package/templates/dynamics-365-starter/tools/entity-generator/templates/model.template.ts +0 -250
  172. package/templates/dynamics-365-starter/tools/metadata-sync/d365-client.js +0 -410
  173. package/templates/dynamics-365-starter/tools/metadata-sync/index.js +0 -512
  174. package/templates/dynamics-365-starter/tools/metadata-sync/type-generator.js +0 -675
  175. /package/templates/{dynamics-365-starter → react-custom-page}/README.md +0 -0
  176. /package/templates/{dynamics-365-starter → react-custom-page}/deployment/README.md +0 -0
  177. /package/templates/{dynamics-365-starter → react-custom-page}/docs/ARCHITECTURE_OVERVIEW.md +0 -0
  178. /package/templates/{dynamics-365-starter → react-custom-page}/docs/BEST_PRACTICES.md +0 -0
  179. /package/templates/{dynamics-365-starter → react-custom-page}/docs/MIGRATION_GUIDE.md +0 -0
  180. /package/templates/{dynamics-365-starter → react-custom-page}/public/index.html +0 -0
  181. /package/templates/{dynamics-365-starter → react-custom-page}/scripts/custom-build.js +0 -0
  182. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountForm.css +0 -0
  183. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountForm.tsx +0 -0
  184. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountManagement.css +0 -0
  185. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountManagement.tsx +0 -0
  186. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactForm.css +0 -0
  187. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactForm.tsx +0 -0
  188. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactManagement.css +0 -0
  189. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactManagement.tsx +0 -0
  190. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LogDialog.tsx +0 -0
  191. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingContext.tsx +0 -0
  192. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingDebugPanel.css +0 -0
  193. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingDebugPanel.tsx +0 -0
  194. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingProvider.tsx +0 -0
  195. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/logger.ts +0 -0
  196. /package/templates/{dynamics-365-starter → react-custom-page}/src/constants/account.ts +0 -0
  197. /package/templates/{dynamics-365-starter → react-custom-page}/src/constants/contact.ts +0 -0
  198. /package/templates/{dynamics-365-starter → react-custom-page}/src/index.tsx +0 -0
  199. /package/templates/{dynamics-365-starter → react-custom-page}/src/models/Account.ts +0 -0
  200. /package/templates/{dynamics-365-starter → react-custom-page}/src/models/BaseEntity.ts +0 -0
  201. /package/templates/{dynamics-365-starter → react-custom-page}/src/models/Contact.ts +0 -0
  202. /package/templates/{dynamics-365-starter → react-custom-page}/src/pcf/ContactControlWrapper.tsx +0 -0
  203. /package/templates/{dynamics-365-starter → react-custom-page}/src/pcf/MultiEntityControlWrapper.tsx +0 -0
  204. /package/templates/{dynamics-365-starter → react-custom-page}/src/providers/DynamicsProvider.tsx +0 -0
  205. /package/templates/{dynamics-365-starter → react-custom-page}/src/services/MockApiService.ts +0 -0
  206. /package/templates/{dynamics-365-starter → react-custom-page}/src/services/ServiceFactory.ts +0 -0
  207. /package/templates/{dynamics-365-starter → react-custom-page}/src/services/XrmApiService.ts +0 -0
  208. /package/templates/{dynamics-365-starter → react-custom-page}/src/styles/index.css +0 -0
  209. /package/templates/{dynamics-365-starter → react-custom-page}/tsconfig.json +0 -0
  210. /package/templates/{dynamics-365-starter → react-custom-page}/webpack.config.js +0 -0
@@ -1,413 +0,0 @@
1
- import React, { useState, useEffect, useCallback } from 'react';
2
- import {
3
- DetailsList,
4
- IColumn,
5
- SelectionMode,
6
- CommandBar,
7
- ICommandBarItemProps,
8
- MessageBar,
9
- MessageBarType,
10
- Spinner,
11
- SpinnerSize,
12
- Panel,
13
- PanelType,
14
- DefaultButton,
15
- PrimaryButton,
16
- Dialog,
17
- DialogType,
18
- DialogFooter
19
- } from '@fluentui/react';
20
- // Replace 'SampleEntity' with your actual entity PascalCase name during template processing
21
- // import { SampleEntity, ISampleEntity } from '../models/SampleEntity';
22
- // import { SampleEntityForm } from './SampleEntityForm';
23
- // import { SampleEntityConstants } from '../constants/sample-entity';
24
- // import { useDynamicsApi } from '../providers/DynamicsProvider';
25
- // import { Logger } from './Logging/logger';
26
- import './SampleEntityManagement.css';
27
-
28
- // Template base entity interface - replace with actual BaseEntity during generation
29
- interface BaseEntity {
30
- id?: string;
31
- createdOn?: Date;
32
- modifiedOn?: Date;
33
- [key: string]: any;
34
- }
35
-
36
- // Template Logger - replace with actual Logger during generation
37
- const Logger = {
38
- log: (message: string, source?: string) => console.log(message, source),
39
- warn: (message: string, source?: string) => console.warn(message, source),
40
- error: (message: string, source?: string, error?: any) => console.error(message, source, error)
41
- };
42
-
43
- // Template API service hook - replace with actual useDynamicsApi during generation
44
- const useDynamicsApi = () => ({
45
- apiService: {
46
- retrieveMultipleRecords: async () => [],
47
- createRecord: async () => ({}),
48
- updateRecord: async () => ({}),
49
- deleteRecord: async () => ({})
50
- }
51
- });
52
-
53
- // Template interfaces - replace with actual entity interface during generation
54
- interface ISampleEntity {
55
- id?: string;
56
- name?: string;
57
- description?: string;
58
- priority?: number;
59
- dueDate?: Date;
60
- amount?: number;
61
- isActive?: boolean;
62
- createdOn?: Date;
63
- }
64
-
65
- class SampleEntity implements BaseEntity, ISampleEntity {
66
- id?: string;
67
- name?: string;
68
- description?: string;
69
- priority?: number;
70
- dueDate?: Date;
71
- amount?: number;
72
- isActive?: boolean;
73
- createdOn?: Date;
74
- modifiedOn?: Date;
75
-
76
- constructor(data: Partial<ISampleEntity> = {}) {
77
- Object.assign(this, data);
78
- }
79
-
80
- static async retrieveByFilter(apiService: any, filter?: string, maxRecords?: number): Promise<SampleEntity[]> {
81
- // Template implementation - replace during generation
82
- return [];
83
- }
84
-
85
- static async create(apiService: any, entity: SampleEntity): Promise<SampleEntity> {
86
- // Template implementation - replace during generation
87
- return entity;
88
- }
89
-
90
- async update(apiService: any): Promise<void> {
91
- // Template implementation - replace during generation
92
- }
93
-
94
- async delete(apiService: any): Promise<void> {
95
- // Template implementation - replace during generation
96
- }
97
- }
98
-
99
- // Template constants - replace with actual constants during generation
100
- const SampleEntityConstants = {
101
- PrimaryNameAttribute: 'name',
102
- Description: 'description',
103
- Priority: 'priority',
104
- CreatedOn: 'createdOn',
105
- FieldDisplayNames: {
106
- name: 'Name',
107
- description: 'Description',
108
- priority: 'Priority',
109
- createdOn: 'Created On'
110
- },
111
- PriorityOptions: {
112
- Low: 1,
113
- Medium: 2,
114
- High: 3,
115
- Critical: 4
116
- }
117
- };
118
-
119
- // Template form component - replace with actual form during generation
120
- const SampleEntityForm: React.FC<{
121
- sampleEntity?: SampleEntity | null;
122
- onSave: (data: Partial<ISampleEntity>) => Promise<void>;
123
- onCancel: () => void;
124
- }> = ({ sampleEntity, onSave, onCancel }) => {
125
- return (
126
- <div>
127
- <p>Template Form Component - Replace during generation</p>
128
- <button onClick={() => onSave({})}>Save</button>
129
- <button onClick={onCancel}>Cancel</button>
130
- </div>
131
- );
132
- };
133
-
134
- interface SampleEntityManagementProps {
135
- title?: string;
136
- showCommandBar?: boolean;
137
- maxRecords?: number;
138
- filter?: string;
139
- onItemSelected?: (item: SampleEntity) => void;
140
- }
141
-
142
- export const SampleEntityManagement: React.FC<SampleEntityManagementProps> = ({
143
- title = "sampleEntities",
144
- showCommandBar = true,
145
- maxRecords = 100,
146
- filter,
147
- onItemSelected
148
- }) => {
149
- const { apiService } = useDynamicsApi();
150
- const [sampleEntities, setSampleEntities] = useState<SampleEntity[]>([]);
151
- const [loading, setLoading] = useState(true);
152
- const [error, setError] = useState<string | null>(null);
153
- const [selectedItem, setSelectedItem] = useState<SampleEntity | null>(null);
154
- const [showPanel, setShowPanel] = useState(false);
155
- const [showDeleteDialog, setShowDeleteDialog] = useState(false);
156
- const [isEditing, setIsEditing] = useState(false);
157
- const [refreshTrigger, setRefreshTrigger] = useState(0);
158
-
159
- // Load sampleEntities data
160
- const loadSampleEntities = useCallback(async () => {
161
- try {
162
- setLoading(true);
163
- setError(null);
164
- Logger.log('Loading sampleEntities...');
165
-
166
- const data = await SampleEntity.retrieveByFilter(apiService, filter, maxRecords);
167
- setSampleEntities(data);
168
- Logger.log(`Loaded ${data.length} sampleEntities`);
169
- } catch (err) {
170
- const errorMessage = err instanceof Error ? err.message : 'Failed to load sampleEntities';
171
- setError(errorMessage);
172
- Logger.error('Error loading sampleEntities:', err);
173
- } finally {
174
- setLoading(false);
175
- }
176
- }, [apiService, filter, maxRecords]);
177
-
178
- useEffect(() => {
179
- loadSampleEntities();
180
- }, [loadSampleEntities, refreshTrigger]);
181
-
182
- // Handle item selection
183
- const handleItemClick = (item: SampleEntity) => {
184
- setSelectedItem(item);
185
- if (onItemSelected) {
186
- onItemSelected(item);
187
- }
188
- };
189
-
190
- // Handle new sampleEntity
191
- const handleNew = () => {
192
- setSelectedItem(null);
193
- setIsEditing(false);
194
- setShowPanel(true);
195
- };
196
-
197
- // Handle edit sampleEntity
198
- const handleEdit = () => {
199
- if (selectedItem) {
200
- setIsEditing(true);
201
- setShowPanel(true);
202
- }
203
- };
204
-
205
- // Handle delete sampleEntity
206
- const handleDelete = () => {
207
- if (selectedItem) {
208
- setShowDeleteDialog(true);
209
- }
210
- };
211
-
212
- // Confirm delete
213
- const confirmDelete = async () => {
214
- if (selectedItem) {
215
- try {
216
- await selectedItem.delete(apiService);
217
- setShowDeleteDialog(false);
218
- setSelectedItem(null);
219
- setRefreshTrigger(prev => prev + 1);
220
- Logger.log(`Sample Entity deleted successfully`);
221
- } catch (err) {
222
- const errorMessage = err instanceof Error ? err.message : 'Failed to delete Sample Entity';
223
- setError(errorMessage);
224
- Logger.error('Error deleting Sample Entity:', err);
225
- }
226
- }
227
- };
228
-
229
- // Handle save
230
- const handleSave = async (sampleEntityData: Partial<ISampleEntity>) => {
231
- try {
232
- if (isEditing && selectedItem) {
233
- // Update existing
234
- Object.assign(selectedItem, sampleEntityData);
235
- await selectedItem.update(apiService);
236
- Logger.log(`Sample Entity updated successfully`);
237
- } else {
238
- // Create new
239
- const newSampleEntity = new SampleEntity(sampleEntityData);
240
- await SampleEntity.create(apiService, newSampleEntity);
241
- Logger.log(`Sample Entity created successfully`);
242
- }
243
-
244
- setShowPanel(false);
245
- setSelectedItem(null);
246
- setRefreshTrigger(prev => prev + 1);
247
- } catch (err) {
248
- const errorMessage = err instanceof Error ? err.message : `Failed to save Sample Entity`;
249
- setError(errorMessage);
250
- Logger.error('Error saving Sample Entity:', err);
251
- }
252
- };
253
-
254
- // Handle panel dismiss
255
- const handlePanelDismiss = () => {
256
- setShowPanel(false);
257
- setSelectedItem(null);
258
- setIsEditing(false);
259
- };
260
-
261
- // Define columns
262
- const columns: IColumn[] = [
263
- {
264
- key: 'name',
265
- name: SampleEntityConstants.FieldDisplayNames[SampleEntityConstants.PrimaryNameAttribute],
266
- fieldName: SampleEntityConstants.PrimaryNameAttribute,
267
- minWidth: 150,
268
- maxWidth: 250,
269
- isResizable: true,
270
- onRender: (item: SampleEntity) => (
271
- <span
272
- className="sample-entity-management-name-link"
273
- onClick={() => handleItemClick(item)}
274
- >
275
- {item[SampleEntityConstants.PrimaryNameAttribute]}
276
- </span>
277
- )
278
- },
279
- {
280
- key: 'description',
281
- name: SampleEntityConstants.FieldDisplayNames[SampleEntityConstants.Description],
282
- fieldName: SampleEntityConstants.Description,
283
- minWidth: 200,
284
- maxWidth: 300,
285
- isResizable: true
286
- },
287
- {
288
- key: 'priority',
289
- name: SampleEntityConstants.FieldDisplayNames[SampleEntityConstants.Priority],
290
- fieldName: SampleEntityConstants.Priority,
291
- minWidth: 100,
292
- maxWidth: 150,
293
- isResizable: true,
294
- onRender: (item: SampleEntity) => {
295
- const priority = item[SampleEntityConstants.Priority];
296
- const priorityText = Object.keys(SampleEntityConstants.PriorityOptions).find(
297
- key => SampleEntityConstants.PriorityOptions[key as keyof typeof SampleEntityConstants.PriorityOptions] === priority
298
- );
299
- return <span>{priorityText || priority}</span>;
300
- }
301
- },
302
- {
303
- key: 'createdOn',
304
- name: SampleEntityConstants.FieldDisplayNames[SampleEntityConstants.CreatedOn],
305
- fieldName: 'createdOn',
306
- minWidth: 120,
307
- maxWidth: 180,
308
- isResizable: true,
309
- onRender: (item: SampleEntity) => (
310
- <span>{item.createdOn?.toLocaleDateString()}</span>
311
- )
312
- }
313
- ];
314
-
315
- // Command bar items
316
- const commandBarItems: ICommandBarItemProps[] = showCommandBar ? [
317
- {
318
- key: 'new',
319
- text: 'New Sample Entity',
320
- iconProps: { iconName: 'Add' },
321
- onClick: handleNew
322
- },
323
- {
324
- key: 'edit',
325
- text: 'Edit',
326
- iconProps: { iconName: 'Edit' },
327
- disabled: !selectedItem,
328
- onClick: handleEdit
329
- },
330
- {
331
- key: 'delete',
332
- text: 'Delete',
333
- iconProps: { iconName: 'Delete' },
334
- disabled: !selectedItem,
335
- onClick: handleDelete
336
- },
337
- {
338
- key: 'refresh',
339
- text: 'Refresh',
340
- iconProps: { iconName: 'Refresh' },
341
- onClick: () => setRefreshTrigger(prev => prev + 1)
342
- }
343
- ] : [];
344
-
345
- return (
346
- <div className="sample-entity-management">
347
- <h2 className="sample-entity-management-title">{title}</h2>
348
-
349
- {error && (
350
- <MessageBar
351
- messageBarType={MessageBarType.error}
352
- onDismiss={() => setError(null)}
353
- >
354
- {error}
355
- </MessageBar>
356
- )}
357
-
358
- {showCommandBar && (
359
- <CommandBar
360
- items={commandBarItems}
361
- className="sample-entity-management-command-bar"
362
- />
363
- )}
364
-
365
- {loading ? (
366
- <div className="sample-entity-management-loading">
367
- <Spinner size={SpinnerSize.large} label="Loading sampleEntities..." />
368
- </div>
369
- ) : (
370
- <DetailsList
371
- items={sampleEntities}
372
- columns={columns}
373
- setKey="set"
374
- layoutMode={0}
375
- selectionMode={SelectionMode.single}
376
- onActiveItemChanged={setSelectedItem}
377
- className="sample-entity-management-list"
378
- />
379
- )}
380
-
381
- {/* Form Panel */}
382
- <Panel
383
- headerText={isEditing ? `Edit Sample Entity` : `New Sample Entity`}
384
- isOpen={showPanel}
385
- onDismiss={handlePanelDismiss}
386
- type={PanelType.medium}
387
- closeButtonAriaLabel="Close"
388
- >
389
- <SampleEntityForm
390
- sampleEntity={selectedItem}
391
- onSave={handleSave}
392
- onCancel={handlePanelDismiss}
393
- />
394
- </Panel>
395
-
396
- {/* Delete Confirmation Dialog */}
397
- <Dialog
398
- hidden={!showDeleteDialog}
399
- onDismiss={() => setShowDeleteDialog(false)}
400
- dialogContentProps={{
401
- type: DialogType.normal,
402
- title: 'Confirm Delete',
403
- subText: `Are you sure you want to delete "${selectedItem?.[SampleEntityConstants.PrimaryNameAttribute]}"?`
404
- }}
405
- >
406
- <DialogFooter>
407
- <PrimaryButton onClick={confirmDelete} text="Delete" />
408
- <DefaultButton onClick={() => setShowDeleteDialog(false)} text="Cancel" />
409
- </DialogFooter>
410
- </Dialog>
411
- </div>
412
- );
413
- };
@@ -1,250 +0,0 @@
1
- // Replace 'SampleEntity' with your actual entity PascalCase name during template processing
2
- // import { BaseEntity } from './BaseEntity';
3
- // import { IApiService } from '../services/IApiService';
4
- // import { Logger } from '../components/Logging/logger';
5
- // import { SampleEntityConstants } from '../constants/sample-entity';
6
-
7
- // Template base entity class - replace with actual BaseEntity during generation
8
- abstract class BaseEntity {
9
- id?: string;
10
- [key: string]: any;
11
- }
12
-
13
- // Template API service interface - replace with actual IApiService during generation
14
- interface IApiService {
15
- createRecord(entityName: string, data: any): Promise<any>;
16
- updateRecord(entityName: string, id: string, data: any): Promise<any>;
17
- deleteRecord(entityName: string, id: string): Promise<void>;
18
- retrieveMultipleRecords(entityName: string, fetchXml: string): Promise<{ entities: any[] }>;
19
- }
20
-
21
- // Template Logger - replace with actual Logger during generation
22
- const Logger = {
23
- log: (message: string, source?: string) => console.log(message, source),
24
- warn: (message: string, source?: string) => console.warn(message, source),
25
- error: (message: string, source?: string, error?: any) => console.error(message, source, error)
26
- };
27
-
28
- // Template constants - replace with actual constants during generation
29
- const SampleEntityConstants = {
30
- EntityLogicalName: 'sample_entity',
31
- PrimaryIdAttribute: 'sample_entityid',
32
- PrimaryNameAttribute: 'name',
33
- FieldDisplayNames: {
34
- sample_entityid: 'ID',
35
- name: 'Name'
36
- }
37
- };
38
-
39
- export interface ISampleEntity {
40
- sample_entityid: string;
41
- name: string;
42
- createdOn?: Date;
43
- modifiedOn?: Date;
44
- }
45
-
46
- /**
47
- * Sample Entity entity model with CRUD operations
48
- * Generated by Entity Generator
49
- */
50
- export class SampleEntity extends BaseEntity implements ISampleEntity {
51
- public sample_entityid: string = '';
52
- public name: string = '';
53
- public createdOn?: Date;
54
- public modifiedOn?: Date;
55
-
56
- constructor(data?: Partial<ISampleEntity>) {
57
- super();
58
- if (data) {
59
- Object.assign(this, data);
60
- }
61
- }
62
-
63
- /**
64
- * Create a new Sample Entity record
65
- */
66
- public static async create(apiService: IApiService, sampleEntity: SampleEntity): Promise<SampleEntity> {
67
- try {
68
- Logger.log(`Creating new Sample Entity: ${sampleEntity.name}`);
69
-
70
- const data = sampleEntity.toCreateData();
71
- const result = await apiService.createRecord(SampleEntityConstants.EntityLogicalName, data);
72
-
73
- const createdSampleEntity = new SampleEntity({
74
- ...sampleEntity,
75
- sample_entityid: result.id || result.sample_entityid
76
- });
77
-
78
- Logger.log(`Sample Entity created successfully with ID: ${createdSampleEntity.sample_entityid}`);
79
- return createdSampleEntity;
80
- } catch (error) {
81
- Logger.error(`Error creating Sample Entity:`, error);
82
- throw new Error(`Failed to create Sample Entity: ${error instanceof Error ? error.message : 'Unknown error'}`);
83
- }
84
- }
85
-
86
- /**
87
- * Retrieve Sample Entity by ID
88
- */
89
- public static async retrieveById(apiService: IApiService, id: string): Promise<SampleEntity | null> {
90
- try {
91
- Logger.log(`Retrieving Sample Entity with ID: ${id}`);
92
-
93
- const fetchXml = `
94
- <fetch top="1">
95
- <entity name="${SampleEntityConstants.EntityLogicalName}">
96
- <attribute name="sample_entityid" />
97
- <attribute name="name" />
98
- <attribute name="createdon" />
99
- <attribute name="modifiedon" />
100
- <filter>
101
- <condition attribute="sample_entityid" operator="eq" value="${id}" />
102
- </filter>
103
- </entity>
104
- </fetch>`;
105
-
106
- const result = await apiService.retrieveMultipleRecords(SampleEntityConstants.EntityLogicalName, fetchXml);
107
-
108
- if (result.entities && result.entities.length > 0) {
109
- const entity = result.entities[0];
110
- return new SampleEntity({
111
- sample_entityid: entity.sample_entityid,
112
- name: entity.name,
113
- createdOn: entity.createdon ? new Date(entity.createdon) : undefined,
114
- modifiedOn: entity.modifiedon ? new Date(entity.modifiedon) : undefined
115
- });
116
- }
117
-
118
- Logger.warn(`Sample Entity not found with ID: ${id}`);
119
- return null;
120
- } catch (error) {
121
- Logger.error(`Error retrieving Sample Entity by ID:`, error);
122
- throw new Error(`Failed to retrieve Sample Entity: ${error instanceof Error ? error.message : 'Unknown error'}`);
123
- }
124
- }
125
-
126
- /**
127
- * Retrieve multiple sampleEntities with optional filter
128
- */
129
- public static async retrieveByFilter(apiService: IApiService, filter?: string, top?: number): Promise<SampleEntity[]> {
130
- try {
131
- Logger.log(`Retrieving sampleEntities with filter: ${filter || 'none'}`);
132
-
133
- const topClause = top ? `top="${top}"` : '';
134
- const filterClause = filter ? `<filter>${filter}</filter>` : '';
135
-
136
- const fetchXml = `
137
- <fetch ${topClause}>
138
- <entity name="${SampleEntityConstants.EntityLogicalName}">
139
- <attribute name="sample_entityid" />
140
- <attribute name="name" />
141
- <attribute name="createdon" />
142
- <attribute name="modifiedon" />
143
- <order attribute="name" />
144
- ${filterClause}
145
- </entity>
146
- </fetch>`;
147
-
148
- const result = await apiService.retrieveMultipleRecords(SampleEntityConstants.EntityLogicalName, fetchXml);
149
-
150
- const sampleEntities = (result.entities || []).map(entity => new SampleEntity({
151
- sample_entityid: entity.sample_entityid,
152
- name: entity.name,
153
- createdOn: entity.createdon ? new Date(entity.createdon) : undefined,
154
- modifiedOn: entity.modifiedon ? new Date(entity.modifiedon) : undefined
155
- }));
156
-
157
- Logger.log(`Retrieved ${sampleEntities.length} sampleEntities`);
158
- return sampleEntities;
159
- } catch (error) {
160
- Logger.error(`Error retrieving sampleEntities:`, error);
161
- throw new Error(`Failed to retrieve sampleEntities: ${error instanceof Error ? error.message : 'Unknown error'}`);
162
- }
163
- }
164
-
165
- /**
166
- * Update the Sample Entity record
167
- */
168
- public async update(apiService: IApiService): Promise<SampleEntity> {
169
- try {
170
- if (!this.sample_entityid) {
171
- throw new Error('Cannot update Sample Entity without ID');
172
- }
173
-
174
- Logger.log(`Updating Sample Entity: ${this.name}`);
175
-
176
- const data = this.toUpdateData();
177
- await apiService.updateRecord(
178
- SampleEntityConstants.EntityLogicalName,
179
- this.sample_entityid,
180
- data
181
- );
182
-
183
- Logger.log(`Sample Entity updated successfully`);
184
- return this;
185
- } catch (error) {
186
- Logger.error(`Error updating Sample Entity:`, error);
187
- throw new Error(`Failed to update Sample Entity: ${error instanceof Error ? error.message : 'Unknown error'}`);
188
- }
189
- }
190
-
191
- /**
192
- * Delete the Sample Entity record
193
- */
194
- public async delete(apiService: IApiService): Promise<void> {
195
- try {
196
- if (!this.sample_entityid) {
197
- throw new Error('Cannot delete Sample Entity without ID');
198
- }
199
-
200
- Logger.log(`Deleting Sample Entity: ${this.name}`);
201
-
202
- await apiService.deleteRecord(
203
- SampleEntityConstants.EntityLogicalName,
204
- this.sample_entityid
205
- );
206
-
207
- Logger.log(`Sample Entity deleted successfully`);
208
- } catch (error) {
209
- Logger.error(`Error deleting Sample Entity:`, error);
210
- throw new Error(`Failed to delete Sample Entity: ${error instanceof Error ? error.message : 'Unknown error'}`);
211
- }
212
- }
213
-
214
- /**
215
- * Validate the Sample Entity data
216
- */
217
- public validate(): { isValid: boolean; errors: string[] } {
218
- const errors: string[] = [];
219
-
220
- // Add your validation rules here
221
- if (!this.name?.trim()) {
222
- errors.push(`${name} is required`);
223
- }
224
-
225
- return {
226
- isValid: errors.length === 0,
227
- errors
228
- };
229
- }
230
-
231
- /**
232
- * Convert to data for create operation
233
- */
234
- private toCreateData(): any {
235
- return {
236
- name: this.name
237
- // Add other fields as needed
238
- };
239
- }
240
-
241
- /**
242
- * Convert to data for update operation
243
- */
244
- private toUpdateData(): any {
245
- return {
246
- name: this.name
247
- // Add other fields as needed
248
- };
249
- }
250
- }