Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Change-Theme schematic #14445

Merged
merged 6 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions npm/ng-packs/packages/schematics/src/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
"description": "ABP Create Library Schematics",
"factory": "./commands/create-lib",
"schema": "./commands/create-lib/schema.json"
},
"change-theme": {
"description": "ABP Change Styles of Theme Schematics",
"factory": "./commands/change-theme",
"schema": "./commands/change-theme/schema.json"

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
import { isLibrary, updateWorkspace, WorkspaceDefinition } from '../../utils';
import { allStyles, StyleDefinition, styleMap } from './style-map';
import { ProjectDefinition } from '@angular-devkit/core/src/workspace';
import { JsonArray, JsonValue } from '@angular-devkit/core';
import { ChangeThemeOptions } from './model';

export default function (_options: ChangeThemeOptions): Rule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return async (_: Tree, __: SchematicContext) => {
const targetThemeName = _options.name;
const selectedProject = _options.targetProject;
if (!targetThemeName) {
throw new SchematicsException('The theme name does not selected');
}

return updateWorkspace(storedWorkspace => {
updateProjectStyle(selectedProject, storedWorkspace, targetThemeName);
});
};
}

function updateProjectStyle(
projectName: string,
workspace: WorkspaceDefinition,
targetThemeName: string,
) {
const project = workspace.projects.get(projectName);

if (!project) {
throw new SchematicsException('The target project does not selected');
}

const isProjectLibrary = isLibrary(project);
if (isProjectLibrary) {
throw new SchematicsException('The library project does not supported');
}

const targetOption = getProjectTargetOptions(project, 'build');
const styles = targetOption.styles as (string | { input: string })[];

const sanitizedStyles = removeThemeBasedStyles(styles);

const newStyles = getStylesOfSelectedTheme(targetThemeName);
targetOption.styles = [...newStyles, ...sanitizedStyles] as JsonArray;
}

export function getProjectTargetOptions(
project: ProjectDefinition,
buildTarget: string,
): Record<string, JsonValue | undefined> {
const options = project.targets?.get(buildTarget)?.options;

if (!options) {
throw new SchematicsException(
`Cannot determine project target configuration for: ${buildTarget}.`,
);
}

return options;
}

export function removeThemeBasedStyles(styles: (string | object)[]) {
return styles.filter(s => !allStyles.some(x => styleCompareFn(s, x)));
}

export const styleCompareFn = (item1: string | object, item2: string | object) => {
const type1 = typeof item1;
const type2 = typeof item1;

if (type1 !== type2) {
return false;
}

if (type1 === 'string') {
return item1 === item2;
}
const o1 = item1 as { bundleName?: string };
const o2 = item2 as { bundleName?: string };

return o1.bundleName && o2.bundleName && o1.bundleName == o2.bundleName;
};

