From d79e7bb7f6bb37ea698adefa7caa2d9f389b3876 Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Thu, 15 May 2025 17:33:18 +0400 Subject: [PATCH 1/5] fix(routing): Add logic to add missing import statements to the routing file --- .../src/add-layout/index.ts | 43 +++++++++++++++---- .../src/utility/routing.ts | 4 +- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/devextreme-schematics/src/add-layout/index.ts b/packages/devextreme-schematics/src/add-layout/index.ts index 56eb1e558..79fab1612 100644 --- a/packages/devextreme-schematics/src/add-layout/index.ts +++ b/packages/devextreme-schematics/src/add-layout/index.ts @@ -67,6 +67,25 @@ import { Change } from '@schematics/angular/utility/change'; import { PatchNodePackageInstallTask } from '../utility/patch'; +const routes = [ + { + name: 'LoginFormComponent', + path: 'login-form' + }, + { + name: 'ResetPasswordFormComponent', + path: 'reset-password' + }, + { + name: 'CreateAccountFormComponent', + path: 'create-account' + }, + { + name: 'ChangePasswordFormComponent', + path: 'change-password' + } +]; + const projectFilesSource = './files/src'; const workspaceFilesSource = './files'; @@ -291,15 +310,23 @@ function updateDevextremeConfig(sourcePath: string = '') { const modifyRouting = (host: Tree, routingFilePath: string) => { // TODO: Try to use the isolated host to generate the result string let source = getSourceFile(host, routingFilePath)!; - const importChange = insertImport(source, routingFilePath, 'LoginFormComponent', './shared/components'); - applyChanges(host, [ importChange ], routingFilePath); - - source = getSourceFile(host, routingFilePath)!; - const routes = findRoutesInSource(source)!; - if (!hasComponentInRoutes(routes, 'login-form')) { - const loginFormRoute = getRoute('login-form'); - insertItemToArray(host, routingFilePath, routes, loginFormRoute); + const importChanges = []; + importChanges.push(insertImport(source, routingFilePath, 'AuthGuardService', './shared/services')); + + for (const route of routes) { + importChanges.push(insertImport(source, routingFilePath, route.name, './shared/components')); } + + applyChanges(host, importChanges, routingFilePath); + for (const route of routes) { + source = getSourceFile(host, routingFilePath)!; + const routeInSource = findRoutesInSource(source)!; + if (!hasComponentInRoutes(routeInSource, route.path)) { + const routeToAdd = getRoute(route.path, route.name); + insertItemToArray(host, routingFilePath, routeInSource, routeToAdd); + } + } + }; export default function(options: any): Rule { diff --git a/packages/devextreme-schematics/src/utility/routing.ts b/packages/devextreme-schematics/src/utility/routing.ts index 3e8542c43..f8052f809 100644 --- a/packages/devextreme-schematics/src/utility/routing.ts +++ b/packages/devextreme-schematics/src/utility/routing.ts @@ -20,10 +20,10 @@ export function hasComponentInRoutes(routes: Node, name: string) { return routesText.indexOf(componentName) !== -1; } -export function getRoute(name: string) { +export function getRoute(name: string, componentName?: string) { return ` { path: '${strings.dasherize(name)}', - component: ${getRouteComponentName(name)}, + component: ${componentName || getRouteComponentName(name)}, canActivate: [ AuthGuardService ] }`; } From ab528dc58b5f111115fc6a8f3873cf0c0dd696d9 Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Mon, 19 May 2025 16:19:24 +0400 Subject: [PATCH 2/5] fix(tests): Add tests to ensure correct imports in toutes file --- .../src/add-layout/index_spec.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/devextreme-schematics/src/add-layout/index_spec.ts b/packages/devextreme-schematics/src/add-layout/index_spec.ts index fcb8ad350..6d8ce715a 100644 --- a/packages/devextreme-schematics/src/add-layout/index_spec.ts +++ b/packages/devextreme-schematics/src/add-layout/index_spec.ts @@ -241,10 +241,27 @@ describe('layout', () => { expect(tree.files).toContain('/src/app/app.routes.ts'); const routesContent = tree.readContent('/src/app/app.routes.ts'); + + expect(routesContent) + .toContain(`import { AuthGuardService } from './shared/services';`); + expect(routesContent) + .toContain(`import { LoginFormComponent } from './shared/components';`); + expect(routesContent) + .toContain(`import { ResetPasswordFormComponent } from './shared/components';`); + expect(routesContent) + .toContain(`import { CreateAccountFormComponent } from './shared/components';`); + expect(routesContent) + .toContain(`import { ChangePasswordFormComponent } from './shared/components';`); expect(routesContent) .toContain(`{\n path: 'login-form',\n component: LoginFormComponent,\n canActivate: [ AuthGuardService ]\n },`); - }); + expect(routesContent) + .toContain(`{\n path: 'reset-password',\n component: ResetPasswordFormComponent,\n canActivate: [ AuthGuardService ]\n },`); + expect(routesContent) + .toContain(`{\n path: 'create-account',\n component: CreateAccountFormComponent,\n canActivate: [ AuthGuardService ]\n },`); + expect(routesContent) + .toContain(`{\n path: 'change-password',\n component: ChangePasswordFormComponent,\n canActivate: [ AuthGuardService ]\n },`); + }); it('should use selected layout', async () => { const runner = new SchematicTestRunner('schematics', collectionPath); From 38692c8b0b8fbf79ab60a4cf085d05a8d11f2fbf Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Wed, 21 May 2025 11:36:10 +0400 Subject: [PATCH 3/5] fix(routing): Fix dasherize logic in getRooute and fix tests --- .../src/add-layout/index.ts | 2 +- .../src/add-layout/index_spec.ts | 29 +++++++++---------- .../src/utility/routing.ts | 2 +- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/devextreme-schematics/src/add-layout/index.ts b/packages/devextreme-schematics/src/add-layout/index.ts index 79fab1612..01f0683b5 100644 --- a/packages/devextreme-schematics/src/add-layout/index.ts +++ b/packages/devextreme-schematics/src/add-layout/index.ts @@ -82,7 +82,7 @@ const routes = [ }, { name: 'ChangePasswordFormComponent', - path: 'change-password' + path: 'change-password/:recoveryCode' } ]; diff --git a/packages/devextreme-schematics/src/add-layout/index_spec.ts b/packages/devextreme-schematics/src/add-layout/index_spec.ts index 6d8ce715a..d22f07c93 100644 --- a/packages/devextreme-schematics/src/add-layout/index_spec.ts +++ b/packages/devextreme-schematics/src/add-layout/index_spec.ts @@ -241,28 +241,27 @@ describe('layout', () => { expect(tree.files).toContain('/src/app/app.routes.ts'); const routesContent = tree.readContent('/src/app/app.routes.ts'); - + expect(routesContent) .toContain(`import { AuthGuardService } from './shared/services';`); - expect(routesContent) - .toContain(`import { LoginFormComponent } from './shared/components';`); - expect(routesContent) - .toContain(`import { ResetPasswordFormComponent } from './shared/components';`); - expect(routesContent) - .toContain(`import { CreateAccountFormComponent } from './shared/components';`); - expect(routesContent) - .toContain(`import { ChangePasswordFormComponent } from './shared/components';`); + const loginFormComponentMatch = routesContent.match(/\bLoginFormComponent\b/g); + const resetPasswordFormComponentMatch = routesContent.match(/\bResetPasswordFormComponent\b/g); + const createAccountFormComponentMatch = routesContent.match(/\bCreateAccountFormComponent\b/g); + const changePasswordFormComponentMatch = routesContent.match(/\bChangePasswordFormComponent\b/g); + expect(loginFormComponentMatch?.length).toBe(2); + expect(resetPasswordFormComponentMatch?.length).toBe(2); + expect(createAccountFormComponentMatch?.length).toBe(2); + expect(changePasswordFormComponentMatch?.length).toBe(2); expect(routesContent) - .toContain(`{\n path: 'login-form',\n component: LoginFormComponent,\n canActivate: [ AuthGuardService ]\n },`); + .toContain(`path: 'login-form'`); expect(routesContent) - .toContain(`{\n path: 'reset-password',\n component: ResetPasswordFormComponent,\n canActivate: [ AuthGuardService ]\n },`); + .toContain(`path: 'reset-password'`); expect(routesContent) - .toContain(`{\n path: 'create-account',\n component: CreateAccountFormComponent,\n canActivate: [ AuthGuardService ]\n },`); + .toContain(`path: 'create-account'`); expect(routesContent) - .toContain(`{\n path: 'change-password',\n component: ChangePasswordFormComponent,\n canActivate: [ AuthGuardService ]\n },`); - }); - + .toContain(`path: 'change-password/:recoveryCode'`); + }); it('should use selected layout', async () => { const runner = new SchematicTestRunner('schematics', collectionPath); options.layout = 'side-nav-inner-toolbar'; diff --git a/packages/devextreme-schematics/src/utility/routing.ts b/packages/devextreme-schematics/src/utility/routing.ts index f8052f809..b93d3dd86 100644 --- a/packages/devextreme-schematics/src/utility/routing.ts +++ b/packages/devextreme-schematics/src/utility/routing.ts @@ -22,7 +22,7 @@ export function hasComponentInRoutes(routes: Node, name: string) { export function getRoute(name: string, componentName?: string) { return ` { - path: '${strings.dasherize(name)}', + path: '${componentName ? name : strings.dasherize(name)}', component: ${componentName || getRouteComponentName(name)}, canActivate: [ AuthGuardService ] }`; From f16915c7672f3ffe2cc269f0fa68f92085543e4e Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Wed, 21 May 2025 11:41:05 +0400 Subject: [PATCH 4/5] fix(routing): Improve getRoute logic, add path optional param --- packages/devextreme-schematics/src/add-layout/index.ts | 2 +- packages/devextreme-schematics/src/utility/routing.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/devextreme-schematics/src/add-layout/index.ts b/packages/devextreme-schematics/src/add-layout/index.ts index 01f0683b5..6fffd1618 100644 --- a/packages/devextreme-schematics/src/add-layout/index.ts +++ b/packages/devextreme-schematics/src/add-layout/index.ts @@ -322,7 +322,7 @@ const modifyRouting = (host: Tree, routingFilePath: string) => { source = getSourceFile(host, routingFilePath)!; const routeInSource = findRoutesInSource(source)!; if (!hasComponentInRoutes(routeInSource, route.path)) { - const routeToAdd = getRoute(route.path, route.name); + const routeToAdd = getRoute(route.name, route.name, route.path); insertItemToArray(host, routingFilePath, routeInSource, routeToAdd); } } diff --git a/packages/devextreme-schematics/src/utility/routing.ts b/packages/devextreme-schematics/src/utility/routing.ts index b93d3dd86..153bd323a 100644 --- a/packages/devextreme-schematics/src/utility/routing.ts +++ b/packages/devextreme-schematics/src/utility/routing.ts @@ -20,9 +20,9 @@ export function hasComponentInRoutes(routes: Node, name: string) { return routesText.indexOf(componentName) !== -1; } -export function getRoute(name: string, componentName?: string) { +export function getRoute(name: string, componentName?: string, componentPath?: string) { return ` { - path: '${componentName ? name : strings.dasherize(name)}', + path: '${componentPath || strings.dasherize(name)}', component: ${componentName || getRouteComponentName(name)}, canActivate: [ AuthGuardService ] }`; From 1bbc3d0bc3adf763421ddb29ec7f413e429db403 Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Mon, 26 May 2025 11:17:06 +0400 Subject: [PATCH 5/5] fix: combine services and components into one array --- .../src/add-layout/index.ts | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/packages/devextreme-schematics/src/add-layout/index.ts b/packages/devextreme-schematics/src/add-layout/index.ts index 6fffd1618..ccd378a34 100644 --- a/packages/devextreme-schematics/src/add-layout/index.ts +++ b/packages/devextreme-schematics/src/add-layout/index.ts @@ -68,21 +68,34 @@ import { Change } from '@schematics/angular/utility/change'; import { PatchNodePackageInstallTask } from '../utility/patch'; const routes = [ + { + name: 'AuthGuardService', + type: 'service', + location: './shared/services' + }, { name: 'LoginFormComponent', - path: 'login-form' + path: 'login-form', + type: 'component', + location: './shared/components' }, { name: 'ResetPasswordFormComponent', - path: 'reset-password' + path: 'reset-password', + type: 'component', + location: './shared/components' }, { name: 'CreateAccountFormComponent', - path: 'create-account' + path: 'create-account', + type: 'component', + location: './shared/components' }, { name: 'ChangePasswordFormComponent', - path: 'change-password/:recoveryCode' + path: 'change-password/:recoveryCode', + type: 'component', + location: './shared/components' } ]; @@ -311,19 +324,19 @@ const modifyRouting = (host: Tree, routingFilePath: string) => { // TODO: Try to use the isolated host to generate the result string let source = getSourceFile(host, routingFilePath)!; const importChanges = []; - importChanges.push(insertImport(source, routingFilePath, 'AuthGuardService', './shared/services')); - for (const route of routes) { - importChanges.push(insertImport(source, routingFilePath, route.name, './shared/components')); + importChanges.push(insertImport(source, routingFilePath, route.name, route.location)); } applyChanges(host, importChanges, routingFilePath); for (const route of routes) { - source = getSourceFile(host, routingFilePath)!; - const routeInSource = findRoutesInSource(source)!; - if (!hasComponentInRoutes(routeInSource, route.path)) { - const routeToAdd = getRoute(route.name, route.name, route.path); - insertItemToArray(host, routingFilePath, routeInSource, routeToAdd); + if (route.type === 'component' && route.path) { + source = getSourceFile(host, routingFilePath)!; + const routeInSource = findRoutesInSource(source)!; + if (!hasComponentInRoutes(routeInSource, route.path)) { + const routeToAdd = getRoute(route.name, route.name, route.path); + insertItemToArray(host, routingFilePath, routeInSource, routeToAdd); + } } }