Skip to content

Commit e3b15b8

Browse files
committed
feat(schematics): Add support for choosing styling library (l-lin#1543)
* feat(schematics): skip adding package.json deps if already exist * feat: move angular.json update code to utils * feat(schematics): Add support for choosing styling library
1 parent 0150d9f commit e3b15b8

File tree

5 files changed

+133
-33
lines changed

5 files changed

+133
-33
lines changed

schematics/src/ng-add/index.ts

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,42 @@
11
import { Rule, SchematicContext, Tree, chain } from '@angular-devkit/schematics';
2-
import { addPackageToPackageJson } from './utils';
2+
import { addAssetToAngularJson, addPackageToPackageJson } from './utils';
33
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
4+
import { IADTSchematicsOptions } from './models/schematics-options';
5+
import { ADT_SUPPORTED_STYLES, ADTStyleOptions } from './models/style-options';
46

5-
export default function (_options: any): Rule {
7+
export default function (_options: IADTSchematicsOptions): Rule {
68
return chain([
7-
addPackageJsonDependencies(),
9+
addPackageJsonDependencies(_options),
810
installPackageJsonDependencies(),
9-
updateAngularJsonFile()
11+
updateAngularJsonFile(_options)
1012
]);
1113
}
1214

13-
function addPackageJsonDependencies() {
15+
function addPackageJsonDependencies(options: IADTSchematicsOptions) {
1416
return (tree: Tree, context: SchematicContext) => {
1517
// Update package.json
18+
const styleDeps = ADT_SUPPORTED_STYLES.find(e => e.style == options.style);
19+
1620
const dependencies = [
1721
{ version: '^3.4.1', name: 'jquery', isDev: false },
1822
{ version: '^1.10.20', name: 'datatables.net', isDev: false },
19-
{ version: '^1.10.20', name: 'datatables.net-dt', isDev: false },
20-
{ version: '^11.0.0', name: 'angular-datatables', isDev: false },
2123
{ version: '^3.3.33', name: '@types/jquery', isDev: true },
2224
{ version: '^1.10.18', name: '@types/datatables.net', isDev: true }
2325
];
2426

27+
if (styleDeps) {
28+
if (styleDeps.style != ADTStyleOptions.DT)
29+
context.logger.log('warn', 'Your project needs Bootstrap CSS installed and configured for changes to take affect.');
30+
styleDeps.packageJson.forEach(e => dependencies.push(e));
31+
}
32+
2533
dependencies.forEach(dependency => {
26-
addPackageToPackageJson(tree, dependency.name, dependency.version, dependency.isDev);
27-
context.logger.log('info', `✅️ Added "${dependency.name}" into "${dependency.isDev ? 'devDependencies' : 'dependencies' }"`);
34+
const result = addPackageToPackageJson(tree, dependency.name, dependency.version, dependency.isDev);
35+
if (result) {
36+
context.logger.log('info', `✅️ Added "${dependency.name}" into "${dependency.isDev ? 'devDependencies' : 'dependencies'}"`);
37+
} else {
38+
context.logger.log('info', `ℹ️ Skipped adding "${dependency.name}" into package.json`);
39+
}
2840
});
2941
return tree;
3042
};
@@ -40,31 +52,27 @@ function installPackageJsonDependencies(): Rule {
4052
}
4153

4254

43-
function updateAngularJsonFile() {
55+
function updateAngularJsonFile(options: IADTSchematicsOptions) {
4456
return (tree: Tree, context: SchematicContext) => {
45-
try {
46-
const angularJsonFile = tree.read('angular.json');
4757

48-
if (angularJsonFile) {
49-
const angularJsonFileObject = JSON.parse(angularJsonFile.toString('utf-8'));
50-
const project = Object.keys(angularJsonFileObject['projects'])[0];
51-
const projectObject = angularJsonFileObject.projects[project];
52-
const targets = projectObject.targets ? projectObject.targets : projectObject.architect;
58+
const styleDeps = ADT_SUPPORTED_STYLES.find(e => e.style == options.style);
5359

54-
const styles = targets.build.options.styles;
55-
const scripts = targets.build.options.scripts;
60+
const assets = [
61+
{ path: 'node_modules/jquery/dist/jquery.js', target: 'scripts', fancyName: 'jQuery Core' },
62+
{ path: 'node_modules/datatables.net/js/jquery.dataTables.js', target: 'scripts', fancyName: 'DataTables.net Core JS' },
63+
];
5664

57-
styles.push('node_modules/datatables.net-dt/css/jquery.dataTables.css');
58-
scripts.push('node_modules/jquery/dist/jquery.js');
59-
scripts.push('node_modules/datatables.net/js/jquery.dataTables.js');
65+
if (styleDeps) {
66+
styleDeps.angularJson.forEach(e => assets.push(e));
67+
}
6068

61-
tree.overwrite('angular.json', JSON.stringify(angularJsonFileObject, null, 2));
62-
context.logger.log('info', `✅️ Updated angular.json`);
69+
assets.forEach(asset => {
70+
const result = addAssetToAngularJson(tree, asset.target, asset.path);
71+
if (result) {
72+
context.logger.log('info', `✅️ Added "${asset.fancyName}" into angular.json`);
6373
} else {
64-
context.logger.log('error', '🚫 Failed to locate angular.json else.');
74+
context.logger.log('info', `ℹ️ Skipped adding "${asset.fancyName}" into angular.json`);
6575
}
66-
} catch (e) {
67-
context.logger.log('error', `🚫 Failed to update angular.json foobar.`);
68-
}
76+
});
6977
};
7078
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { ADTStyleOptions } from "./style-options";
2+
3+
export interface IADTSchematicsOptions {
4+
project: string,
5+
style: ADTStyleOptions
6+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
export enum ADTStyleOptions {
2+
DT="dt",
3+
BS3="bs3",
4+
BS4="bs4",
5+
}
6+
7+
export const ADT_SUPPORTED_STYLES = [
8+
{
9+
style: ADTStyleOptions.DT,
10+
packageJson: [
11+
{ version: '^1.10.20', name: 'datatables.net-dt', isDev: false },
12+
],
13+
angularJson: [
14+
{ path: 'node_modules/datatables.net-dt/css/jquery.dataTables.css', target: 'styles', fancyName: 'DataTables.net Core CSS' },
15+
]
16+
},
17+
{
18+
style: ADTStyleOptions.BS3,
19+
packageJson: [
20+
{ version: '^1.10.20', name: 'datatables.net-bs', isDev: false },
21+
],
22+
angularJson: [
23+
{ path: 'node_modules/datatables.net-bs/css/dataTables.bootstrap.min.css', target: 'styles', fancyName: 'DataTables.net Bootstrap 3 CSS' },
24+
{ path: 'node_modules/datatables.net-bs/js/dataTables.bootstrap.min.js', target: 'scripts', fancyName: 'DataTables.net Bootstrap 3 JS' },
25+
]
26+
},
27+
{
28+
style: ADTStyleOptions.BS4,
29+
packageJson: [
30+
{ version: '^1.10.20', name: 'datatables.net-bs4', isDev: false },
31+
],
32+
angularJson: [
33+
{ path: 'node_modules/datatables.net-bs4/css/dataTables.bootstrap4.min.css', target: 'styles', fancyName: 'DataTables.net Bootstrap 4 CSS' },
34+
{ path: 'node_modules/datatables.net-bs4/js/dataTables.bootstrap4.min.js', target: 'scripts', fancyName: 'DataTables.net Bootstrap 4 JS' },
35+
]
36+
},
37+
]

schematics/src/ng-add/schema.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@
1111
"$default": {
1212
"$source": "projectName"
1313
}
14+
},
15+
"style": {
16+
"description": "The styling library to use for Datatables.",
17+
"type": "string",
18+
"default": "dt",
19+
"enum": ["dt", "bs3", "bs4"],
20+
"x-prompt": {
21+
"message": "Which styling library would you like to use for DataTables?",
22+
"type": "list",
23+
"items": [
24+
{ "value": "dt", "label": "DataTables (Default)" },
25+
{
26+
"value": "bs3",
27+
"label": "Bootstrap 3"
28+
},
29+
{
30+
"value": "bs4",
31+
"label": "Bootstrap 4"
32+
}
33+
]
34+
}
1435
}
1536
}
16-
}
37+
}

schematics/src/ng-add/utils/index.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function installPackageJsonDependencies(): Rule {
2727
}
2828

2929
export function addStyleToTarget(project: WorkspaceProject, targetName: string, host: Tree,
30-
assetPath: string, workspace: WorkspaceSchema) {
30+
assetPath: string, workspace: WorkspaceSchema) {
3131

3232
const targetOptions = getProjectTargetOptions(project, targetName);
3333

@@ -99,7 +99,7 @@ function sortObjectByKeys(obj: { [key: string]: string }) {
9999
* Note: This function accepts an additional parameter `isDevDependency` so we
100100
* can place a given dependency in the correct dependencies array inside package.json
101101
*/
102-
export function addPackageToPackageJson(host: Tree, pkg: string, version: string, isDevDependency = false): Tree {
102+
export function addPackageToPackageJson(host: Tree, pkg: string, version: string, isDevDependency = false): boolean {
103103

104104
if (host.exists('package.json')) {
105105
/* tslint:disable-next-line: no-non-null-assertion */
@@ -114,20 +114,48 @@ export function addPackageToPackageJson(host: Tree, pkg: string, version: string
114114
json.dependencies = {};
115115
}
116116

117+
// update UI that `pkg` wasn't re-added to package.json
118+
if (json.dependencies[pkg] || json.devDependencies[pkg]) return false;
119+
117120
if (!json.dependencies[pkg] && !isDevDependency) {
118121
json.dependencies[pkg] = version;
119122
json.dependencies = sortObjectByKeys(json.dependencies);
120123
}
121124

122-
if(!json.devDependencies[pkg] && isDevDependency) {
125+
if (!json.devDependencies[pkg] && isDevDependency) {
123126
json.devDependencies[pkg] = version;
124127
json.devDependencies = sortObjectByKeys(json.devDependencies);
125128
}
126129

127130
host.overwrite('package.json', JSON.stringify(json, null, 2));
131+
return true;
128132
}
129133

130-
return host;
134+
return false;
135+
}
136+
137+
export function addAssetToAngularJson(host: Tree, assetType: string, assetPath: string): boolean {
138+
/* tslint:disable-next-line: no-non-null-assertion */
139+
const sourceText = host.read('angular.json')!.toString('utf-8');
140+
const json = JSON.parse(sourceText);
141+
142+
if (!json) return false;
143+
144+
const projectName = Object.keys(json['projects'])[0];
145+
const projectObject = json.projects[projectName];
146+
const targets = projectObject.targets || projectObject.architect;
147+
148+
const targetLocation: string[] = targets.build.options[assetType];
149+
150+
// update UI that `assetPath` wasn't re-added to angular.json
151+
if (targetLocation.indexOf(assetPath) != -1) return false;
152+
153+
targetLocation.push(assetPath);
154+
155+
host.overwrite('angular.json', JSON.stringify(json, null, 2));
156+
157+
return true;
158+
131159
}
132160

133161
export function removePackageJsonDependency(tree: Tree, dependencyName: string) {

0 commit comments

Comments
 (0)