mirror of https://github.com/abpframework/abp
Merge pull request #14460 from abpframework/auto-merge/rel-6-0/1425
Merge branch dev with rel-6.0pull/14462/head
commit
e4ac0c2b72
|
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,85 @@
|
||||
import { Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
|
||||
import { isLibrary, updateWorkspace, WorkspaceDefinition } from '../../utils';
|
||||
import { allStyles, styleMap } from './style-map';
|
||||
import { ProjectDefinition } from '@angular-devkit/core/src/workspace';
|
||||
import { JsonArray, JsonValue } from '@angular-devkit/core';
|
||||
import { ChangeThemeOptions } from './model';
|
||||
import { ThemeOptionsEnum } from './theme-options.enum';
|
||||
|
||||
export default function (_options: ChangeThemeOptions): Rule {
|
||||
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: ThemeOptionsEnum,
|
||||
) {
|
||||
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 = styleMap.get(targetThemeName);
|
||||
if (!newStyles) {
|
||||
throw new SchematicsException('The theme does not found');
|
||||
}
|
||||
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;
|
||||
};
|
||||
@ -0,0 +1,6 @@
|
||||
import { ThemeOptionsEnum } from './theme-options.enum';
|
||||
|
||||
export type ChangeThemeOptions = {
|
||||
name: ThemeOptionsEnum;
|
||||
targetProject: string;
|
||||
};
|
||||
@ -0,0 +1,37 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"$id": "SchematicsABPThemeChanger",
|
||||
"title": "ABP Theme Style Generator API Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of theme will change.",
|
||||
"type": "number",
|
||||
"$default": {
|
||||
"$source": "argv",
|
||||
"index": 0
|
||||
},
|
||||
"enum": [1, 2, 3, 4],
|
||||
"x-prompt": {
|
||||
"message": "Which theme would you like to use?",
|
||||
"type": "list",
|
||||
"items": [
|
||||
{ "value": 1, "label": "Basic" },
|
||||
{ "value": 2, "label": "Lepton" },
|
||||
{ "value": 3, "label": "LeptonXLite" },
|
||||
{ "value": 4, "label": "LeptonX" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"targetProject": {
|
||||
"description": "The name of the project will change the style.The project type must be 'application'",
|
||||
"type": "string",
|
||||
"x-prompt": "Please enter the project name",
|
||||
"$default": {
|
||||
"$source": "argv",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["name"]
|
||||
}
|
||||
@ -0,0 +1,223 @@
|
||||
import { ThemeOptionsEnum } from './theme-options.enum';
|
||||
|
||||
export type StyleDefinition =
|
||||
| {
|
||||
input: string;
|
||||
inject: boolean;
|
||||
bundleName: string;
|
||||
}
|
||||
| string;
|
||||
|
||||
export const styleMap = new Map<ThemeOptionsEnum, StyleDefinition[]>();
|
||||
|
||||
styleMap.set(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',
|
||||
},
|
||||
]);
|
||||
|
||||
styleMap.set(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',
|
||||
},
|
||||
]);
|
||||
styleMap.set(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',
|
||||
},
|
||||
]);
|
||||
styleMap.set(ThemeOptionsEnum.LeptonXLite, [
|
||||
{
|
||||
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',
|
||||
},
|
||||
]);
|
||||
// the code written by Github co-pilot. thank go-pilot. You are the best sidekick.
|
||||
export const allStyles = Array.from(styleMap.values()).reduce((acc, val) => [...acc, ...val], []);
|
||||
@ -0,0 +1,8 @@
|
||||
// this enum create by https://raw.githubusercontent.com/abpframework/abp/rel-6.0/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Theme.cs
|
||||
|
||||
export enum ThemeOptionsEnum {
|
||||
Basic = 1,
|
||||
Lepton = 2,
|
||||
LeptonXLite = 3,
|
||||
LeptonX = 4,
|
||||
}
|
||||
Loading…
Reference in new issue