export function getStylesOfSelectedTheme(theme: string): StyleDefinition[] {
return styleMap[theme];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type ChangeThemeOptions = {
name: string;
targetProject: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"$schema": "http://json-schema.org/schema",
"$id": "SchematicsABPModuleTemplateCreator",
mahmut-gundogdu marked this conversation as resolved.
Show resolved Hide resolved
"title": "ABP Theme Style Generator API Schema",
"type": "object",
"properties": {
"name": {
"description": "The file extension or preprocessor to use for style files.",
mahmut-gundogdu marked this conversation as resolved.
Show resolved Hide resolved
"type": "string",
"default": "basic",
"enum": ["basic", "lepton", "leptonx-lite", "leptonx"],
"x-prompt": {
"message": "Which theme would you like to use?",
"type": "list",
"items": [
{ "value": "basic", "label": "basic" },
{ "value": "lepton", "label": "lepton" },
{ "value": "leptonx-lite", "label": "leptonx-lite" },
{ "value": "leptonx", "label": "leptonx" }
]
}
},
"targetProject": {
"description": "The name of the project will change the style",
mahmut-gundogdu marked this conversation as resolved.
Show resolved Hide resolved
"type": "string",
"x-prompt": "Please enter the project name"
}
},
"required": ["name"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import { ThemeOptionsEnum } from './theme-options.enum';

export type StyleDefinition =
| {
input: string;
inject: boolean;
bundleName: string;
}
| string;

export type StyleMapType = {
[key: string]: StyleDefinition[];
};

export const styleMap: StyleMapType = {
[ThemeOptionsEnum.basic]: [
{
input: 'node_modules/bootstrap/dist/css/bootstrap.rtl.min.css',
inject: false,
bundleName: 'bootstrap-rtl.min',
},
{
input: 'node_modules/bootstrap/dist/css/bootstrap.min.css',
inject: true,
bundleName: 'bootstrap-ltr.min',
},
],
[ThemeOptionsEnum['leptonx-lite']]: [
{
input: 'node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.css',
inject: false,
bundleName: 'bootstrap-dim',
},
{
input: 'node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.css',
inject: false,
bundleName: 'ng-bundle',
},
{
input: 'node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.css',
inject: false,
bundleName: 'layout-bundle',
},
{
input: 'node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.css',
inject: false,
bundleName: 'abp-bundle',
},
{
input: 'node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.rtl.css',
inject: false,
bundleName: 'bootstrap-dim.rtl',
},
{
input: 'node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.rtl.css',
inject: false,
bundleName: 'ng-bundle.rtl',
},
{
input: 'node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.rtl.css',
inject: false,
bundleName: 'layout-bundle.rtl',
},
{
input: 'node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.rtl.css',
inject: false,
bundleName: 'abp-bundle.rtl',
},
],
[ThemeOptionsEnum.lepton]: [
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton1.min.css',
inject: false,
bundleName: 'lepton1',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton2.min.css',
inject: false,
bundleName: 'lepton2',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton3.min.css',
inject: false,
bundleName: 'lepton3',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton4.min.css',
inject: false,
bundleName: 'lepton4',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton5.min.css',
inject: false,
bundleName: 'lepton5',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton6.min.css',
inject: false,
bundleName: 'lepton6',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton1.rtl.min.css',
inject: false,
bundleName: 'lepton1.rtl',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton2.rtl.min.css',
inject: false,
bundleName: 'lepton2.rtl',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton3.rtl.min.css',
inject: false,
bundleName: 'lepton3.rtl',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton4.rtl.min.css',
inject: false,
bundleName: 'lepton4.rtl',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton5.rtl.min.css',
inject: false,
bundleName: 'lepton5.rtl',
},
{
input: 'node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton6.rtl.min.css',
inject: false,
bundleName: 'lepton6.rtl',
},
],
[ThemeOptionsEnum.leptonx]: [
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/dark.css',
inject: false,
bundleName: 'dark',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/light.css',
inject: false,
bundleName: 'light',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/dim.css',
inject: false,
bundleName: 'dim',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dim.css',
inject: false,
bundleName: 'bootstrap-dim',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dark.css',
inject: false,
bundleName: 'bootstrap-dark',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-light.css',
inject: false,
bundleName: 'bootstrap-light',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/ng-bundle.css',
inject: false,
bundleName: 'ng-bundle',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/side-menu/layout-bundle.css',
inject: false,
bundleName: 'layout-bundle',
},
{
input: 'node_modules/@volosoft/abp.ng.theme.lepton-x/assets/css/abp-bundle.css',
inject: false,
bundleName: 'abp-bundle',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/dark.rtl.css',
inject: false,
bundleName: 'dark.rtl',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/light.rtl.css',
inject: false,
bundleName: 'light.rtl',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/dim.rtl.css',
inject: false,
bundleName: 'dim.rtl',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dim.rtl.css',
inject: false,
bundleName: 'bootstrap-dim.rtl',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dark.rtl.css',
inject: false,
bundleName: 'bootstrap-dark.rtl',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-light.rtl.css',
inject: false,
bundleName: 'bootstrap-light.rtl',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/ng-bundle.rtl.css',
inject: false,
bundleName: 'ng-bundle.rtl',
},
{
input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/side-menu/layout-bundle.rtl.css',
inject: false,
bundleName: 'layout-bundle.rtl',
},
{
input: 'node_modules/@volosoft/abp.ng.theme.lepton-x/assets/css/abp-bundle.rtl.css',
inject: false,
bundleName: 'abp-bundle.rtl',
},
],
};

export const allStyles = Object.values(styleMap).reduce((acc, val) => [...acc, ...val], []);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const ThemeOptionsEnum = Object.freeze({
basic: 'basic',
lepton: 'lepton',
'leptonx-lite': 'leptonx-lite',
leptonx: 'leptonx',
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"isSecondaryEntrypoint": {
"description": "Is secondary entrypoint",
"type": "boolean",
"type": "boole∂an",
mahmut-gundogdu marked this conversation as resolved.
Show resolved Hide resolved
"$default": false,
"x-prompt": "Is secondary entrypoint?"
},
Expand Down
1 change: 1 addition & 0 deletions npm/ng-packs/scripts/build-schematics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class FileCopy {
const PACKAGE_TO_BUILD = 'schematics';
const FILES_TO_COPY_AFTER_BUILD: (FileCopy | string)[] = [
{ src: 'src/commands/create-lib/schema.json', dest: 'commands/create-lib/schema.json' },
{ src: 'src/commands/change-theme/schema.json', dest: 'commands/change-theme/schema.json' },
{ src: 'src/commands/create-lib/files-package', dest: 'commands/create-lib/files-package' },
{
src: 'src/commands/create-lib/files-secondary-entrypoint',
Expand Down