From 79acb5e1b7595d25c11c1733b329ae492e5b644e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 10 Mar 2020 22:14:42 +0100 Subject: [PATCH] Lazy load boards module --- frontend/src/app/angular4-modules.ts | 3 -- .../board-actions-registry.service.ts | 2 +- .../boards/board/board-cache.service.ts | 2 +- .../modules/boards/board/board-dm.service.ts | 8 ++--- .../board/board-list/board-lists.service.ts | 18 +++++----- .../app/modules/boards/board/board.service.ts | 4 +-- .../boards-root/boards-root.component.ts | 24 +++++++++++-- .../boards-sidebar/boards-menu.component.ts | 12 ++++--- .../boards/openproject-boards.module.ts | 35 +------------------ .../app/modules/router/openproject.routes.ts | 20 +++++++---- .../spec/features/board_navigation_spec.rb | 3 +- 11 files changed, 62 insertions(+), 69 deletions(-) diff --git a/frontend/src/app/angular4-modules.ts b/frontend/src/app/angular4-modules.ts index 28712c26d4..be1e38d32d 100644 --- a/frontend/src/app/angular4-modules.ts +++ b/frontend/src/app/angular4-modules.ts @@ -59,7 +59,6 @@ import {OpenprojectRouterModule} from "core-app/modules/router/openproject-route import {OpenprojectWorkPackageRoutesModule} from "core-app/modules/work_packages/openproject-work-package-routes.module"; import {BrowserModule} from "@angular/platform-browser"; import {OpenprojectCalendarModule} from "core-app/modules/calendar/openproject-calendar.module"; -import {OpenprojectBoardsModule} from "core-app/modules/boards/openproject-boards.module"; import {OpenprojectGlobalSearchModule} from "core-app/modules/global_search/openproject-global-search.module"; import {MainMenuToggleComponent} from "core-components/main-menu/main-menu-toggle.component"; import {MainMenuNavigationService} from "core-components/main-menu/main-menu-navigation.service"; @@ -84,8 +83,6 @@ import {globalDynamicComponents} from "core-app/global-dynamic-components.const" OpenprojectRouterModule, // Hal Module OpenprojectHalModule, - // Boards module - OpenprojectBoardsModule, // CKEditor OpenprojectEditorModule, diff --git a/frontend/src/app/modules/boards/board/board-actions/board-actions-registry.service.ts b/frontend/src/app/modules/boards/board/board-actions/board-actions-registry.service.ts index 8363e5893d..50d82d0fde 100644 --- a/frontend/src/app/modules/boards/board/board-actions/board-actions-registry.service.ts +++ b/frontend/src/app/modules/boards/board/board-actions/board-actions-registry.service.ts @@ -1,7 +1,7 @@ import {Injectable} from "@angular/core"; import {BoardActionService} from "core-app/modules/boards/board/board-actions/board-action.service"; -@Injectable() +@Injectable({ providedIn: 'root' }) export class BoardActionsRegistryService { private mapping:{ [attribute:string]:BoardActionService } = {}; diff --git a/frontend/src/app/modules/boards/board/board-cache.service.ts b/frontend/src/app/modules/boards/board/board-cache.service.ts index 2aa49769fe..eb1869a0b6 100644 --- a/frontend/src/app/modules/boards/board/board-cache.service.ts +++ b/frontend/src/app/modules/boards/board/board-cache.service.ts @@ -4,7 +4,7 @@ import {multiInput, MultiInputState} from "reactivestates"; import {Board} from "core-app/modules/boards/board/board"; import {BoardDmService} from "core-app/modules/boards/board/board-dm.service"; -@Injectable() +@Injectable({ providedIn: 'root' }) export class BoardCacheService extends StateCacheService { protected _state = multiInput(); diff --git a/frontend/src/app/modules/boards/board/board-dm.service.ts b/frontend/src/app/modules/boards/board/board-dm.service.ts index 27a6bcb740..6244567d59 100644 --- a/frontend/src/app/modules/boards/board/board-dm.service.ts +++ b/frontend/src/app/modules/boards/board/board-dm.service.ts @@ -1,6 +1,5 @@ import {Injectable} from "@angular/core"; import {from, Observable} from "rxjs"; -import {BoardListsService} from "core-app/modules/boards/board/board-list/board-lists.service"; import {HalResourceService} from "core-app/modules/hal/services/hal-resource.service"; import {PathHelperService} from "core-app/modules/common/path-helper/path-helper.service"; import {GridDmService} from "core-app/modules/hal/dm-services/grid-dm.service"; @@ -8,10 +7,9 @@ import {CurrentProjectService} from "core-components/projects/current-project.se import {GridResource} from "core-app/modules/hal/resources/grid-resource"; import {map, tap} from "rxjs/operators"; import {Board, BoardType} from "core-app/modules/boards/board/board"; -import {OpenprojectBoardsModule} from "core-app/modules/boards/openproject-boards.module"; import {AuthorisationService} from "core-app/modules/common/model-auth/model-auth.service"; -@Injectable() +@Injectable({ providedIn: 'root' }) export class BoardDmService { constructor(protected GridDm:GridDmService, @@ -30,8 +28,8 @@ export class BoardDmService { const path = this.boardPath(projectIdentifier); return from( - this.GridDm.list({ filters: [['scope', '=', [path]]] }) - ) + this.GridDm.list({ filters: [['scope', '=', [path]]] }) + ) .pipe( tap(collection => this.authorisationService.initModelAuth('boards', collection.$links)), map(collection => collection.elements.map(grid => new Board(grid))) diff --git a/frontend/src/app/modules/boards/board/board-list/board-lists.service.ts b/frontend/src/app/modules/boards/board/board-list/board-lists.service.ts index d052a884bb..e1d2b2951b 100644 --- a/frontend/src/app/modules/boards/board/board-list/board-lists.service.ts +++ b/frontend/src/app/modules/boards/board/board-list/board-lists.service.ts @@ -11,7 +11,7 @@ import {ApiV3Filter} from "core-components/api/api-v3/api-v3-filter-builder"; import {I18nService} from "core-app/modules/common/i18n/i18n.service"; import {NotificationsService} from "core-app/modules/common/notifications/notifications.service"; -@Injectable() +@Injectable({ providedIn: 'root' }) export class BoardListsService { private readonly v3 = this.pathHelper.api.v3; @@ -31,8 +31,10 @@ export class BoardListsService { return this.QueryFormDm .loadWithParams( - {pageSize: 0, - filters: filterJson}, + { + pageSize: 0, + filters: filterJson + }, undefined, this.CurrentProject.identifier, this.buildQueryRequest(params), @@ -53,8 +55,8 @@ export class BoardListsService { * Add a free query to the board */ public addFreeQuery(board:Board, queryParams:Object) { - const filter = this.freeBoardQueryFilter(); - return this.addQuery(board, queryParams, [filter]); + const filter = this.freeBoardQueryFilter(); + return this.addQuery(board, queryParams, [filter]); } /** @@ -95,8 +97,8 @@ export class BoardListsService { public: true, "_links": { "sortBy": [ - {"href": this.v3.resource("/queries/sort_bys/manualSorting-asc")}, - {"href": this.v3.resource("/queries/sort_bys/id-asc")}, + { "href": this.v3.resource("/queries/sort_bys/manualSorting-asc") }, + { "href": this.v3.resource("/queries/sort_bys/id-asc") }, ] }, ...params @@ -104,6 +106,6 @@ export class BoardListsService { } private freeBoardQueryFilter():ApiV3Filter { - return {manualSort: {operator: 'ow', values: []}}; + return { manualSort: { operator: 'ow', values: [] } }; } } diff --git a/frontend/src/app/modules/boards/board/board.service.ts b/frontend/src/app/modules/boards/board/board.service.ts index 2742043ba4..2221a8052f 100644 --- a/frontend/src/app/modules/boards/board/board.service.ts +++ b/frontend/src/app/modules/boards/board/board.service.ts @@ -17,7 +17,7 @@ export interface CreateBoardParams { attribute?:string; } -@Injectable() +@Injectable({ providedIn: 'root' }) export class BoardService { private loadAllPromise:Promise|undefined; @@ -25,7 +25,7 @@ export class BoardService { private text = { unnamed_board: this.I18n.t('js.boards.label_unnamed_board'), action_board: (attr:string) => this.I18n.t('js.boards.board_type.action_by_attribute', - { attribute: attr}), + { attribute: attr }), unnamed_list: this.I18n.t('js.boards.label_unnamed_list'), }; diff --git a/frontend/src/app/modules/boards/boards-root/boards-root.component.ts b/frontend/src/app/modules/boards/boards-root/boards-root.component.ts index 19ed121deb..032fe66b87 100644 --- a/frontend/src/app/modules/boards/boards-root/boards-root.component.ts +++ b/frontend/src/app/modules/boards/boards-root/boards-root.component.ts @@ -1,12 +1,30 @@ -import {Component} from "@angular/core"; -import {BoardCacheService} from "core-app/modules/boards/board/board-cache.service"; +import {Component, Injector} from "@angular/core"; +import {BoardConfigurationService} from "core-app/modules/boards/board/configuration-modal/board-configuration.service"; +import {BoardActionsRegistryService} from "core-app/modules/boards/board/board-actions/board-actions-registry.service"; +import {BoardStatusActionService} from "core-app/modules/boards/board/board-actions/status/status-action.service"; +import {BoardVersionActionService} from "core-app/modules/boards/board/board-actions/version/version-action.service"; +import {QueryUpdatedService} from "core-app/modules/boards/board/query-updated/query-updated.service"; @Component({ selector: 'boards-entry', template: '', providers: [ - BoardCacheService + BoardConfigurationService, + BoardStatusActionService, + BoardVersionActionService, + QueryUpdatedService ] }) export class BoardsRootComponent { + + constructor(readonly injector:Injector) { + + // Register action services + const registry = injector.get(BoardActionsRegistryService); + const statusAction = injector.get(BoardStatusActionService); + const versionAction = injector.get(BoardVersionActionService); + + registry.add('status', statusAction); + registry.add('version', versionAction); + } } diff --git a/frontend/src/app/modules/boards/boards-sidebar/boards-menu.component.ts b/frontend/src/app/modules/boards/boards-sidebar/boards-menu.component.ts index dcbe7781a7..3017afa189 100644 --- a/frontend/src/app/modules/boards/boards-sidebar/boards-menu.component.ts +++ b/frontend/src/app/modules/boards/boards-sidebar/boards-menu.component.ts @@ -22,9 +22,13 @@ export class BoardsMenuComponent implements OnInit { public boards$:Observable = this.boardCache.observeAll().pipe( map((boards:Board[]) => { - return boards.sort(function(a, b){ - if(a.name < b.name) { return -1; } - if(a.name > b.name) { return 1; } + return boards.sort(function (a, b) { + if (a.name < b.name) { + return -1; + } + if (a.name > b.name) { + return 1; + } return 0; }); }) @@ -43,7 +47,7 @@ export class BoardsMenuComponent implements OnInit { .onActivate('board_view') .subscribe(() => { this.focusBackArrow(); - this.boardService.loadAllBoards() + this.boardService.loadAllBoards(); }); } diff --git a/frontend/src/app/modules/boards/openproject-boards.module.ts b/frontend/src/app/modules/boards/openproject-boards.module.ts index 29fd196d69..aee74c02ea 100644 --- a/frontend/src/app/modules/boards/openproject-boards.module.ts +++ b/frontend/src/app/modules/boards/openproject-boards.module.ts @@ -26,25 +26,19 @@ // See docs/COPYRIGHT.rdoc for more details. // ++ -import {Injector, NgModule} from '@angular/core'; +import {NgModule} from '@angular/core'; import {OpenprojectCommonModule} from "core-app/modules/common/openproject-common.module"; import {OpenprojectWorkPackagesModule} from "core-app/modules/work_packages/openproject-work-packages.module"; import {Ng2StateDeclaration, UIRouter, UIRouterModule} from "@uirouter/angular"; import {BoardComponent} from "core-app/modules/boards/board/board.component"; import {BoardListComponent} from "core-app/modules/boards/board/board-list/board-list.component"; import {BoardsRootComponent} from "core-app/modules/boards/boards-root/boards-root.component"; -import {BoardListsService} from "core-app/modules/boards/board/board-list/board-lists.service"; -import {BoardService} from "core-app/modules/boards/board/board.service"; import {BoardInlineAddAutocompleterComponent} from "core-app/modules/boards/board/inline-add/board-inline-add-autocompleter.component"; -import {BoardCacheService} from "core-app/modules/boards/board/board-cache.service"; import {BoardsToolbarMenuDirective} from "core-app/modules/boards/board/toolbar-menu/boards-toolbar-menu.directive"; -import {BoardConfigurationService} from "core-app/modules/boards/board/configuration-modal/board-configuration.service"; import {BoardConfigurationModal} from "core-app/modules/boards/board/configuration-modal/board-configuration.modal"; import {BoardsIndexPageComponent} from "core-app/modules/boards/index-page/boards-index-page.component"; import {BoardsMenuComponent} from "core-app/modules/boards/boards-sidebar/boards-menu.component"; -import {BoardDmService} from "core-app/modules/boards/board/board-dm.service"; import {NewBoardModalComponent} from "core-app/modules/boards/new-board-modal/new-board-modal.component"; -import {BoardActionsRegistryService} from "core-app/modules/boards/board/board-actions/board-actions-registry.service"; import {AddListModalComponent} from "core-app/modules/boards/board/add-list-modal/add-list-modal.component"; import {BoardHighlightingTabComponent} from "core-app/modules/boards/board/configuration-modal/tabs/highlighting-tab.component"; import {AddCardDropdownMenuDirective} from "core-app/modules/boards/board/add-card-dropdown/add-card-dropdown-menu.directive"; @@ -53,9 +47,6 @@ import {DragScrollModule} from "cdk-drag-scroll"; import {BoardListMenuComponent} from "core-app/modules/boards/board/board-list/board-list-menu.component"; import {VersionBoardHeaderComponent} from "core-app/modules/boards/board/board-actions/version/version-board-header.component"; import {DynamicModule} from "ng-dynamic-component"; -import {BoardStatusActionService} from "core-app/modules/boards/board/board-actions/status/status-action.service"; -import {BoardVersionActionService} from "core-app/modules/boards/board/board-actions/version/version-action.service"; -import {QueryUpdatedService} from "core-app/modules/boards/board/query-updated/query-updated.service"; const menuItemClass = 'board-view-menu-item'; @@ -113,16 +104,6 @@ export function uiRouterBoardsConfiguration(uiRouter:UIRouter) { ); } -export function registerBoardsModule(injector:Injector) { - // Register action services - const registry = injector.get(BoardActionsRegistryService); - const statusAction = injector.get(BoardStatusActionService); - const versionAction = injector.get(BoardVersionActionService); - - registry.add('status', statusAction); - registry.add('version', versionAction); -} - @NgModule({ imports: [ OpenprojectCommonModule, @@ -138,17 +119,6 @@ export function registerBoardsModule(injector:Injector) { config: uiRouterBoardsConfiguration }), ], - providers: [ - BoardService, - BoardDmService, - BoardListsService, - BoardCacheService, - BoardConfigurationService, - BoardActionsRegistryService, - BoardStatusActionService, - BoardVersionActionService, - QueryUpdatedService, - ], declarations: [ BoardsIndexPageComponent, BoardComponent, @@ -168,8 +138,5 @@ export function registerBoardsModule(injector:Injector) { ] }) export class OpenprojectBoardsModule { - constructor(injector:Injector) { - registerBoardsModule(injector); - } } diff --git a/frontend/src/app/modules/router/openproject.routes.ts b/frontend/src/app/modules/router/openproject.routes.ts index 89d6020f2d..dedab6a90a 100644 --- a/frontend/src/app/modules/router/openproject.routes.ts +++ b/frontend/src/app/modules/router/openproject.routes.ts @@ -26,7 +26,7 @@ // See docs/COPYRIGHT.rdoc for more details. // ++ -import {StateDeclaration, StateService, Transition, TransitionService, UIRouter, UrlService} from '@uirouter/core'; +import {StateDeclaration, StateService, Transition, TransitionService, UIRouter} from '@uirouter/core'; import {INotification, NotificationsService} from "core-app/modules/common/notifications/notifications.service"; import {CurrentProjectService} from "core-components/projects/current-project.service"; import {Injector} from "@angular/core"; @@ -44,13 +44,19 @@ export const OPENPROJECT_ROUTES:Ng2StateDeclaration[] = [ params: { // value: null makes the parameter optional // squash: true avoids duplicate slashes when the parameter is not provided - projectPath: {type: 'path', value: null, squash: true}, - projects: {type: 'path', value: null, squash: true}, + projectPath: { type: 'path', value: null, squash: true }, + projects: { type: 'path', value: null, squash: true }, // Allow passing of flash messages after routes load - flash_message: {dynamic: true, value: null, inherit: false} + flash_message: { dynamic: true, value: null, inherit: false } } }, + { + name: 'boards.**', + parent: 'root', + url: '/boards', + loadChildren: () => import('../boards/openproject-boards.module').then(m => m.OpenprojectBoardsModule) + }, { name: 'bim.**', parent: 'root', @@ -182,8 +188,8 @@ export function initializeUiRouterListeners(injector:Injector) { const projectIdentifier = toParams.projectPath || currentProject.identifier; if (!toParams.projects && projectIdentifier) { const newParams = _.clone(toParams); - _.assign(newParams, {projectPath: projectIdentifier, projects: 'projects'}); - return $state.target(toState, newParams, {location: 'replace'}); + _.assign(newParams, { projectPath: projectIdentifier, projects: 'projects' }); + return $state.target(toState, newParams, { location: 'replace' }); } // Abort the transition and move to the url instead @@ -198,7 +204,7 @@ export function initializeUiRouterListeners(injector:Injector) { const path = window.location.pathname; const target = stateService.href(toState, toParams); - if (path !== target) { + if (target && path !== target) { window.location.href = target; return false; } diff --git a/modules/boards/spec/features/board_navigation_spec.rb b/modules/boards/spec/features/board_navigation_spec.rb index 0bc743f141..0ac45e80d2 100644 --- a/modules/boards/spec/features/board_navigation_spec.rb +++ b/modules/boards/spec/features/board_navigation_spec.rb @@ -82,7 +82,8 @@ describe 'Work Package boards spec', type: :feature, js: true do item.find('.toggler').click subitem = page.find('.main-menu--children-sub-item', text: 'My board', wait: 10) - expect(subitem[:href]).to end_with "/projects/#{project.identifier}/boards/#{board_view.id}" + # Ends with boards due to lazy route + expect(subitem[:href]).to end_with "/projects/#{project.identifier}/boards" subitem.click