@khester/create-dynamics-app 1.0.8 → 1.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.
- package/bin/create-dynamics-app.js +1 -1
- package/dist/index.js +140 -15
- package/dist/index.js.map +1 -1
- package/dist/utils/consultingHelpers.d.ts +13 -0
- package/dist/utils/consultingHelpers.d.ts.map +1 -0
- package/dist/utils/consultingHelpers.js +569 -0
- package/dist/utils/consultingHelpers.js.map +1 -0
- package/dist/utils/copyTemplate.d.ts.map +1 -1
- package/dist/utils/copyTemplate.js.map +1 -1
- package/dist/utils/initGit.d.ts.map +1 -1
- package/dist/utils/initGit.js.map +1 -1
- package/dist/utils/installDependencies.d.ts.map +1 -1
- package/dist/utils/installDependencies.js +3 -2
- package/dist/utils/installDependencies.js.map +1 -1
- package/dist/utils/updatePackageJson.d.ts +1 -1
- package/dist/utils/updatePackageJson.d.ts.map +1 -1
- package/dist/utils/updatePackageJson.js +11 -1
- package/dist/utils/updatePackageJson.js.map +1 -1
- package/package.json +1 -1
- package/templates/dynamics-365-starter/INTEGRATION_TEST_RESULTS.md +302 -0
- package/templates/dynamics-365-starter/PHASE_4_COMPLETION_SUMMARY.md +305 -0
- package/templates/dynamics-365-starter/README.md +566 -137
- package/templates/dynamics-365-starter/deployment/QUICKSTART-MAC.md +507 -0
- package/templates/dynamics-365-starter/deployment/QUICKSTART-WINDOWS.md +372 -0
- package/templates/dynamics-365-starter/deployment/README.md +484 -0
- package/templates/dynamics-365-starter/deployment/pipelines/README.md +375 -0
- package/templates/dynamics-365-starter/deployment/pipelines/azure-pipelines.yml +330 -0
- package/templates/dynamics-365-starter/deployment/pipelines/github-actions.yml +422 -0
- package/templates/dynamics-365-starter/deployment/pipelines/jenkins.groovy +636 -0
- package/templates/dynamics-365-starter/deployment/scripts/deploy.ps1 +417 -0
- package/templates/dynamics-365-starter/deployment/scripts/deploy.sh +582 -0
- package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.ps1 +486 -0
- package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.sh +567 -0
- package/templates/dynamics-365-starter/deployment/scripts/validate-setup.ps1 +703 -0
- package/templates/dynamics-365-starter/deployment/scripts/validate-setup.sh +671 -0
- package/templates/dynamics-365-starter/docs/ARCHITECTURE_OVERVIEW.md +506 -0
- package/templates/dynamics-365-starter/docs/BEST_PRACTICES.md +723 -0
- package/templates/dynamics-365-starter/docs/MIGRATION_GUIDE.md +447 -0
- package/templates/dynamics-365-starter/docs/team-standards/README.md +273 -0
- package/templates/dynamics-365-starter/docs/team-standards/client-onboarding.md +577 -0
- package/templates/dynamics-365-starter/docs/team-standards/code-review-checklist.md +359 -0
- package/templates/dynamics-365-starter/docs/team-standards/coding-standards.md +700 -0
- package/templates/dynamics-365-starter/docs/team-standards/cross-platform-team-guide.md +736 -0
- package/templates/dynamics-365-starter/docs/team-standards/development-workflows.md +727 -0
- package/templates/dynamics-365-starter/docs/troubleshooting/common-errors.md +758 -0
- package/templates/dynamics-365-starter/docs/troubleshooting/platform-specific-issues.md +878 -0
- package/templates/dynamics-365-starter/package.json +22 -1
- package/templates/dynamics-365-starter/public/index.html +8 -11
- package/templates/dynamics-365-starter/scripts/custom-build.js +255 -0
- package/templates/dynamics-365-starter/src/client-project-template/README.md +234 -0
- package/templates/dynamics-365-starter/src/client-project-template/config/client.template.json +114 -0
- package/templates/dynamics-365-starter/src/client-project-template/config/environments/template.json +186 -0
- package/templates/dynamics-365-starter/src/client-project-template/scripts/client-setup.js +667 -0
- package/templates/dynamics-365-starter/src/components/AccountForm.css +71 -0
- package/templates/dynamics-365-starter/src/components/AccountForm.tsx +541 -0
- package/templates/dynamics-365-starter/src/components/AccountManagement.css +86 -0
- package/templates/dynamics-365-starter/src/components/AccountManagement.tsx +370 -0
- package/templates/dynamics-365-starter/src/components/ContactForm.tsx +149 -63
- package/templates/dynamics-365-starter/src/components/ContactManagement.tsx +153 -63
- package/templates/dynamics-365-starter/src/components/Logging/LogDialog.tsx +291 -0
- package/templates/dynamics-365-starter/src/components/Logging/LoggingContext.tsx +166 -0
- package/templates/dynamics-365-starter/src/components/Logging/LoggingDebugPanel.css +192 -0
- package/templates/dynamics-365-starter/src/components/Logging/LoggingDebugPanel.tsx +177 -0
- package/templates/dynamics-365-starter/src/components/Logging/LoggingProvider.tsx +3 -0
- package/templates/dynamics-365-starter/src/components/Logging/logger.ts +193 -0
- package/templates/dynamics-365-starter/src/constants/account.ts +410 -0
- package/templates/dynamics-365-starter/src/constants/contact.ts +362 -0
- package/templates/dynamics-365-starter/src/examples/README.md +52 -0
- package/templates/dynamics-365-starter/src/examples/component-examples/opportunity-management.tsx +625 -0
- package/templates/dynamics-365-starter/src/examples/entity-examples/opportunity-model.ts +545 -0
- package/templates/dynamics-365-starter/src/examples/integration-examples/custom-pcf-wrapper.tsx +722 -0
- package/templates/dynamics-365-starter/src/examples/workflow-examples/sales-workflow.ts +662 -0
- package/templates/dynamics-365-starter/src/index.tsx +107 -19
- package/templates/dynamics-365-starter/src/models/Account.ts +480 -0
- package/templates/dynamics-365-starter/src/models/BaseEntity.ts +204 -0
- package/templates/dynamics-365-starter/src/models/Contact.ts +580 -0
- package/templates/dynamics-365-starter/src/page-templates/EntityDashboard.tsx +519 -0
- package/templates/dynamics-365-starter/src/page-templates/EntityDetailPage.tsx +456 -0
- package/templates/dynamics-365-starter/src/page-templates/EntityListPage.tsx +406 -0
- package/templates/dynamics-365-starter/src/page-templates/RelatedEntitiesPage.tsx +578 -0
- package/templates/dynamics-365-starter/src/page-templates/SearchPage.tsx +629 -0
- package/templates/dynamics-365-starter/src/pcf/ContactControlWrapper.tsx +75 -22
- package/templates/dynamics-365-starter/src/pcf/MultiEntityControlWrapper.tsx +205 -0
- package/templates/dynamics-365-starter/src/providers/DynamicsProvider.tsx +297 -80
- package/templates/dynamics-365-starter/src/services/MockApiService.ts +260 -0
- package/templates/dynamics-365-starter/src/services/ServiceFactory.ts +65 -0
- package/templates/dynamics-365-starter/src/services/XrmApiService.ts +213 -0
- package/templates/dynamics-365-starter/src/styles/index.css +74 -7
- package/templates/dynamics-365-starter/tools/entity-generator/index.js +168 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/constants.template.ts +124 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.css +283 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.tsx +275 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.css +204 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.tsx +413 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/model.template.ts +250 -0
- package/templates/dynamics-365-starter/tools/metadata-sync/d365-client.js +410 -0
- package/templates/dynamics-365-starter/tools/metadata-sync/index.js +512 -0
- package/templates/dynamics-365-starter/tools/metadata-sync/type-generator.js +675 -0
- package/templates/dynamics-365-starter/tsconfig.json +11 -8
- package/templates/dynamics-365-starter/webpack.config.js +8 -9
- package/templates/power-pages-starter/README.md +7 -1
- package/templates/power-pages-starter/public/index.html +8 -11
- package/templates/power-pages-starter/src/components/ContactForm.tsx +60 -41
- package/templates/power-pages-starter/src/index.tsx +3 -3
- package/templates/power-pages-starter/src/providers/PowerPagesProvider.tsx +46 -23
- package/templates/power-pages-starter/tsconfig.json +3 -9
- package/templates/power-pages-starter/webpack.config.js +8 -3
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Client Project Setup Script
|
|
5
|
+
* Automates the setup of client-specific configurations and branding
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs-extra');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const inquirer = require('inquirer');
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
|
|
13
|
+
async function setupClientProject() {
|
|
14
|
+
console.log(chalk.cyan('\n🎯 Client Project Setup\n'));
|
|
15
|
+
|
|
16
|
+
// Gather client information
|
|
17
|
+
const answers = await inquirer.prompt([
|
|
18
|
+
{
|
|
19
|
+
type: 'input',
|
|
20
|
+
name: 'clientName',
|
|
21
|
+
message: 'Client full name:',
|
|
22
|
+
validate: input => input.length > 0
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: 'input',
|
|
26
|
+
name: 'clientCode',
|
|
27
|
+
message: 'Client code (3-4 characters):',
|
|
28
|
+
validate: input => input.length >= 3 && input.length <= 4
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'list',
|
|
32
|
+
name: 'industry',
|
|
33
|
+
message: 'Industry:',
|
|
34
|
+
choices: [
|
|
35
|
+
'Manufacturing',
|
|
36
|
+
'Healthcare',
|
|
37
|
+
'Financial Services',
|
|
38
|
+
'Retail',
|
|
39
|
+
'Technology',
|
|
40
|
+
'Education',
|
|
41
|
+
'Government',
|
|
42
|
+
'Non-Profit',
|
|
43
|
+
'Other'
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: 'list',
|
|
48
|
+
name: 'timezone',
|
|
49
|
+
message: 'Primary timezone:',
|
|
50
|
+
choices: [
|
|
51
|
+
'America/New_York',
|
|
52
|
+
'America/Chicago',
|
|
53
|
+
'America/Denver',
|
|
54
|
+
'America/Los_Angeles',
|
|
55
|
+
'Europe/London',
|
|
56
|
+
'Europe/Paris',
|
|
57
|
+
'Asia/Tokyo',
|
|
58
|
+
'Australia/Sydney'
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
type: 'input',
|
|
63
|
+
name: 'primaryContact',
|
|
64
|
+
message: 'Primary contact name:'
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: 'input',
|
|
68
|
+
name: 'contactEmail',
|
|
69
|
+
message: 'Primary contact email:',
|
|
70
|
+
validate: input => /\S+@\S+\.\S+/.test(input)
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: 'input',
|
|
74
|
+
name: 'primaryColor',
|
|
75
|
+
message: 'Primary brand color (hex):',
|
|
76
|
+
default: '#0078d4'
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
type: 'input',
|
|
80
|
+
name: 'secondaryColor',
|
|
81
|
+
message: 'Secondary brand color (hex):',
|
|
82
|
+
default: '#106ebe'
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
type: 'checkbox',
|
|
86
|
+
name: 'environments',
|
|
87
|
+
message: 'Environments to configure:',
|
|
88
|
+
choices: [
|
|
89
|
+
{ name: 'Development', value: 'dev', checked: true },
|
|
90
|
+
{ name: 'Testing', value: 'test', checked: true },
|
|
91
|
+
{ name: 'Staging', value: 'staging', checked: false },
|
|
92
|
+
{ name: 'Production', value: 'prod', checked: true }
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'confirm',
|
|
97
|
+
name: 'enableAdvancedFeatures',
|
|
98
|
+
message: 'Enable advanced features (custom workflows, reporting, etc.)?',
|
|
99
|
+
default: true
|
|
100
|
+
}
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
console.log(chalk.cyan('\n📁 Creating client configuration...\n'));
|
|
104
|
+
|
|
105
|
+
// Create client configuration
|
|
106
|
+
await createClientConfig(answers);
|
|
107
|
+
|
|
108
|
+
// Create environment configurations
|
|
109
|
+
for (const env of answers.environments) {
|
|
110
|
+
await createEnvironmentConfig(env, answers);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Create branding files
|
|
114
|
+
await createBrandingFiles(answers);
|
|
115
|
+
|
|
116
|
+
// Create deployment scripts
|
|
117
|
+
await createDeploymentScripts(answers);
|
|
118
|
+
|
|
119
|
+
// Create documentation
|
|
120
|
+
await createProjectDocumentation(answers);
|
|
121
|
+
|
|
122
|
+
console.log(chalk.green('\n✅ Client project setup completed!\n'));
|
|
123
|
+
console.log(chalk.cyan('📝 Next steps:'));
|
|
124
|
+
console.log(' 1. Review and update configuration files');
|
|
125
|
+
console.log(' 2. Add client logos to src/branding/logos/');
|
|
126
|
+
console.log(' 3. Configure environment-specific settings');
|
|
127
|
+
console.log(' 4. Set up deployment pipelines');
|
|
128
|
+
console.log(' 5. Run initial deployment to dev environment');
|
|
129
|
+
console.log('\n📚 Documentation created in docs/ folder');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function createClientConfig(answers) {
|
|
133
|
+
const configPath = 'config/client.json';
|
|
134
|
+
await fs.ensureDir(path.dirname(configPath));
|
|
135
|
+
|
|
136
|
+
const clientConfig = {
|
|
137
|
+
name: answers.clientName,
|
|
138
|
+
code: answers.clientCode.toUpperCase(),
|
|
139
|
+
industry: answers.industry,
|
|
140
|
+
timezone: answers.timezone,
|
|
141
|
+
locale: 'en-US',
|
|
142
|
+
version: '1.0.0',
|
|
143
|
+
created: new Date().toISOString(),
|
|
144
|
+
lastUpdated: new Date().toISOString(),
|
|
145
|
+
contact: {
|
|
146
|
+
primaryContact: answers.primaryContact,
|
|
147
|
+
email: answers.contactEmail,
|
|
148
|
+
phone: ''
|
|
149
|
+
},
|
|
150
|
+
branding: {
|
|
151
|
+
primaryColor: answers.primaryColor,
|
|
152
|
+
secondaryColor: answers.secondaryColor,
|
|
153
|
+
accentColor: '#ffaa44',
|
|
154
|
+
logoPath: `src/branding/logos/${answers.clientCode.toLowerCase()}-logo.png`,
|
|
155
|
+
faviconPath: `src/branding/logos/${answers.clientCode.toLowerCase()}-favicon.ico`,
|
|
156
|
+
fontFamily: 'Segoe UI, sans-serif',
|
|
157
|
+
customCss: `src/branding/${answers.clientCode.toLowerCase()}-custom.css`
|
|
158
|
+
},
|
|
159
|
+
features: {
|
|
160
|
+
enableAdvancedLogging: answers.enableAdvancedFeatures,
|
|
161
|
+
enableCustomWorkflows: answers.enableAdvancedFeatures,
|
|
162
|
+
enableReporting: answers.enableAdvancedFeatures,
|
|
163
|
+
enableMobileOptimization: true,
|
|
164
|
+
enableOfflineCapability: false,
|
|
165
|
+
enableMultiLanguage: false,
|
|
166
|
+
enableCustomDashboards: answers.enableAdvancedFeatures,
|
|
167
|
+
enableDataExport: true,
|
|
168
|
+
enableBulkOperations: true,
|
|
169
|
+
enableAdvancedSecurity: true
|
|
170
|
+
},
|
|
171
|
+
customEntities: [],
|
|
172
|
+
integrations: {
|
|
173
|
+
sharepoint: { enabled: false, siteUrl: '' },
|
|
174
|
+
teams: { enabled: false, appId: '' },
|
|
175
|
+
powerBI: { enabled: false, workspaceId: '' },
|
|
176
|
+
powerAutomate: { enabled: true },
|
|
177
|
+
externalAPIs: []
|
|
178
|
+
},
|
|
179
|
+
compliance: {
|
|
180
|
+
gdprCompliant: true,
|
|
181
|
+
hipaaCompliant: false,
|
|
182
|
+
soxCompliant: false,
|
|
183
|
+
auditRetentionDays: 365,
|
|
184
|
+
dataClassification: 'Internal'
|
|
185
|
+
},
|
|
186
|
+
deployment: {
|
|
187
|
+
strategy: 'blue-green',
|
|
188
|
+
rollbackEnabled: true,
|
|
189
|
+
approvalRequired: true,
|
|
190
|
+
notificationEmail: answers.contactEmail,
|
|
191
|
+
maintenanceWindow: {
|
|
192
|
+
timezone: answers.timezone,
|
|
193
|
+
startTime: '02:00',
|
|
194
|
+
duration: 120
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
await fs.writeJson(configPath, clientConfig, { spaces: 2 });
|
|
200
|
+
console.log(chalk.green(` ✓ Created ${configPath}`));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function createEnvironmentConfig(environment, answers) {
|
|
204
|
+
const envPath = `config/environments/${environment}.json`;
|
|
205
|
+
await fs.ensureDir(path.dirname(envPath));
|
|
206
|
+
|
|
207
|
+
const environmentConfig = {
|
|
208
|
+
name: environment.charAt(0).toUpperCase() + environment.slice(1),
|
|
209
|
+
type: environment,
|
|
210
|
+
description: `${environment.charAt(0).toUpperCase() + environment.slice(1)} environment for ${answers.clientName}`,
|
|
211
|
+
lastUpdated: new Date().toISOString(),
|
|
212
|
+
dynamics365: {
|
|
213
|
+
orgUrl: `https://${answers.clientCode.toLowerCase()}-${environment}.crm.dynamics.com`,
|
|
214
|
+
webApiUrl: `https://${answers.clientCode.toLowerCase()}-${environment}.api.crm.dynamics.com/api/data/v9.2`,
|
|
215
|
+
version: '9.2',
|
|
216
|
+
region: 'northamerica',
|
|
217
|
+
tenantId: 'your-tenant-id',
|
|
218
|
+
dataverse: {
|
|
219
|
+
environmentId: 'your-environment-id',
|
|
220
|
+
uniqueName: `${answers.clientCode.toLowerCase()}-${environment}`
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
authentication: {
|
|
224
|
+
type: 'oauth2',
|
|
225
|
+
clientId: 'your-client-id',
|
|
226
|
+
clientSecret: 'your-client-secret',
|
|
227
|
+
redirectUri: `https://${answers.clientCode.toLowerCase()}-${environment}.dynamics.com/auth/callback`,
|
|
228
|
+
scopes: [`https://${answers.clientCode.toLowerCase()}-${environment}.crm.dynamics.com/user_impersonation`],
|
|
229
|
+
authority: 'https://login.microsoftonline.com/your-tenant-id'
|
|
230
|
+
},
|
|
231
|
+
security: {
|
|
232
|
+
enableAuditLogging: true,
|
|
233
|
+
requireMFA: environment === 'prod',
|
|
234
|
+
sessionTimeout: environment === 'prod' ? 480 : 720,
|
|
235
|
+
enableConditionalAccess: environment === 'prod',
|
|
236
|
+
allowedIPs: [],
|
|
237
|
+
dataLossPreventionEnabled: environment === 'prod',
|
|
238
|
+
encryptionAtRest: true,
|
|
239
|
+
encryptionInTransit: true
|
|
240
|
+
},
|
|
241
|
+
performance: {
|
|
242
|
+
enableCaching: environment !== 'dev',
|
|
243
|
+
cacheTimeout: 300,
|
|
244
|
+
batchSize: environment === 'prod' ? 100 : 50,
|
|
245
|
+
timeoutMs: 30000,
|
|
246
|
+
retryAttempts: 3,
|
|
247
|
+
retryDelayMs: 1000,
|
|
248
|
+
enableCompression: true,
|
|
249
|
+
enableCDN: environment === 'prod'
|
|
250
|
+
},
|
|
251
|
+
monitoring: {
|
|
252
|
+
enableApplicationInsights: true,
|
|
253
|
+
instrumentationKey: 'your-instrumentation-key',
|
|
254
|
+
logLevel: environment === 'prod' ? 'error' : environment === 'test' ? 'warn' : 'debug',
|
|
255
|
+
enableMetrics: true,
|
|
256
|
+
enableTracing: environment !== 'prod',
|
|
257
|
+
enableProfiling: environment === 'dev'
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
await fs.writeJson(envPath, environmentConfig, { spaces: 2 });
|
|
262
|
+
console.log(chalk.green(` ✓ Created ${envPath}`));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async function createBrandingFiles(answers) {
|
|
266
|
+
const brandingPath = 'src/branding';
|
|
267
|
+
await fs.ensureDir(brandingPath);
|
|
268
|
+
await fs.ensureDir(path.join(brandingPath, 'logos'));
|
|
269
|
+
|
|
270
|
+
// Create theme file
|
|
271
|
+
const themeContent = `// ${answers.clientName} Theme Configuration
|
|
272
|
+
import { ITheme } from '@fluentui/react';
|
|
273
|
+
|
|
274
|
+
export const ${answers.clientCode.toLowerCase()}Theme: ITheme = {
|
|
275
|
+
palette: {
|
|
276
|
+
themePrimary: '${answers.primaryColor}',
|
|
277
|
+
themeSecondary: '${answers.secondaryColor}',
|
|
278
|
+
themeTertiary: '#71afe5',
|
|
279
|
+
themeLight: '#c7e0f4',
|
|
280
|
+
themeLighter: '#deecf9',
|
|
281
|
+
themeLighterAlt: '#eff6fc',
|
|
282
|
+
black: '#000000',
|
|
283
|
+
blackTranslucent40: 'rgba(0,0,0,.4)',
|
|
284
|
+
neutralDark: '#201f1e',
|
|
285
|
+
neutralPrimary: '#323130',
|
|
286
|
+
neutralPrimaryAlt: '#3b3a39',
|
|
287
|
+
neutralSecondary: '#605e5c',
|
|
288
|
+
neutralTertiary: '#a19f9d',
|
|
289
|
+
neutralTertiaryAlt: '#c8c6c4',
|
|
290
|
+
neutralQuaternary: '#d2d0ce',
|
|
291
|
+
neutralQuaternaryAlt: '#e1dfdd',
|
|
292
|
+
neutralLight: '#edebe9',
|
|
293
|
+
neutralLighter: '#f3f2f1',
|
|
294
|
+
neutralLighterAlt: '#faf9f8',
|
|
295
|
+
white: '#ffffff',
|
|
296
|
+
yellowDark: '#d29200',
|
|
297
|
+
yellow: '#ffb900',
|
|
298
|
+
yellowLight: '#fff4ce',
|
|
299
|
+
orange: '#d83b01',
|
|
300
|
+
orangeLight: '#febf04',
|
|
301
|
+
orangeLighter: '#fcd116',
|
|
302
|
+
redDark: '#a4262c',
|
|
303
|
+
red: '#e81123',
|
|
304
|
+
magentaDark: '#5c2d91',
|
|
305
|
+
magenta: '#b4009e',
|
|
306
|
+
magentaLight: '#e3008c',
|
|
307
|
+
purpleDark: '#32145a',
|
|
308
|
+
purple: '#5c2d91',
|
|
309
|
+
purpleLight: '#b4a0ff',
|
|
310
|
+
blueDark: '#002050',
|
|
311
|
+
blueMid: '#00188f',
|
|
312
|
+
blue: '${answers.primaryColor}',
|
|
313
|
+
blueLight: '#40e0d0',
|
|
314
|
+
tealDark: '#004b50',
|
|
315
|
+
teal: '#008272',
|
|
316
|
+
tealLight: '#00bcf2',
|
|
317
|
+
greenDark: '#004b1c',
|
|
318
|
+
green: '#107c10',
|
|
319
|
+
greenLight: '#bad80a'
|
|
320
|
+
},
|
|
321
|
+
fonts: {
|
|
322
|
+
small: {
|
|
323
|
+
fontSize: '12px',
|
|
324
|
+
lineHeight: '16px'
|
|
325
|
+
},
|
|
326
|
+
medium: {
|
|
327
|
+
fontSize: '14px',
|
|
328
|
+
lineHeight: '20px',
|
|
329
|
+
fontFamily: 'Segoe UI, sans-serif'
|
|
330
|
+
},
|
|
331
|
+
large: {
|
|
332
|
+
fontSize: '18px',
|
|
333
|
+
lineHeight: '24px'
|
|
334
|
+
},
|
|
335
|
+
xLarge: {
|
|
336
|
+
fontSize: '20px',
|
|
337
|
+
lineHeight: '28px'
|
|
338
|
+
},
|
|
339
|
+
xxLarge: {
|
|
340
|
+
fontSize: '28px',
|
|
341
|
+
lineHeight: '36px'
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
};`;
|
|
345
|
+
|
|
346
|
+
await fs.writeFile(path.join(brandingPath, 'theme.ts'), themeContent);
|
|
347
|
+
|
|
348
|
+
// Create custom CSS file
|
|
349
|
+
const customCssContent = `/* ${answers.clientName} Custom Styles */
|
|
350
|
+
|
|
351
|
+
:root {
|
|
352
|
+
--client-primary-color: ${answers.primaryColor};
|
|
353
|
+
--client-secondary-color: ${answers.secondaryColor};
|
|
354
|
+
--client-font-family: 'Segoe UI', sans-serif;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/* Client-specific component overrides */
|
|
358
|
+
.client-header {
|
|
359
|
+
background-color: var(--client-primary-color);
|
|
360
|
+
color: white;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.client-navigation {
|
|
364
|
+
border-bottom: 2px solid var(--client-primary-color);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.client-button-primary {
|
|
368
|
+
background-color: var(--client-primary-color);
|
|
369
|
+
border-color: var(--client-primary-color);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.client-button-primary:hover {
|
|
373
|
+
background-color: var(--client-secondary-color);
|
|
374
|
+
border-color: var(--client-secondary-color);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/* Logo and branding */
|
|
378
|
+
.client-logo {
|
|
379
|
+
max-height: 40px;
|
|
380
|
+
width: auto;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/* Custom responsive breakpoints for client */
|
|
384
|
+
@media (max-width: 768px) {
|
|
385
|
+
.client-header {
|
|
386
|
+
padding: 10px;
|
|
387
|
+
}
|
|
388
|
+
}`;
|
|
389
|
+
|
|
390
|
+
await fs.writeFile(path.join(brandingPath, `${answers.clientCode.toLowerCase()}-custom.css`), customCssContent);
|
|
391
|
+
|
|
392
|
+
// Create logo placeholder README
|
|
393
|
+
const logoReadme = `# ${answers.clientName} Logos
|
|
394
|
+
|
|
395
|
+
Please add the following logo files to this directory:
|
|
396
|
+
|
|
397
|
+
- \`${answers.clientCode.toLowerCase()}-logo.png\` - Main logo (recommended: 200x60px)
|
|
398
|
+
- \`${answers.clientCode.toLowerCase()}-logo-white.png\` - White version for dark backgrounds
|
|
399
|
+
- \`${answers.clientCode.toLowerCase()}-favicon.ico\` - Favicon (16x16, 32x32px)
|
|
400
|
+
- \`${answers.clientCode.toLowerCase()}-logo-large.png\` - High resolution logo (400x120px)
|
|
401
|
+
|
|
402
|
+
## Logo Guidelines
|
|
403
|
+
|
|
404
|
+
- Use PNG format with transparent background
|
|
405
|
+
- Maintain aspect ratio when resizing
|
|
406
|
+
- Ensure logos are optimized for web use
|
|
407
|
+
- Test visibility on both light and dark backgrounds
|
|
408
|
+
`;
|
|
409
|
+
|
|
410
|
+
await fs.writeFile(path.join(brandingPath, 'logos', 'README.md'), logoReadme);
|
|
411
|
+
|
|
412
|
+
console.log(chalk.green(` ✓ Created branding files in ${brandingPath}/`));
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async function createDeploymentScripts(answers) {
|
|
416
|
+
const scriptsPath = 'scripts';
|
|
417
|
+
await fs.ensureDir(scriptsPath);
|
|
418
|
+
|
|
419
|
+
// Client-specific deployment script
|
|
420
|
+
const deployScript = `#!/bin/bash
|
|
421
|
+
# ${answers.clientName} Deployment Script
|
|
422
|
+
# Generated on ${new Date().toISOString()}
|
|
423
|
+
|
|
424
|
+
CLIENT_NAME="${answers.clientName}"
|
|
425
|
+
CLIENT_CODE="${answers.clientCode.toUpperCase()}"
|
|
426
|
+
PROJECT_ROOT="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
427
|
+
|
|
428
|
+
echo "🚀 Deploying \${CLIENT_NAME} project..."
|
|
429
|
+
|
|
430
|
+
# Validate environment parameter
|
|
431
|
+
if [ -z "$1" ]; then
|
|
432
|
+
echo "❌ Environment parameter required"
|
|
433
|
+
echo "Usage: $0 <environment>"
|
|
434
|
+
echo "Available environments: dev, test, staging, prod"
|
|
435
|
+
exit 1
|
|
436
|
+
fi
|
|
437
|
+
|
|
438
|
+
ENVIRONMENT=$1
|
|
439
|
+
|
|
440
|
+
# Check if environment config exists
|
|
441
|
+
if [ ! -f "\${PROJECT_ROOT}/config/environments/\${ENVIRONMENT}.json" ]; then
|
|
442
|
+
echo "❌ Environment configuration not found: \${ENVIRONMENT}.json"
|
|
443
|
+
exit 1
|
|
444
|
+
fi
|
|
445
|
+
|
|
446
|
+
echo "📋 Deploying to \${ENVIRONMENT} environment for \${CLIENT_NAME}..."
|
|
447
|
+
|
|
448
|
+
# Load environment configuration
|
|
449
|
+
export NODE_ENV=\${ENVIRONMENT}
|
|
450
|
+
|
|
451
|
+
# Run pre-deployment checks
|
|
452
|
+
echo "🔍 Running pre-deployment checks..."
|
|
453
|
+
npm run quality
|
|
454
|
+
if [ $? -ne 0 ]; then
|
|
455
|
+
echo "❌ Quality checks failed"
|
|
456
|
+
exit 1
|
|
457
|
+
fi
|
|
458
|
+
|
|
459
|
+
# Build for target environment
|
|
460
|
+
echo "🔨 Building for \${ENVIRONMENT}..."
|
|
461
|
+
npm run build:prod
|
|
462
|
+
if [ $? -ne 0 ]; then
|
|
463
|
+
echo "❌ Build failed"
|
|
464
|
+
exit 1
|
|
465
|
+
fi
|
|
466
|
+
|
|
467
|
+
# Run deployment
|
|
468
|
+
echo "📦 Deploying to \${ENVIRONMENT}..."
|
|
469
|
+
case \${ENVIRONMENT} in
|
|
470
|
+
"dev")
|
|
471
|
+
echo "🛠️ Deploying to development environment..."
|
|
472
|
+
# Add dev-specific deployment steps
|
|
473
|
+
;;
|
|
474
|
+
"test")
|
|
475
|
+
echo "🧪 Deploying to test environment..."
|
|
476
|
+
# Add test-specific deployment steps
|
|
477
|
+
;;
|
|
478
|
+
"prod")
|
|
479
|
+
echo "🚀 Deploying to production environment..."
|
|
480
|
+
# Add production-specific deployment steps
|
|
481
|
+
echo "⚠️ Production deployment requires manual approval"
|
|
482
|
+
;;
|
|
483
|
+
*)
|
|
484
|
+
echo "❌ Unknown environment: \${ENVIRONMENT}"
|
|
485
|
+
exit 1
|
|
486
|
+
;;
|
|
487
|
+
esac
|
|
488
|
+
|
|
489
|
+
echo "✅ Deployment completed for \${CLIENT_NAME} - \${ENVIRONMENT}"
|
|
490
|
+
echo "📝 Next steps:"
|
|
491
|
+
echo " 1. Verify deployment in Dynamics 365"
|
|
492
|
+
echo " 2. Run smoke tests"
|
|
493
|
+
echo " 3. Notify stakeholders"
|
|
494
|
+
`;
|
|
495
|
+
|
|
496
|
+
await fs.writeFile(path.join(scriptsPath, 'deploy-client.sh'), deployScript);
|
|
497
|
+
await fs.chmod(path.join(scriptsPath, 'deploy-client.sh'), '755');
|
|
498
|
+
|
|
499
|
+
console.log(chalk.green(` ✓ Created deployment scripts in ${scriptsPath}/`));
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
async function createProjectDocumentation(answers) {
|
|
503
|
+
const docsPath = 'docs';
|
|
504
|
+
await fs.ensureDir(docsPath);
|
|
505
|
+
|
|
506
|
+
// Client requirements document
|
|
507
|
+
const requirementsDoc = `# ${answers.clientName} - Technical Requirements
|
|
508
|
+
|
|
509
|
+
**Project:** ${answers.clientName} Dynamics 365 Implementation
|
|
510
|
+
**Industry:** ${answers.industry}
|
|
511
|
+
**Primary Contact:** ${answers.primaryContact} (${answers.contactEmail})
|
|
512
|
+
**Created:** ${new Date().toLocaleDateString()}
|
|
513
|
+
|
|
514
|
+
## Overview
|
|
515
|
+
|
|
516
|
+
This document outlines the technical requirements and specifications for the ${answers.clientName} Dynamics 365 implementation.
|
|
517
|
+
|
|
518
|
+
## Client Information
|
|
519
|
+
|
|
520
|
+
- **Company:** ${answers.clientName}
|
|
521
|
+
- **Industry:** ${answers.industry}
|
|
522
|
+
- **Timezone:** ${answers.timezone}
|
|
523
|
+
- **Primary Contact:** ${answers.primaryContact}
|
|
524
|
+
- **Email:** ${answers.contactEmail}
|
|
525
|
+
|
|
526
|
+
## Technical Requirements
|
|
527
|
+
|
|
528
|
+
### Environments
|
|
529
|
+
${answers.environments.map(env => `- ${env.charAt(0).toUpperCase() + env.slice(1)}`).join('\n')}
|
|
530
|
+
|
|
531
|
+
### Branding Requirements
|
|
532
|
+
- **Primary Color:** ${answers.primaryColor}
|
|
533
|
+
- **Secondary Color:** ${answers.secondaryColor}
|
|
534
|
+
- **Logo Requirements:** See branding guidelines
|
|
535
|
+
|
|
536
|
+
### Features
|
|
537
|
+
${answers.enableAdvancedFeatures ? `- Advanced logging and monitoring
|
|
538
|
+
- Custom workflows and business logic
|
|
539
|
+
- Enhanced reporting and dashboards
|
|
540
|
+
- Mobile optimization` : `- Standard CRM functionality
|
|
541
|
+
- Basic reporting
|
|
542
|
+
- Mobile responsive design`}
|
|
543
|
+
|
|
544
|
+
## Security Requirements
|
|
545
|
+
|
|
546
|
+
- Multi-factor authentication for production
|
|
547
|
+
- Data encryption at rest and in transit
|
|
548
|
+
- Audit logging enabled
|
|
549
|
+
- Role-based access control
|
|
550
|
+
|
|
551
|
+
## Compliance Requirements
|
|
552
|
+
|
|
553
|
+
- GDPR compliance required
|
|
554
|
+
- Data retention: 365 days
|
|
555
|
+
- Regular security assessments
|
|
556
|
+
|
|
557
|
+
## Integration Requirements
|
|
558
|
+
|
|
559
|
+
TBD - To be defined based on client needs
|
|
560
|
+
|
|
561
|
+
## Deployment Strategy
|
|
562
|
+
|
|
563
|
+
- Blue-green deployment for production
|
|
564
|
+
- Automated rollback capability
|
|
565
|
+
- Maintenance window: 2:00 AM ${answers.timezone}
|
|
566
|
+
|
|
567
|
+
## Support Requirements
|
|
568
|
+
|
|
569
|
+
- Business hours support during implementation
|
|
570
|
+
- Post-go-live support plan TBD
|
|
571
|
+
|
|
572
|
+
## Success Criteria
|
|
573
|
+
|
|
574
|
+
TBD - To be defined with client stakeholders
|
|
575
|
+
|
|
576
|
+
## Next Steps
|
|
577
|
+
|
|
578
|
+
1. Review and approve requirements
|
|
579
|
+
2. Define detailed functional specifications
|
|
580
|
+
3. Create project timeline
|
|
581
|
+
4. Begin development sprint planning
|
|
582
|
+
`;
|
|
583
|
+
|
|
584
|
+
await fs.writeFile(path.join(docsPath, 'client-requirements.md'), requirementsDoc);
|
|
585
|
+
|
|
586
|
+
// Project README
|
|
587
|
+
const projectReadme = `# ${answers.clientName} - Dynamics 365 Project
|
|
588
|
+
|
|
589
|
+
${answers.industry} company Dynamics 365 implementation using the Dynamics UI Kit enterprise consulting framework.
|
|
590
|
+
|
|
591
|
+
## Quick Start
|
|
592
|
+
|
|
593
|
+
\`\`\`bash
|
|
594
|
+
# Install dependencies
|
|
595
|
+
npm install
|
|
596
|
+
|
|
597
|
+
# Start development
|
|
598
|
+
npm run dev
|
|
599
|
+
|
|
600
|
+
# Build for production
|
|
601
|
+
npm run build:prod
|
|
602
|
+
|
|
603
|
+
# Deploy to environment
|
|
604
|
+
./scripts/deploy-client.sh dev
|
|
605
|
+
\`\`\`
|
|
606
|
+
|
|
607
|
+
## Project Structure
|
|
608
|
+
|
|
609
|
+
- \`config/\` - Client and environment configurations
|
|
610
|
+
- \`src/branding/\` - Client-specific branding and themes
|
|
611
|
+
- \`src/entities/\` - Custom entity definitions
|
|
612
|
+
- \`src/pages/\` - Custom page templates
|
|
613
|
+
- \`scripts/\` - Deployment and automation scripts
|
|
614
|
+
- \`docs/\` - Project documentation
|
|
615
|
+
|
|
616
|
+
## Configuration
|
|
617
|
+
|
|
618
|
+
Client configuration is managed in \`config/client.json\`. Environment-specific settings are in \`config/environments/\`.
|
|
619
|
+
|
|
620
|
+
## Branding
|
|
621
|
+
|
|
622
|
+
Client branding assets should be placed in \`src/branding/logos/\`. The theme is configured in \`src/branding/theme.ts\`.
|
|
623
|
+
|
|
624
|
+
## Deployment
|
|
625
|
+
|
|
626
|
+
Use the deployment script for environment-specific deployments:
|
|
627
|
+
|
|
628
|
+
\`\`\`bash
|
|
629
|
+
# Deploy to development
|
|
630
|
+
./scripts/deploy-client.sh dev
|
|
631
|
+
|
|
632
|
+
# Deploy to production (requires approval)
|
|
633
|
+
./scripts/deploy-client.sh prod
|
|
634
|
+
\`\`\`
|
|
635
|
+
|
|
636
|
+
## Development Workflow
|
|
637
|
+
|
|
638
|
+
1. Create feature branch
|
|
639
|
+
2. Implement changes
|
|
640
|
+
3. Run quality checks: \`npm run quality\`
|
|
641
|
+
4. Deploy to dev: \`./scripts/deploy-client.sh dev\`
|
|
642
|
+
5. Test and get approval
|
|
643
|
+
6. Deploy to production
|
|
644
|
+
|
|
645
|
+
## Support
|
|
646
|
+
|
|
647
|
+
For technical issues, contact the development team.
|
|
648
|
+
For client-specific questions, contact ${answers.primaryContact} at ${answers.contactEmail}.
|
|
649
|
+
|
|
650
|
+
## Documentation
|
|
651
|
+
|
|
652
|
+
- [Client Requirements](docs/client-requirements.md)
|
|
653
|
+
- [Technical Specifications](docs/technical-specifications.md)
|
|
654
|
+
- [Deployment Guide](docs/deployment-guide.md)
|
|
655
|
+
`;
|
|
656
|
+
|
|
657
|
+
await fs.writeFile('README.md', projectReadme);
|
|
658
|
+
|
|
659
|
+
console.log(chalk.green(` ✓ Created project documentation in ${docsPath}/`));
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// Run the setup if called directly
|
|
663
|
+
if (require.main === module) {
|
|
664
|
+
setupClientProject().catch(console.error);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
module.exports = { setupClientProject };
|