devextreme-schematics 1.2.18 → 1.2.22
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/package.json +2 -2
- package/src/add-app-template/index.ts +30 -0
- package/src/add-app-template/index_spec.ts +73 -0
- package/src/add-layout/files/e2e/src/app.e2e-spec.ts +14 -14
- package/src/add-layout/files/e2e/src/app.po.ts +11 -11
- package/src/add-layout/files/src/app/app-navigation.ts +1 -1
- package/src/add-layout/files/src/app/layouts/index.ts +3 -3
- package/src/add-layout/files/src/app/shared/components/change-password-form/change-password-form.component.html +8 -6
- package/src/add-layout/files/src/app/shared/components/create-account-form/create-account-form.component.html +9 -7
- package/src/add-layout/files/src/app/shared/components/footer/footer.component.ts +19 -19
- package/src/add-layout/files/src/app/shared/components/login-form/login-form.component.html +8 -6
- package/src/add-layout/files/src/app/shared/components/reset-password-form/reset-password-form.component.html +8 -6
- package/src/add-layout/index.ts +386 -0
- package/src/add-layout/index_spec.ts +340 -0
- package/src/add-sample-views/files/pages/home/home.component.ts +10 -10
- package/src/add-sample-views/files/pages/profile/profile.component.ts +33 -33
- package/src/add-sample-views/index.ts +141 -0
- package/src/add-sample-views/index_spec.ts +74 -0
- package/src/add-view/index.ts +165 -0
- package/src/add-view/index_spec.ts +155 -0
- package/src/install/index.ts +86 -0
- package/src/install/index_spec.ts +106 -0
- package/src/install/schema.json +1 -1
- package/src/utility/array.ts +3 -0
- package/src/utility/change.js +1 -1
- package/src/utility/change.ts +66 -0
- package/src/utility/latest-versions.js +2 -2
- package/src/utility/latest-versions.ts +6 -0
- package/src/utility/modify-json-file.ts +13 -0
- package/src/utility/project.ts +25 -0
- package/src/utility/routing.js +4 -4
- package/src/utility/routing.ts +44 -0
- package/src/utility/source.ts +16 -0
- package/src/utility/string.ts +5 -0
- package/src/utility/styles.ts +33 -0
@@ -0,0 +1,165 @@
|
|
1
|
+
import {
|
2
|
+
Rule,
|
3
|
+
chain,
|
4
|
+
Tree,
|
5
|
+
SchematicsException,
|
6
|
+
externalSchematic
|
7
|
+
} from '@angular-devkit/schematics';
|
8
|
+
|
9
|
+
import {
|
10
|
+
findModuleFromOptions
|
11
|
+
} from '@schematics/angular/utility/find-module';
|
12
|
+
|
13
|
+
import {
|
14
|
+
insertItemToArray
|
15
|
+
} from '../utility/change';
|
16
|
+
|
17
|
+
import {
|
18
|
+
hasComponentInRoutes,
|
19
|
+
getRoute,
|
20
|
+
findRoutesInSource
|
21
|
+
} from '../utility/routing';
|
22
|
+
|
23
|
+
import { getSourceFile } from '../utility/source';
|
24
|
+
|
25
|
+
import { strings, basename, normalize, dirname } from '@angular-devkit/core';
|
26
|
+
|
27
|
+
import {
|
28
|
+
getProjectName,
|
29
|
+
getApplicationPath
|
30
|
+
} from '../utility/project';
|
31
|
+
import { humanize } from '../utility/string';
|
32
|
+
|
33
|
+
function getPathToFile(host: Tree, projectName: string, moduleName: string) {
|
34
|
+
const rootPath = getApplicationPath(host, projectName);
|
35
|
+
|
36
|
+
try {
|
37
|
+
return findModuleFromOptions(host, { name: moduleName, path: rootPath, module: moduleName });
|
38
|
+
} catch (error) {
|
39
|
+
return;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
function addViewToNavigation(options: any) {
|
44
|
+
return (host: Tree) => {
|
45
|
+
const navigationName = 'app-navigation';
|
46
|
+
const navigationFilePath = getPathToFile(host, options.project, navigationName);
|
47
|
+
|
48
|
+
if (!navigationFilePath) {
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
|
52
|
+
const source = getSourceFile(host, navigationFilePath)!;
|
53
|
+
const pagePath = strings.dasherize(options.name);
|
54
|
+
const name = strings.dasherize(basename(normalize(options.name)));
|
55
|
+
const title = humanize(name);
|
56
|
+
const navigationItem = ` {
|
57
|
+
text: '${title}',
|
58
|
+
path: '/${pagePath}',
|
59
|
+
icon: '${options.icon}'
|
60
|
+
}`;
|
61
|
+
|
62
|
+
insertItemToArray(host, navigationFilePath, source, navigationItem, { location: 'end' });
|
63
|
+
|
64
|
+
return host;
|
65
|
+
};
|
66
|
+
}
|
67
|
+
|
68
|
+
function addRedirectRoute(host: Tree, routingModulePath: string, page: string) {
|
69
|
+
const source = getSourceFile(host, routingModulePath)!;
|
70
|
+
const content = source.getText();
|
71
|
+
if (content.match(/path:\s*'\*\*'/g)) {
|
72
|
+
return;
|
73
|
+
}
|
74
|
+
|
75
|
+
const routes = findRoutesInSource(source)!;
|
76
|
+
const redirectRoute = ` {
|
77
|
+
path: '**',
|
78
|
+
redirectTo: '${strings.dasherize(page)}'
|
79
|
+
}`;
|
80
|
+
|
81
|
+
insertItemToArray(host, routingModulePath, routes, redirectRoute, { location: 'end' });
|
82
|
+
}
|
83
|
+
|
84
|
+
export function addViewToRouting(options: any) {
|
85
|
+
return (host: Tree) => {
|
86
|
+
const routingModulePath = getPathToFile(host, options.project, options.module);
|
87
|
+
|
88
|
+
if (!routingModulePath) {
|
89
|
+
throw new SchematicsException('Specified module does not exist.');
|
90
|
+
}
|
91
|
+
|
92
|
+
addRedirectRoute(host, routingModulePath, options.name);
|
93
|
+
|
94
|
+
const source = getSourceFile(host, routingModulePath)!;
|
95
|
+
const routes = findRoutesInSource(source);
|
96
|
+
|
97
|
+
if (!routes) {
|
98
|
+
throw new SchematicsException('No routes found.');
|
99
|
+
}
|
100
|
+
|
101
|
+
if (!hasComponentInRoutes(routes, options.name)) {
|
102
|
+
const route = getRoute(options.name);
|
103
|
+
insertItemToArray(host, routingModulePath, routes, route);
|
104
|
+
}
|
105
|
+
return host;
|
106
|
+
};
|
107
|
+
}
|
108
|
+
|
109
|
+
function getPathForView(name: string) {
|
110
|
+
if (name.includes('/')) {
|
111
|
+
return name;
|
112
|
+
}
|
113
|
+
return 'pages/' + name;
|
114
|
+
}
|
115
|
+
|
116
|
+
function getModuleName(addRoute: boolean, moduleName: string) {
|
117
|
+
if (!moduleName && addRoute) {
|
118
|
+
return 'app-routing';
|
119
|
+
}
|
120
|
+
return moduleName;
|
121
|
+
}
|
122
|
+
|
123
|
+
function addContentToView(options: any) {
|
124
|
+
return (host: Tree) => {
|
125
|
+
const name = strings.dasherize(basename(normalize(options.name)));
|
126
|
+
const path = `${dirname(options.name)}/${name}`;
|
127
|
+
const title = humanize(name);
|
128
|
+
const componentPath = `/${getApplicationPath(host, options.project)}${path}/${name}.component.html`;
|
129
|
+
if (host.exists(componentPath)) {
|
130
|
+
host.overwrite(
|
131
|
+
componentPath,
|
132
|
+
`<h2 class="content-block">${title}</h2>
|
133
|
+
<div class="content-block">
|
134
|
+
<div class="dx-card responsive-paddings">Put your content here</div>
|
135
|
+
</div>
|
136
|
+
`);
|
137
|
+
}
|
138
|
+
return host;
|
139
|
+
};
|
140
|
+
}
|
141
|
+
|
142
|
+
export default function(options: any): Rule {
|
143
|
+
return (host: Tree) => {
|
144
|
+
const addRoute = options.addRoute;
|
145
|
+
const project = getProjectName(host, options);
|
146
|
+
const module = getModuleName(addRoute, options.module);
|
147
|
+
const name = getPathForView(options.name);
|
148
|
+
const rules = [externalSchematic('@schematics/angular', 'component', {
|
149
|
+
name,
|
150
|
+
project,
|
151
|
+
module,
|
152
|
+
skipTests: options.skipTests,
|
153
|
+
inlineStyle: options.inlineStyle,
|
154
|
+
prefix: options.prefix
|
155
|
+
}),
|
156
|
+
addContentToView({ name, project })
|
157
|
+
];
|
158
|
+
|
159
|
+
if (addRoute) {
|
160
|
+
rules.push(addViewToRouting({ name, project, module }));
|
161
|
+
rules.push(addViewToNavigation({ name, icon: options.icon, project }));
|
162
|
+
}
|
163
|
+
return chain(rules);
|
164
|
+
};
|
165
|
+
}
|
@@ -0,0 +1,155 @@
|
|
1
|
+
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
2
|
+
import { Schema as WorkspaceOptions } from '@schematics/angular/workspace/schema';
|
3
|
+
import * as path from 'path';
|
4
|
+
|
5
|
+
const collectionPath = path.join(__dirname, '../collection.json');
|
6
|
+
|
7
|
+
describe('view', () => {
|
8
|
+
const appOptions: any = {
|
9
|
+
name: 'testApp',
|
10
|
+
projectRoot: '',
|
11
|
+
inlineStyle: false,
|
12
|
+
inlineTemplate: false,
|
13
|
+
routing: true,
|
14
|
+
style: 'css',
|
15
|
+
skipTests: false,
|
16
|
+
skipPackageJson: false
|
17
|
+
};
|
18
|
+
|
19
|
+
const workspaceOptions: WorkspaceOptions = {
|
20
|
+
name: 'workspace',
|
21
|
+
version: '6.0.0'
|
22
|
+
};
|
23
|
+
|
24
|
+
const componentOptions: any = {
|
25
|
+
name: 'test',
|
26
|
+
inlineStyle: false,
|
27
|
+
inlineTemplate: false,
|
28
|
+
changeDetection: 'Default',
|
29
|
+
styleext: 'css',
|
30
|
+
skipImport: true,
|
31
|
+
module: undefined,
|
32
|
+
export: false,
|
33
|
+
project: 'testApp'
|
34
|
+
};
|
35
|
+
|
36
|
+
const angularSchematicsCollection = require.resolve('../../node_modules/@schematics/angular/collection.json');
|
37
|
+
const schematicRunner = new SchematicTestRunner('@schematics/angular', angularSchematicsCollection);
|
38
|
+
let appTree: UnitTestTree;
|
39
|
+
|
40
|
+
beforeEach(async () => {
|
41
|
+
appTree = await schematicRunner.runSchematicAsync('workspace', workspaceOptions).toPromise();
|
42
|
+
appTree = await schematicRunner.runSchematicAsync('application', appOptions, appTree).toPromise();
|
43
|
+
});
|
44
|
+
|
45
|
+
it('should create new view', async () => {
|
46
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
47
|
+
let tree = await runner.runSchematicAsync('add-layout', { layout: 'side-nav-outer-toolbar' }, appTree).toPromise();
|
48
|
+
tree = await runner.runSchematicAsync('add-view', componentOptions, appTree).toPromise();
|
49
|
+
|
50
|
+
expect(tree.files).toContain('/src/app/pages/test/test.component.ts');
|
51
|
+
expect(tree.files).toContain('/src/app/pages/test/test.component.html');
|
52
|
+
|
53
|
+
const content = tree.readContent('/src/app/pages/test/test.component.html');
|
54
|
+
|
55
|
+
expect(content).toMatch(/<h2 class="content-block">Test<\/h2>/);
|
56
|
+
});
|
57
|
+
|
58
|
+
it('should add view to default routing module', async () => {
|
59
|
+
const options = { ...componentOptions, addRoute: true };
|
60
|
+
|
61
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
62
|
+
let tree = await runner.runSchematicAsync('add-layout', { layout: 'side-nav-outer-toolbar' }, appTree).toPromise();
|
63
|
+
tree = await runner.runSchematicAsync('add-view', options, tree).toPromise();
|
64
|
+
tree = await runner.runSchematicAsync('add-view', { ...options, name: 'test2' }, tree).toPromise();
|
65
|
+
const moduleContent = tree.readContent('/src/app/app-routing.module.ts');
|
66
|
+
|
67
|
+
expect(moduleContent).toContain(`const routes: Routes = [
|
68
|
+
{
|
69
|
+
path: 'pages/test2',
|
70
|
+
component: Test2Component,
|
71
|
+
canActivate: [ AuthGuardService ]
|
72
|
+
},
|
73
|
+
{
|
74
|
+
path: 'pages/test',
|
75
|
+
component: TestComponent,
|
76
|
+
canActivate: [ AuthGuardService ]
|
77
|
+
},
|
78
|
+
{
|
79
|
+
path: 'login-form',
|
80
|
+
component: LoginFormComponent,
|
81
|
+
canActivate: [ AuthGuardService ]
|
82
|
+
},
|
83
|
+
{
|
84
|
+
path: '**',
|
85
|
+
redirectTo: 'pages/test'
|
86
|
+
}
|
87
|
+
];`);
|
88
|
+
});
|
89
|
+
|
90
|
+
it('should add view to other routing module', async () => {
|
91
|
+
const options = { ...componentOptions, addRoute: true, module: 'test/test-routing' };
|
92
|
+
|
93
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
94
|
+
let tree = await runner.runExternalSchematicAsync('@schematics/angular', 'module', {
|
95
|
+
name: 'test',
|
96
|
+
routing: true,
|
97
|
+
project: 'testApp'
|
98
|
+
}, appTree).toPromise();
|
99
|
+
|
100
|
+
tree = await runner.runSchematicAsync('add-layout', {
|
101
|
+
layout: 'side-nav-outer-toolbar',
|
102
|
+
project: 'testApp',
|
103
|
+
name: 'test'
|
104
|
+
}, tree).toPromise();
|
105
|
+
tree = await runner.runSchematicAsync('add-view', options, tree).toPromise();
|
106
|
+
|
107
|
+
const moduleContent = tree.readContent('/src/app/test/test-routing.module.ts');
|
108
|
+
|
109
|
+
expect(moduleContent).toMatch(/component: TestComponent/);
|
110
|
+
expect(moduleContent).toMatch(/path: 'pages\/test'/);
|
111
|
+
expect(moduleContent).toContain('canActivate: [ AuthGuardService ]');
|
112
|
+
});
|
113
|
+
|
114
|
+
it('should add view to navigation', async () => {
|
115
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
116
|
+
let tree = await runner.runSchematicAsync('add-layout', { layout: 'side-nav-outer-toolbar' }, appTree).toPromise();
|
117
|
+
tree = await runner.runSchematicAsync('add-view', componentOptions, tree).toPromise();
|
118
|
+
|
119
|
+
componentOptions.name = 'some test';
|
120
|
+
componentOptions.icon = 'home';
|
121
|
+
tree = await runner.runSchematicAsync('add-view', componentOptions, tree).toPromise();
|
122
|
+
|
123
|
+
const moduleContent = tree.readContent('/src/app/app-navigation.ts');
|
124
|
+
|
125
|
+
expect(moduleContent).toMatch(/text: 'Some Test'/);
|
126
|
+
expect(moduleContent).toMatch(/icon: 'home'/);
|
127
|
+
expect(moduleContent).toMatch(/text: 'Test'/);
|
128
|
+
expect(moduleContent).toMatch(/icon: 'folder'/);
|
129
|
+
|
130
|
+
expect(moduleContent).toContain(`navigation = [
|
131
|
+
{
|
132
|
+
text: 'Test',
|
133
|
+
path: '/pages/test',
|
134
|
+
icon: 'folder'
|
135
|
+
},
|
136
|
+
{
|
137
|
+
text: 'Some Test',
|
138
|
+
path: '/pages/some-test',
|
139
|
+
icon: 'home'
|
140
|
+
}
|
141
|
+
];`);
|
142
|
+
const pageContent = tree.readContent('/src/app/pages/some-test/some-test.component.html');
|
143
|
+
expect(pageContent).toMatch(/<h2 class="content-block">Some Test<\/h2>/);
|
144
|
+
});
|
145
|
+
|
146
|
+
it('should create new view with path', async () => {
|
147
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
148
|
+
componentOptions.name = 'folder/test';
|
149
|
+
let tree = await runner.runSchematicAsync('add-layout', { layout: 'side-nav-outer-toolbar' }, appTree).toPromise();
|
150
|
+
tree = await runner.runSchematicAsync('add-view', componentOptions, appTree).toPromise();
|
151
|
+
|
152
|
+
expect(tree.files).toContain('/src/app/folder/test/test.component.ts');
|
153
|
+
expect(tree.files).toContain('/src/app/folder/test/test.component.html');
|
154
|
+
});
|
155
|
+
});
|
@@ -0,0 +1,86 @@
|
|
1
|
+
import {
|
2
|
+
Rule,
|
3
|
+
Tree,
|
4
|
+
SchematicContext,
|
5
|
+
chain
|
6
|
+
} from '@angular-devkit/schematics';
|
7
|
+
|
8
|
+
import { addStylesToApp } from '../utility/styles';
|
9
|
+
|
10
|
+
import {
|
11
|
+
NodeDependencyType,
|
12
|
+
addPackageJsonDependency
|
13
|
+
} from '@schematics/angular/utility/dependencies';
|
14
|
+
|
15
|
+
import {
|
16
|
+
NodePackageInstallTask
|
17
|
+
} from '@angular-devkit/schematics/tasks';
|
18
|
+
|
19
|
+
import { latestVersions } from '../utility/latest-versions';
|
20
|
+
import { modifyJSONFile } from '../utility/modify-json-file';
|
21
|
+
|
22
|
+
export default function(options: any): Rule {
|
23
|
+
return chain([
|
24
|
+
(host: Tree) => addDevExtremeDependency(host, { dxversion: options.dxversion }),
|
25
|
+
(host: Tree) => addDevExtremeCSS(host, { project: options.project }),
|
26
|
+
(host: Tree) => reqisterJSZip(host),
|
27
|
+
(_, context: SchematicContext) => {
|
28
|
+
context.addTask(new NodePackageInstallTask());
|
29
|
+
}
|
30
|
+
]);
|
31
|
+
}
|
32
|
+
|
33
|
+
function addDevExtremeDependency(host: Tree, options: any) {
|
34
|
+
addPackageJsonDependency(host, {
|
35
|
+
type: NodeDependencyType.Default,
|
36
|
+
name: 'devextreme',
|
37
|
+
version: options.dxversion || latestVersions['devextreme']
|
38
|
+
});
|
39
|
+
addPackageJsonDependency(host, {
|
40
|
+
type: NodeDependencyType.Default,
|
41
|
+
name: 'devextreme-angular',
|
42
|
+
version: options.dxversion || latestVersions['devextreme-angular']
|
43
|
+
});
|
44
|
+
addPackageJsonDependency(host, {
|
45
|
+
type: NodeDependencyType.Dev,
|
46
|
+
name: 'devextreme-cli',
|
47
|
+
version: latestVersions['devextreme-cli']
|
48
|
+
});
|
49
|
+
addPackageJsonDependency(host, {
|
50
|
+
type: NodeDependencyType.Dev,
|
51
|
+
name: 'devextreme-themebuilder',
|
52
|
+
version: options.dxversion || latestVersions['devextreme']
|
53
|
+
});
|
54
|
+
|
55
|
+
return host;
|
56
|
+
}
|
57
|
+
|
58
|
+
function addDevExtremeCSS(host: Tree, options: any) {
|
59
|
+
modifyJSONFile(host, './angular.json', config => {
|
60
|
+
|
61
|
+
return addStylesToApp(host, options.project, config);
|
62
|
+
});
|
63
|
+
|
64
|
+
return host;
|
65
|
+
}
|
66
|
+
|
67
|
+
function reqisterJSZip(host: Tree) {
|
68
|
+
modifyJSONFile(host, './tsconfig.app.json', config => {
|
69
|
+
const compilerOptions = config['compilerOptions'];
|
70
|
+
let paths = compilerOptions['paths'];
|
71
|
+
|
72
|
+
if (!paths) {
|
73
|
+
paths = {};
|
74
|
+
}
|
75
|
+
|
76
|
+
if (!paths['jszip']) {
|
77
|
+
paths['jszip'] = ['node_modules/jszip/dist/jszip.min.js'];
|
78
|
+
}
|
79
|
+
|
80
|
+
compilerOptions['paths'] = paths;
|
81
|
+
|
82
|
+
return config;
|
83
|
+
});
|
84
|
+
|
85
|
+
return host;
|
86
|
+
}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
2
|
+
import { Schema as WorkspaceOptions } from '@schematics/angular/workspace/schema';
|
3
|
+
import * as path from 'path';
|
4
|
+
import { latestVersions } from '../utility/latest-versions';
|
5
|
+
|
6
|
+
const collectionPath = path.join(__dirname, '../collection.json');
|
7
|
+
|
8
|
+
describe('install', () => {
|
9
|
+
// TODO: Extract workspase preparing somewhere
|
10
|
+
const appOptions: any = {
|
11
|
+
name: 'testApp',
|
12
|
+
projectRoot: '',
|
13
|
+
inlineStyle: false,
|
14
|
+
inlineTemplate: false,
|
15
|
+
routing: true,
|
16
|
+
style: 'css',
|
17
|
+
skipTests: false,
|
18
|
+
skipPackageJson: false
|
19
|
+
};
|
20
|
+
|
21
|
+
const workspaceOptions: WorkspaceOptions = {
|
22
|
+
name: 'workspace',
|
23
|
+
// TODO: use angular latest-versions module
|
24
|
+
version: '6.0.0'
|
25
|
+
};
|
26
|
+
|
27
|
+
const angularSchematicsCollection = require.resolve('../../node_modules/@schematics/angular/collection.json');
|
28
|
+
const schematicRunner = new SchematicTestRunner('@schematics/angular', angularSchematicsCollection);
|
29
|
+
let appTree: UnitTestTree;
|
30
|
+
|
31
|
+
beforeEach(async () => {
|
32
|
+
appTree = await schematicRunner.runSchematicAsync('workspace', workspaceOptions).toPromise();
|
33
|
+
appTree = await schematicRunner.runSchematicAsync('application', appOptions, appTree).toPromise();
|
34
|
+
});
|
35
|
+
|
36
|
+
it('should add devextreme dependency (default)', async () => {
|
37
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
38
|
+
const tree = await runner.runSchematicAsync('install', {}, appTree).toPromise();
|
39
|
+
const packageConfig = JSON.parse(tree.readContent('package.json'));
|
40
|
+
|
41
|
+
expect(packageConfig.dependencies['devextreme']).toBe(latestVersions['devextreme']);
|
42
|
+
expect(packageConfig.dependencies['devextreme-angular']).toBe(latestVersions['devextreme-angular']);
|
43
|
+
expect(packageConfig.devDependencies['devextreme-themebuilder']).toBe(latestVersions['devextreme']);
|
44
|
+
});
|
45
|
+
|
46
|
+
it('should add devextreme dependency (custom)', async () => {
|
47
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
48
|
+
const tree = await runner.runSchematicAsync('install', { dxversion: '18.2.5' }, appTree).toPromise();
|
49
|
+
const packageConfig = JSON.parse(tree.readContent('package.json'));
|
50
|
+
|
51
|
+
expect(packageConfig.dependencies.devextreme).toBe('18.2.5');
|
52
|
+
expect(packageConfig.devDependencies['devextreme-themebuilder']).toBe('18.2.5');
|
53
|
+
});
|
54
|
+
|
55
|
+
it('should add devextreme cli devDependency', async () => {
|
56
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
57
|
+
const tree = await runner.runSchematicAsync('install', { dxversion: '18.2.5' }, appTree).toPromise();
|
58
|
+
const packageConfig = JSON.parse(tree.readContent('package.json'));
|
59
|
+
|
60
|
+
expect(packageConfig.devDependencies['devextreme-cli']).toBeDefined();
|
61
|
+
});
|
62
|
+
|
63
|
+
it('should add devextreme styles', async () => {
|
64
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
65
|
+
const tree = await runner.runSchematicAsync('install', {}, appTree).toPromise();
|
66
|
+
const angularConfig = JSON.parse(tree.readContent('angular.json'));
|
67
|
+
const styles = angularConfig['projects']['testApp']['architect']['build']['options']['styles'];
|
68
|
+
|
69
|
+
expect(styles[0]).toBe('node_modules/devextreme/dist/css/dx.common.css');
|
70
|
+
expect(styles[1]).toBe('node_modules/devextreme/dist/css/dx.light.css');
|
71
|
+
});
|
72
|
+
|
73
|
+
it('should register jszip', async () => {
|
74
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
75
|
+
const tree = await runner.runSchematicAsync('install', {}, appTree).toPromise();
|
76
|
+
const tsconfig = JSON.parse(tree.readContent('tsconfig.app.json'));
|
77
|
+
const jszip = tsconfig['compilerOptions']['paths']['jszip'];
|
78
|
+
|
79
|
+
expect(jszip[0]).toBe('node_modules/jszip/dist/jszip.min.js');
|
80
|
+
});
|
81
|
+
|
82
|
+
it('should add devextreme styles to the specified project', async () => {
|
83
|
+
const secondAppOptions: any = {
|
84
|
+
name: 'testApp2',
|
85
|
+
inlineStyle: false,
|
86
|
+
inlineTemplate: false,
|
87
|
+
projectRoot: 'src2',
|
88
|
+
routing: true,
|
89
|
+
style: 'css',
|
90
|
+
skipTests: false,
|
91
|
+
skipPackageJson: false
|
92
|
+
};
|
93
|
+
|
94
|
+
appTree = await schematicRunner.runSchematicAsync('application', secondAppOptions, appTree).toPromise();
|
95
|
+
|
96
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
97
|
+
const tree = await runner.runSchematicAsync('install', { project: 'testApp2' }, appTree).toPromise();
|
98
|
+
const angularConfig = JSON.parse(tree.readContent('angular.json'));
|
99
|
+
const styles = angularConfig['projects']['testApp2']['architect']['build']['options']['styles'];
|
100
|
+
|
101
|
+
expect(styles[0]).toBe('node_modules/devextreme/dist/css/dx.common.css');
|
102
|
+
expect(styles[1]).toBe('node_modules/devextreme/dist/css/dx.light.css');
|
103
|
+
|
104
|
+
expect(angularConfig['projects']['testApp']['architect']['build']['options']['styles'].length).toBe(1);
|
105
|
+
});
|
106
|
+
});
|
package/src/install/schema.json
CHANGED
package/src/utility/change.js
CHANGED
@@ -0,0 +1,66 @@
|
|
1
|
+
import { Tree } from '@angular-devkit/schematics';
|
2
|
+
import { InsertChange, Change } from '@schematics/angular/utility/change';
|
3
|
+
|
4
|
+
import {
|
5
|
+
Node
|
6
|
+
} from 'typescript';
|
7
|
+
|
8
|
+
const newLine = `
|
9
|
+
`;
|
10
|
+
|
11
|
+
export function applyChanges(host: Tree, changes: Change[], filePath: string) {
|
12
|
+
const recorder = host.beginUpdate(filePath);
|
13
|
+
|
14
|
+
changes.forEach((change: InsertChange) => {
|
15
|
+
recorder.insertLeft(change.pos, change.toAdd);
|
16
|
+
});
|
17
|
+
|
18
|
+
host.commitUpdate(recorder);
|
19
|
+
|
20
|
+
return host;
|
21
|
+
}
|
22
|
+
|
23
|
+
// TODO: implement options.index
|
24
|
+
// TODO: implement spaces shift calculation
|
25
|
+
export function insertItemToArray(
|
26
|
+
host: Tree,
|
27
|
+
filePath: string,
|
28
|
+
node: Node,
|
29
|
+
item: string,
|
30
|
+
options: { location: 'start' | 'end' } = { location: 'start' }
|
31
|
+
) {
|
32
|
+
const isItemValid = /^\s*\{[\s\S]*\}\s*$/m.test(item);
|
33
|
+
if (!isItemValid) {
|
34
|
+
return host;
|
35
|
+
}
|
36
|
+
|
37
|
+
const nodeContent = node.getText();
|
38
|
+
const nodePosition = node.getStart();
|
39
|
+
const leftBracketPosition = nodePosition + nodeContent.indexOf('[');
|
40
|
+
const rightBracketPosition = nodePosition + nodeContent.lastIndexOf(']');
|
41
|
+
let itemPosition = leftBracketPosition + 1;
|
42
|
+
let fileRecorder = host.beginUpdate(filePath);
|
43
|
+
|
44
|
+
item = newLine + item;
|
45
|
+
|
46
|
+
const isNodeEmpty = !/\[[\s\S]*\S+[\s\S]*\]/m.test(nodeContent);
|
47
|
+
if (isNodeEmpty) {
|
48
|
+
const formattedArray = `[${newLine}]`;
|
49
|
+
fileRecorder.remove(leftBracketPosition, rightBracketPosition - leftBracketPosition + 1);
|
50
|
+
fileRecorder.insertLeft(leftBracketPosition, formattedArray);
|
51
|
+
host.commitUpdate(fileRecorder);
|
52
|
+
fileRecorder = host.beginUpdate(filePath);
|
53
|
+
} else {
|
54
|
+
if (options.location === 'end') {
|
55
|
+
itemPosition = nodePosition + nodeContent.lastIndexOf('}') + 1;
|
56
|
+
item = ',' + item;
|
57
|
+
} else {
|
58
|
+
item = item + ',';
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
fileRecorder.insertLeft(itemPosition, item);
|
63
|
+
host.commitUpdate(fileRecorder);
|
64
|
+
|
65
|
+
return host;
|
66
|
+
}
|
@@ -2,8 +2,8 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
// TODO: implement
|
4
4
|
exports.latestVersions = {
|
5
|
-
'devextreme': '^21.
|
6
|
-
'devextreme-angular': '^21.
|
5
|
+
'devextreme': '^21.2.3',
|
6
|
+
'devextreme-angular': '^21.2.3',
|
7
7
|
'devextreme-cli': 'latest'
|
8
8
|
};
|
9
9
|
//# sourceMappingURL=latest-versions.js.map
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { Tree } from '@angular-devkit/schematics';
|
2
|
+
|
3
|
+
export function modifyJSONFile(host: Tree, path: string, callback: (obj: any) => any) {
|
4
|
+
let serializedConfig = host.read(path)!.toString();
|
5
|
+
serializedConfig = serializedConfig.replace(/\/\*[\S\s]+?\*\/\r?\n/g, '');
|
6
|
+
let obj = JSON.parse(serializedConfig);
|
7
|
+
|
8
|
+
obj = callback(obj);
|
9
|
+
|
10
|
+
host.overwrite(path, `${JSON.stringify(obj, null, 2)}\n`);
|
11
|
+
|
12
|
+
return host;
|
13
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { Tree } from '@angular-devkit/schematics';
|
2
|
+
import { getWorkspace } from '@schematics/angular/utility/config';
|
3
|
+
|
4
|
+
export function getProjectName(host: Tree, project: any) {
|
5
|
+
const projectName = project;
|
6
|
+
const workspace = getWorkspace(host);
|
7
|
+
const projects = Object.keys(workspace.projects);
|
8
|
+
|
9
|
+
return projectName && projects.indexOf(projectName) > -1 ? projectName : workspace.defaultProject;
|
10
|
+
}
|
11
|
+
|
12
|
+
export function getApplicationPath(host: Tree, projectName: string) {
|
13
|
+
const sourcePath = getSourceRootPath(host, projectName);
|
14
|
+
return sourcePath ? `${sourcePath}/app/` : 'src/app/';
|
15
|
+
}
|
16
|
+
|
17
|
+
export function getSourceRootPath(host: Tree, projectName: string) {
|
18
|
+
const project = getWorkspace(host).projects[projectName];
|
19
|
+
return project.sourceRoot || project.root;
|
20
|
+
}
|
21
|
+
|
22
|
+
export function getRootPath(host: Tree, projectName: string) {
|
23
|
+
const project = getWorkspace(host).projects[projectName];
|
24
|
+
return project.root;
|
25
|
+
}
|
package/src/utility/routing.js
CHANGED
@@ -12,10 +12,10 @@ function hasComponentInRoutes(routes, name) {
|
|
12
12
|
}
|
13
13
|
exports.hasComponentInRoutes = hasComponentInRoutes;
|
14
14
|
function getRoute(name) {
|
15
|
-
return ` {
|
16
|
-
path: '${core_1.strings.dasherize(name)}',
|
17
|
-
component: ${getRouteComponentName(name)},
|
18
|
-
canActivate: [ AuthGuardService ]
|
15
|
+
return ` {
|
16
|
+
path: '${core_1.strings.dasherize(name)}',
|
17
|
+
component: ${getRouteComponentName(name)},
|
18
|
+
canActivate: [ AuthGuardService ]
|
19
19
|
}`;
|
20
20
|
}
|
21
21
|
exports.getRoute = getRoute;
|