diff --git a/docs/en/Themes/LeptonXLite/Angular.md b/docs/en/Themes/LeptonXLite/Angular.md index 4079281f99..950cd20c8b 100644 --- a/docs/en/Themes/LeptonXLite/Angular.md +++ b/docs/en/Themes/LeptonXLite/Angular.md @@ -1,7 +1,8 @@ # LeptonX Lite Angular UI + LeptonX Lite has implementation for the ABP Framework Angular Client. It's a simplified variation of the [LeptonX Theme](https://x.leptontheme.com/). -> If you are looking for a professional, enterprise ready theme, you can check the [LeptonX Theme](https://x.leptontheme.com/), which is a part of [ABP Commercial](https://commercial.abp.io/). +> If you are looking for a professional, enterprise ready theme, you can check the [LeptonX Theme](https://x.leptontheme.com/), which is a part of [ABP Commercial](https://commercial.abp.io/). > See the [Theming document](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Theming) to learn about themes. @@ -11,28 +12,27 @@ This theme is **already installed** when you create a new solution using the sta To add `LeptonX-lite` into your project, -* Install `@abp/ng.theme.lepton-x` +- Install `@abp/ng.theme.lepton-x` `yarn add @abp/ng.theme.lepton-x@preview` -* Install `bootstrap-icons` +- Install `bootstrap-icons` `yarn add bootstrap-icons` +- Then, we need to edit the styles array in `angular.json` to replace the existing style with the new one. -* Then, we need to edit the styles array in `angular.json` to replace the existing style with the new one. - -Add the following style +Add the following style ```json "node_modules/bootstrap-icons/font/bootstrap-icons.css", ``` -* Finally, remove `ThemeBasicModule` from `app.module.ts`, and import the related modules in `app.module.ts` +- Finally, remove `ThemeBasicModule` from `app.module.ts`, and import the related modules in `app.module.ts` ```js -import { ThemeLeptonXModule } from '@abp/ng.theme.lepton-x'; -import { SideMenuLayoutModule } from '@abp/ng.theme.lepton-x/layouts'; +import { ThemeLeptonXModule } from "@abp/ng.theme.lepton-x"; +import { SideMenuLayoutModule } from "@abp/ng.theme.lepton-x/layouts"; @NgModule({ imports: [ @@ -51,7 +51,7 @@ export class AppModule {} Note: If you employ [Resource Owner Password Flow](https://docs.abp.io/en/abp/latest/UI/Angular/Authorization#resource-owner-password-flow) for authorization, you should import the following module as well: ```js -import { AccountLayoutModule } from '@abp/ng.theme.lepton-x/account'; +import { AccountLayoutModule } from "@abp/ng.theme.lepton-x/account"; @NgModule({ // ... @@ -69,15 +69,15 @@ To change the logos and brand color of `LeptonX`, simply add the following CSS t ```css :root { - --lpx-logo: url('/assets/images/logo.png'); - --lpx-logo-icon: url('/assets/images/logo-icon.png'); + --lpx-logo: url("/assets/images/logo.png"); + --lpx-logo-icon: url("/assets/images/logo-icon.png"); --lpx-brand: #edae53; } ``` - `--lpx-logo` is used to place the logo in the menu. -- `--lpx-logo-icon` is a square icon used when the menu is collapsed. -- `--lpx-brand` is a color used throughout the application, especially on active elements. +- `--lpx-logo-icon` is a square icon used when the menu is collapsed. +- `--lpx-brand` is a color used throughout the application, especially on active elements. ### Server Side @@ -85,22 +85,18 @@ In order to migrate to LeptonX on your server side projects (Host and/or AuthSer ## Customization - ### Layouts -The Angular version of LeptonX Lite provides **layout components** for your **user interface** on [ABP Framework Theming](https://docs.abp.io/en/abp/latest/UI/Angular/Theming). You can use layouts to **organize your user interface**. You can replace the **layout components** and some parts of the **layout components** with the [ABP replaceable component system](https://docs.abp.io/en/abp/latest/UI/Angular/Component-Replacement). - +The Angular version of LeptonX Lite provides **layout components** for your **user interface** on [ABP Framework Theming](https://docs.abp.io/en/abp/latest/UI/Angular/Theming). You can use the layouts to **organize your user interface**. You can replace the **layout components** and some parts of the **layout components** with the [ABP replaceable component system](https://docs.abp.io/en/abp/latest/UI/Angular/Component-Replacement). The main responsibility of a theme is to **provide** the layouts. There are **three pre-defined layouts that must be implemented by all the themes:** -* **ApplicationLayoutComponent:** The **default** layout which is used by the **main** application pages. - -* **AccountLayoutComponent:** Mostly used by the **account module** for **login**, **register**, **forgot password**... pages. - -* **EmptyLayoutComponent:** The **Minimal** layout that **has no layout components** at all. +- **ApplicationLayoutComponent:** The **default** layout which is used by the **main** application pages. +- **AccountLayoutComponent:** Mostly used by the **account module** for **login**, **register**, **forgot password**... pages. +- **EmptyLayoutComponent:** The **Minimal** layout that **has no layout components** at all. + +The **Layout components** and all the replacable components are predefined in `eThemeLeptonXComponents` as enum. - The **Layout components** and all the replacable components are predefined in `eThemeLeptonXComponents` as enum. - ### How to replace a component ```js @@ -122,8 +118,8 @@ export class AppComponent { } } ``` -See the [Component Replacement](https://docs.abp.io/en/abp/latest/UI/Angular/Component-Replacement) documentation for more information on how to replace components. +See the [Component Replacement](https://docs.abp.io/en/abp/latest/UI/Angular/Component-Replacement) documentation for more information on how to replace components. ### Brand Component @@ -131,16 +127,14 @@ The **brand component** is a simple component that can be used to display your b ```js ///... - this.replaceableComponents.add({ - component: YourNewLogoComponent, - key: eThemeLeptonXComponents.Logo, - }); +this.replaceableComponents.add({ + component: YourNewLogoComponent, + key: eThemeLeptonXComponents.Logo, +}); ///... ``` -![Brand component](../../images/leptonxlite-brand-component.png) - - +![Brand component](../../images/leptonxlite-brand-component.png) ## Breadcrumb Component @@ -148,14 +142,14 @@ On websites that have a lot of pages, **breadcrumb navigation** can greatly **en ```js ///... - this.replaceableComponents.add({ - component: YourNewSidebarComponent, - key: eThemeLeptonXComponents.Breadcrumb, - }); +this.replaceableComponents.add({ + component: YourNewSidebarComponent, + key: eThemeLeptonXComponents.Breadcrumb, +}); ///... ``` -![Breadcrumb component](../../images/leptonxlite-breadcrumb-component.png) +![Breadcrumb component](../../images/leptonxlite-breadcrumb-component.png) ## Sidebar Menu Component @@ -163,54 +157,61 @@ Sidebar menus have been used as a **directory for Related Pages** to a **Service ```js ///... - this.replaceableComponents.add({ - component: YourNewSidebarComponent, - key: eThemeLeptonXComponents.Sidebar, - }); +this.replaceableComponents.add({ + component: YourNewSidebarComponent, + key: eThemeLeptonXComponents.Sidebar, +}); ///... ``` -![Sidebar menu component](../../images/leptonxlite-sidebar-menu-component.png) + +![Sidebar menu component](../../images/leptonxlite-sidebar-menu-component.png) ## Page Alerts Component Provides contextual **feedback messages** for typical user actions with a handful of **available** and **flexible** **alert messages**. Alerts are available for any length of text, as well as an **optional dismiss button**. -![Page alerts component](../../images/leptonxlite-page-alerts-component.png) +![Page alerts component](../../images/leptonxlite-page-alerts-component.png) + ```js ///... - this.replaceableComponents.add({ - component: YourNewPageAlertContainerComponent, - key: eThemeLeptonXComponents.PageAlertContainer, - }); +this.replaceableComponents.add({ + component: YourNewPageAlertContainerComponent, + key: eThemeLeptonXComponents.PageAlertContainer, +}); ///... ``` + ## Toolbar Component + ![Breadcrumb component](../../images/leptonxlite-toolbar-component.png) Toolbar items are used to add **extra functionality to the toolbar**. The toolbar is a **horizontal bar** that **contains** a group of **toolbar items**. + ```js ///... - this.replaceableComponents.add({ - component: YourNewNavItemsComponent, - key: eThemeLeptonXComponents.NavItems, - }); +this.replaceableComponents.add({ + component: YourNewNavItemsComponent, + key: eThemeLeptonXComponents.NavItems, +}); ///... ``` ## Toolbar Items + There are two parts to the toolbar. The first is Language-Switch. The second is the User-Profile element. You can swap out each of these parts individually. ## Language Switch Component -Think about a **multi-lingual** website and the first thing that could **hit your mind** is **the language switch component**. A **navigation bar** is a **great place** to **embed a language switch**. By embedding the language switch in the navigation bar of your website, you would **make it simpler** for users to **find it** and **easily** switch the **language** **without trying to locate it across the website.** +Think about a **multi-lingual** website and the first thing that could **hit your mind** is **the language switch component**. A **navigation bar** is a **great place** to **embed a language switch**. By embedding the language switch in the navigation bar of your website, you would **make it simpler** for users to **find it** and **easily** switch the **language** **without trying to locate it across the website.** + +![Language switch component](../../images/leptonxlite-language-switch-component.png) -![Language switch component](../../images/leptonxlite-language-switch-component.png) ```js ///... - this.replaceableComponents.add({ - component: YourNewLanguagesComponent, - key: eThemeLeptonXComponents.Languages, - }); +this.replaceableComponents.add({ + component: YourNewLanguagesComponent, + key: eThemeLeptonXComponents.Languages, +}); ///... ``` @@ -219,33 +220,84 @@ Think about a **multi-lingual** website and the first thing that could **hit you The **User Menu** is the **menu** that **drops down** when you **click your name** or **profile picture** in the **upper right corner** of your page (**in the toolbar**). It drops down options such as **Settings**, **Logout**, etc. ![User menu component](../../images/leptonxlite-user-menu-component.png) + ```js ///... - this.replaceableComponents.add({ - component: YourNewCurrentUserComponent, - key: eThemeLeptonXComponents.CurrentUser, - }); +this.replaceableComponents.add({ + component: YourNewCurrentUserComponent, + key: eThemeLeptonXComponents.CurrentUser, +}); ///... ``` + Note: The language selection component in the Volo app is not replaceable. It is part of the settings menu. ## Mobile Navbar Component + The **mobile navbar component** is used to display the **navbar menu on mobile devices**. The mobile navbar component is a **dropdown menu** that contains language selection and user menu. -![Mobile user menu component](../../images/leptonxlite-mobile-user-menu-component.png) +![Mobile user menu component](../../images/leptonxlite-mobile-user-menu-component.png) + ```js ///... - this.replaceableComponents.add({ - component: YourNewMobileNavbarComponent, - key: eThemeLeptonXComponents.MobileNavbar, - }); +this.replaceableComponents.add({ + component: YourNewMobileNavbarComponent, + key: eThemeLeptonXComponents.MobileNavbar, +}); ///... ``` + ## Mobile Navbar Items. -There are two parts of the mobile navbar. The mobile navbar has Language-Switch and User-Profile. You can swap out each of these parts individually. + +There are two parts of the mobile navbar. The mobile navbar has Language-Switch and User-Profile. You can swap out each of these parts individually. The Mobile language-Selection component key is `eThemeLeptonXComponents.MobileLanguageSelection`. The Mobile User-Profile component key is `eThemeLeptonXComponents.MobileUserProfile`. +## Footer Component + +![Angular Footer Component](../../images/angular-footer.png) + +The Footer is the section of content at the very bottom of the site. This section of the content can be modified. +Inject **FooterLinksService** and use the **setFooterInfo** method of **FooterLinksService** +to assign path or link and description. +**descUrl** and **footerLinks** are nullable. Constant **footerLinks** are on the right side of footer. + + +```js +///... + +const footerLinks = [ + { + link: "/components/bootstrap/badge", + text: "Manage Your Profile", + }, + { + link: "/components/bootstrap/border", + text: "My Security Logs", + }, +]; + +const footerInfo: FooterNav = { + desc: "Home", + descUrl: "/components/home", + footerLinks: footerLinks, +}; + +this.footerLinksService.setFooterInfo(footerInfo); + +///... +``` +If you want to change the footer component, the key is `eThemeLeptonXComponents.Footer` + +```js +///... +this.replaceableComponents.add({ + component: YourNewFooterComponent, + key: eThemeLeptonXComponents.Footer, +}); +///... +``` + diff --git a/docs/en/images/angular-footer.png b/docs/en/images/angular-footer.png new file mode 100644 index 0000000000..16be8194ab Binary files /dev/null and b/docs/en/images/angular-footer.png differ diff --git a/npm/ng-packs/packages/schematics/src/collection.json b/npm/ng-packs/packages/schematics/src/collection.json index 8441a786b0..16f148d78a 100644 --- a/npm/ng-packs/packages/schematics/src/collection.json +++ b/npm/ng-packs/packages/schematics/src/collection.json @@ -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" + } } } diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts new file mode 100644 index 0000000000..22f32be353 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts @@ -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 { + 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; +}; diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/model.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/model.ts new file mode 100644 index 0000000000..ca553c50c7 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/model.ts @@ -0,0 +1,6 @@ +import { ThemeOptionsEnum } from './theme-options.enum'; + +export type ChangeThemeOptions = { + name: ThemeOptionsEnum; + targetProject: string; +}; diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/schema.json b/npm/ng-packs/packages/schematics/src/commands/change-theme/schema.json new file mode 100644 index 0000000000..6eb6bc71a5 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/schema.json @@ -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"] +} diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts new file mode 100644 index 0000000000..aa5f17b21a --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts @@ -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(); + +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], []); diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/theme-options.enum.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/theme-options.enum.ts new file mode 100644 index 0000000000..6e2f863674 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/theme-options.enum.ts @@ -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, +} diff --git a/npm/ng-packs/scripts/build-schematics.ts b/npm/ng-packs/scripts/build-schematics.ts index 8884ca9571..6690b272b3 100644 --- a/npm/ng-packs/scripts/build-schematics.ts +++ b/npm/ng-packs/scripts/build-schematics.ts @@ -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',