Skip to content

Commit 5a77acd

Browse files
committed
Resolve problems with ng add schematics and add ng update schematics
1 parent 48df844 commit 5a77acd

File tree

4,958 files changed

+332
-934128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

4,958 files changed

+332
-934128
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "./node_modules/@angular-devkit/schematics/collection-schema.json",
3+
"schematics": {
4+
"ng-add": {
5+
"description": "Add MDB Angular Free to the application.",
6+
"factory": "./ng-add/index#ngAdd",
7+
"schema": "./ng-add/schema.json"
8+
},
9+
"ng-add-mdb-setup": {
10+
"description": "Setup MDB Angular Free.",
11+
"factory": "./ng-add/mdb-setup",
12+
"schema": "./ng-add/schema.json"
13+
}
14+
}
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "./node_modules/@angular-devkit/schematics/collection-schema.json",
3+
"schematics": {
4+
"migration-v9": {
5+
"version": "9.0.0-0",
6+
"description": "Updates MDB Angular Pro to version 9",
7+
"factory": "./ng-update/index#updateToV9"
8+
}
9+
},
10+
"ng-update": {
11+
"migrations": "./schematics/migration.json"
12+
}
13+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
2+
import { RunSchematicTask, NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
3+
import { Schema } from './schema';
4+
import { addPackageToPackageJson } from './package';
5+
6+
// Just return the tree
7+
export function ngAdd(options: Schema): Rule {
8+
return (tree: Tree, context: SchematicContext) => {
9+
const angularDependencyVersion = '^9.0.0';
10+
11+
addPackageToPackageJson(tree, '@angular/cdk', angularDependencyVersion);
12+
addPackageToPackageJson(tree, '@angular/forms', angularDependencyVersion);
13+
addPackageToPackageJson(tree, '@angular/animations', angularDependencyVersion);
14+
15+
if (options.externalDependencies) {
16+
addPackageToPackageJson(tree, 'chart.js', '^2.7.2');
17+
addPackageToPackageJson(tree, '@types/chart.js', '^2.7.40');
18+
addPackageToPackageJson(tree, '@fortawesome/fontawesome-free', '~5.6.3');
19+
addPackageToPackageJson(tree, 'hammerjs', '~2.0.8');
20+
addPackageToPackageJson(tree, 'animate.css', '~3.7.2');
21+
}
22+
23+
const installMainDependenciesTask = context.addTask(new NodePackageInstallTask());
24+
25+
context.addTask(new RunSchematicTask('ng-add-mdb-setup', options), [installMainDependenciesTask]);
26+
};
27+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import {
2+
Rule,
3+
SchematicContext,
4+
Tree,
5+
chain,
6+
} from '@angular-devkit/schematics';
7+
import { getWorkspace } from '@schematics/angular/utility/config';
8+
import {
9+
getAppModulePath,
10+
getProjectMainFile,
11+
hasNgModuleImport,
12+
addModuleImportToRootModule,
13+
getProjectFromWorkspace,
14+
getProjectIndexFiles,
15+
appendHtmlElementToHead,
16+
} from '@angular/cdk/schematics';
17+
import { Schema } from './schema';
18+
19+
export default function(options: Schema): Rule {
20+
return chain([
21+
addMdbFreeModuleImport(options),
22+
addAngularAnimationsModule(options),
23+
addStylesAndScriptsToAngularJson(options),
24+
addRobotoFontToIndexHtml(),
25+
]);
26+
}
27+
28+
function addMdbFreeModuleImport(options: Schema) {
29+
return (tree: Tree) => {
30+
const workspace = getWorkspace(tree);
31+
const project = getProjectFromWorkspace(workspace, options.project);
32+
const mdbFreeModuleName = 'MDBBootstrapModule.forRoot()';
33+
const mdbFreeModulePath = 'angular-bootstrap-md';
34+
35+
addModuleImportToRootModule(tree, mdbFreeModuleName, mdbFreeModulePath, project);
36+
37+
return tree;
38+
};
39+
}
40+
41+
42+
function addAngularAnimationsModule(options: Schema) {
43+
return (tree: Tree, context: SchematicContext) => {
44+
const workspace = getWorkspace(tree);
45+
const project = getProjectFromWorkspace(workspace, options.project);
46+
const appModulePath = getAppModulePath(tree, getProjectMainFile(project));
47+
const browserAnimationModule = 'BrowserAnimationsModule';
48+
const animationsModulePath = '@angular/platform-browser/animations';
49+
const noopAnimationModule = 'NoopAnimationsModule';
50+
51+
if (options.animations) {
52+
if (hasNgModuleImport(tree, appModulePath, noopAnimationModule)) {
53+
context.logger.error(
54+
`Could not add ${browserAnimationModule} because ${noopAnimationModule} is already added`
55+
);
56+
return;
57+
}
58+
59+
addModuleImportToRootModule(tree, browserAnimationModule, animationsModulePath, project);
60+
} else if (!hasNgModuleImport(tree, appModulePath, noopAnimationModule)) {
61+
addModuleImportToRootModule(tree, noopAnimationModule, animationsModulePath, project);
62+
}
63+
64+
return tree;
65+
};
66+
}
67+
68+
function addRobotoFontToIndexHtml() {
69+
return (tree: Tree, context: SchematicContext) => {
70+
const fontUrl = 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,600&display=swap';
71+
const workspace = getWorkspace(tree);
72+
const project = getProjectFromWorkspace(workspace);
73+
const projectIndexFiles = getProjectIndexFiles(project);
74+
const logger = context.logger;
75+
76+
if (!projectIndexFiles.length) {
77+
logger.error('Index HTML not found');
78+
logger.info('Add roboto font manually');
79+
return;
80+
}
81+
82+
projectIndexFiles.forEach((indexFile: any) => {
83+
appendHtmlElementToHead(tree, indexFile, `<link href="${fontUrl}" rel="stylesheet">`);
84+
});
85+
86+
return tree;
87+
};
88+
}
89+
90+
function addStylesAndScriptsToAngularJson(options: Schema) {
91+
return (tree: Tree, context: SchematicContext) => {
92+
const logger = context.logger;
93+
const mainStyles = [
94+
{
95+
name: 'bootstrap',
96+
path: './node_modules/angular-bootstrap-md/assets/scss/bootstrap/bootstrap.scss',
97+
},
98+
{ name: 'mdb', path: './node_modules/angular-bootstrap-md/assets/scss/mdb.scss' },
99+
];
100+
101+
const additionalStyles = [
102+
{
103+
name: 'fontawesome',
104+
path: './node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss',
105+
},
106+
{
107+
name: 'fontawesome-solid',
108+
path: './node_modules/@fortawesome/fontawesome-free/scss/solid.scss',
109+
},
110+
{
111+
name: 'fontawesome-regular',
112+
path: './node_modules/@fortawesome/fontawesome-free/scss/regular.scss',
113+
},
114+
{
115+
name: 'fontawesome-brand',
116+
path: './node_modules/@fortawesome/fontawesome-free/scss/brands.scss',
117+
},
118+
{ name: 'animate.css', path: './node_modules/animate.css/animate.css' },
119+
];
120+
121+
const allStyles = options.externalDependencies ? [...mainStyles, ...additionalStyles] : mainStyles;
122+
const additionalScripts = [
123+
{ name: 'chart.js', path: './node_modules/chart.js/dist/Chart.js' },
124+
{ name: 'hammerjs', path: './node_modules/hammerjs/hammer.min.js' },
125+
];
126+
127+
const angularJsonFile = tree.read('angular.json');
128+
129+
if (angularJsonFile) {
130+
const angularJsonFileObject = JSON.parse(angularJsonFile.toString('utf-8'));
131+
const project = options.project
132+
? options.project
133+
: Object.keys(angularJsonFileObject['projects'])[0];
134+
const projectObject = angularJsonFileObject.projects[project];
135+
const styles = projectObject.architect.build.options.styles;
136+
const scripts = projectObject.architect.build.options.scripts;
137+
138+
allStyles.forEach(style => {
139+
styles.unshift(style.path);
140+
});
141+
142+
additionalScripts.forEach(script => {
143+
scripts.push(script.path);
144+
});
145+
tree.overwrite('angular.json', JSON.stringify(angularJsonFileObject, null, 2));
146+
} else {
147+
logger.error('Failed to add scripts or styles to angular.json');
148+
}
149+
150+
return tree;
151+
};
152+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Tree } from '@angular-devkit/schematics';
2+
3+
function sortObjectByKeys(obj: any) {
4+
return Object.keys(obj)
5+
.sort()
6+
.reduce((result: any, key) => (result[key] = obj[key]) && result, {});
7+
}
8+
9+
export function addPackageToPackageJson(tree: Tree, pkg: string, version: string): Tree {
10+
if (tree.exists('package.json')) {
11+
const packageJsonFile = tree.read('package.json');
12+
const sourceText = packageJsonFile && packageJsonFile.toString('utf-8');
13+
const json = sourceText && JSON.parse(sourceText);
14+
15+
if (!json.dependencies) {
16+
json.dependencies = {};
17+
}
18+
19+
if (!json.dependencies[pkg]) {
20+
json.dependencies[pkg] = version;
21+
json.dependencies = sortObjectByKeys(json.dependencies);
22+
}
23+
24+
tree.overwrite('package.json', JSON.stringify(json, null, 2));
25+
}
26+
27+
return tree;
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"$schema": "http://json-schema.org/schema",
3+
"id": "mdb-angular-ng-add",
4+
"title": "MDB Angular ng-add schematic",
5+
"type": "object",
6+
"properties": {
7+
"project": {
8+
"type": "string",
9+
"description": "Name of the project.",
10+
"$default": {
11+
"$source": "projectName"
12+
}
13+
},
14+
"animations": {
15+
"type": "boolean",
16+
"default": true,
17+
"description": "Whether to set up Angular animations.",
18+
"x-prompt": "Set up Angular animations?"
19+
},
20+
"externalDependencies": {
21+
"type": "boolean",
22+
"default": false,
23+
"description": "Whether to set up external dependencies.",
24+
"x-prompt": "Set up external dependencies (chart.js, hammerjs, animate, font awesome)?"
25+
}
26+
},
27+
"required": []
28+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface Schema {
2+
project: string;
3+
animations: boolean;
4+
externalDependencies: boolean;
5+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
2+
import { getWorkspace } from '@schematics/angular/utility/config';
3+
import {
4+
getProjectFromWorkspace,
5+
getProjectIndexFiles,
6+
appendHtmlElementToHead,
7+
} from '@angular/cdk/schematics';
8+
9+
export function updateToV9(): Rule {
10+
return (tree: Tree, context: SchematicContext) => {
11+
12+
const fontUrl = 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,600&display=swap';
13+
const workspace = getWorkspace(tree);
14+
const project = getProjectFromWorkspace(workspace);
15+
const projectIndexFiles = getProjectIndexFiles(project);
16+
const logger = context.logger;
17+
18+
if (!projectIndexFiles.length) {
19+
logger.error('Index HTML not found');
20+
logger.info('Add roboto font manually');
21+
return;
22+
}
23+
24+
projectIndexFiles.forEach((indexFile: any) => {
25+
appendHtmlElementToHead(tree, indexFile, `<link href="${fontUrl}" rel="stylesheet">`);
26+
});
27+
28+
return tree;
29+
};
30+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"lib": [
5+
"es2018",
6+
"dom"
7+
],
8+
"declaration": true,
9+
"module": "commonjs",
10+
"moduleResolution": "node",
11+
"noEmitOnError": true,
12+
"noFallthroughCasesInSwitch": true,
13+
"noImplicitAny": true,
14+
"noImplicitThis": true,
15+
"noUnusedParameters": true,
16+
"noUnusedLocals": true,
17+
"rootDir": "schematics",
18+
"outDir": "../../dist/angular-bootstrap-md/schematics",
19+
"skipDefaultLibCheck": true,
20+
"skipLibCheck": true,
21+
"sourceMap": true,
22+
"strictNullChecks": true,
23+
"target": "es6",
24+
"types": [
25+
"jasmine",
26+
"node"
27+
]
28+
},
29+
"include": [
30+
"schematics/"
31+
],
32+
"exclude": [
33+
]
34+
}

projects/schematics/.gitignore

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)