From b7f732ddcc8c11f842fa90e6f095bac4ab9a097f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20B=C3=A4dorf?= Date: Thu, 7 Apr 2022 13:40:36 +0200 Subject: [PATCH] Feature/41135 include all subprojects (#10413) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add new query attribute include_subprojects * Set include_subprojects in factories * Replace create_query helper with default endpoint * Adapt spec to new query create service * Add spec for changed subproject behavior * Extend project filter with replaced values and add spec * Fix spec trying to save default query * Fix ordered_work_packages now that we're base service compatible * Basic frontend for include all subprojects * Fix disabled state, update button colors * Add new query attribute include_subprojects * Set include_subprojects in factories * Replace create_query helper with default endpoint * Adapt spec to new query create service * Add spec for changed subproject behavior * Extend project filter with replaced values and add spec * Add a ParserStruct overriding Enumerable#group_by * Fix ordered_work_packages now that we're base service compatible * Add tooltip * Add tooltips to include projects * Add is parameter to query props for query space * Fix specs, add i18n strings * Correctly parse and update the query with includeSubprojects * FIx most spec * Fix badge count for team planner spec, fix duplicated where def in project filter * Only load project list if opening drop modal * Expect that sub_sub_bug is also present * I18nify the strings * Fix typo * Fix specs * Fix linting errors * Fix specs * Fix linting errors * Fix linting errors * Fix failing specs Co-authored-by: Oliver Günther --- .../api/v3/parse_query_params_service.rb | 3 +- .../update_query_from_params_service.rb | 6 + config/locales/js-en.yml | 4 + frontend/.eslintrc.js | 4 +- .../features/hal/resources/query-resource.ts | 2 + .../planner/team-planner.component.ts | 2 +- ...rk-package-view-toggle-button.component.ts | 6 +- .../wp-states-initialization.service.ts | 14 +- .../wp-query/url-params-helper.spec.ts | 2 + .../components/wp-query/url-params-helper.ts | 12 +- .../query-space/isolated-query-space.ts | 6 +- .../wp-isolated-query-space.directive.ts | 2 + .../wp-list-view/wp-list-view.component.ts | 6 +- .../view-services/wp-view-base.service.ts | 5 +- .../wp-view-display-representation.service.ts | 6 +- .../wp-view-include-subprojects.service.ts | 66 ++++++ .../wp-view-base/work-packages-view.base.ts | 4 + .../wp-view-dropdown-menu.directive.ts | 6 +- .../project-include.component.html | 16 +- .../project-include.component.sass | 10 + .../project-include.component.ts | 123 +++++++--- .../project-list.component.html | 45 ++-- .../project-include/project-list.component.ts | 24 +- .../drop-modal/drop-modal.component.ts | 12 +- .../components/tooltip/tooltip.component.html | 7 + .../components/tooltip/tooltip.component.ts | 24 ++ .../src/app/spot/drop-alignment-options.ts | 19 ++ .../src/app/spot/spot-docs.component.html | 67 +++++- frontend/src/app/spot/spot-docs.component.ts | 15 +- frontend/src/app/spot/spot.module.ts | 3 + .../spot/styles/sass/common/typography.sass | 14 ++ .../spot/styles/sass/components/button.sass | 36 ++- .../styles/sass/components/drop-modal.sass | 42 +++- .../spot/styles/sass/components/index.sass | 1 + .../app/spot/styles/sass/components/list.sass | 13 +- .../spot/styles/sass/components/tooltip.sass | 142 ++++++++++++ .../spot/styles/sass/variables/zindex.sass | 2 +- .../src/global_styles/content/_badges.sass | 4 + .../features/calendar_project_include_spec.rb | 4 +- ...planner_add_existing_work_packages_spec.rb | 8 + .../team_planner_project_include_spec.rb | 6 +- .../spec/features/team_planner_spec.rb | 14 +- ...eam_planner_subproject_constraints_spec.rb | 2 +- .../spec/support/pages/team_planner.rb | 10 + nix/shell.nix | 2 +- .../project_include_shared_examples.rb | 214 +++++++++++++++--- ...ork_packages_table_project_include_spec.rb | 4 +- .../api/v3/parse_query_params_service_spec.rb | 12 + .../update_query_from_params_service_spec.rb | 28 +++ .../components/project_include_component.rb | 10 + 50 files changed, 926 insertions(+), 163 deletions(-) create mode 100644 frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-include-subprojects.service.ts create mode 100644 frontend/src/app/spot/components/tooltip/tooltip.component.html create mode 100644 frontend/src/app/spot/components/tooltip/tooltip.component.ts create mode 100644 frontend/src/app/spot/drop-alignment-options.ts create mode 100644 frontend/src/app/spot/styles/sass/components/tooltip.sass diff --git a/app/services/api/v3/parse_query_params_service.rb b/app/services/api/v3/parse_query_params_service.rb index fbdea2f25e..a4f3058048 100644 --- a/app/services/api/v3/parse_query_params_service.rb +++ b/app/services/api/v3/parse_query_params_service.rb @@ -69,7 +69,8 @@ module API highlighting_mode: params[:highlightingMode], highlighted_attributes: highlighted_attributes_from_params(params), display_representation: params[:displayRepresentation], - show_hierarchies: boolearize(params[:showHierarchies]) + show_hierarchies: boolearize(params[:showHierarchies]), + include_subprojects: boolearize(params[:includeSubprojects]) } end diff --git a/app/services/update_query_from_params_service.rb b/app/services/update_query_from_params_service.rb index e091cf11c0..794f4d3abc 100644 --- a/app/services/update_query_from_params_service.rb +++ b/app/services/update_query_from_params_service.rb @@ -51,6 +51,8 @@ class UpdateQueryFromParamsService apply_display_representation(params) + apply_include_subprojects(params) + disable_hierarchy_when_only_grouped_by(params) if valid_subset @@ -112,6 +114,10 @@ class UpdateQueryFromParamsService query.display_representation = params[:display_representation] if params.key?(:display_representation) end + def apply_include_subprojects(params) + query.include_subprojects = params[:include_subprojects] if params.key?(:include_subprojects) + end + def disable_hierarchy_when_only_grouped_by(params) if params.key?(:group_by) && !params.key?(:show_hierarchies) query.show_hierarchies = false diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml index 4686f9b6af..7371e14750 100644 --- a/config/locales/js-en.yml +++ b/config/locales/js-en.yml @@ -1273,6 +1273,10 @@ en: all: 'All projects' selected: 'Only selected' search_placeholder: 'Search project...' + include_subprojects: 'Include all sub-projects' + tooltip: + include_all_selected: 'Include all sub-projects is currently selected.' + current_project: 'This is the current project you are in.' forms: submit_success_message: 'The form was successfully submitted' diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js index 744637820d..2bc6b9dc2e 100644 --- a/frontend/.eslintrc.js +++ b/frontend/.eslintrc.js @@ -42,11 +42,11 @@ module.exports = { */ "@angular-eslint/directive-selector": [ "error", - { "type": "attribute", "prefix": "op", "style": "camelCase" } + { "type": "attribute", "prefix": ["op", "spot"], "style": "camelCase" } ], "@angular-eslint/component-selector": [ "error", - { "type": "element", "prefix": "op", "style": "kebab-case" } + { "type": "element", "prefix": ["op", "spot"], "style": "kebab-case" } ], // Warn when new components are being created without OnPush diff --git a/frontend/src/app/features/hal/resources/query-resource.ts b/frontend/src/app/features/hal/resources/query-resource.ts index fdd7a55389..d2f27eb467 100644 --- a/frontend/src/app/features/hal/resources/query-resource.ts +++ b/frontend/src/app/features/hal/resources/query-resource.ts @@ -92,6 +92,8 @@ export class QueryResource extends HalResource { public project:ProjectResource; + public includeSubprojects:boolean; + public ordered_work_packages:QueryOrder; public $initialize(source:any) { diff --git a/frontend/src/app/features/team-planner/team-planner/planner/team-planner.component.ts b/frontend/src/app/features/team-planner/team-planner/planner/team-planner.component.ts index e48ba7c2da..115d7f488a 100644 --- a/frontend/src/app/features/team-planner/team-planner/planner/team-planner.component.ts +++ b/frontend/src/app/features/team-planner/team-planner/planner/team-planner.component.ts @@ -828,7 +828,7 @@ export class TeamPlannerComponent extends UntilDestroyedMixin implements OnInit, principals.forEach((principal) => { const resourceId = principal._links.self.href; - if (!assignable.includes(resourceId)) { + if (!assignable || !assignable.includes(resourceId)) { api.addEvent({ ...eventBase, resourceId }, 'background'); } }); diff --git a/frontend/src/app/features/work-packages/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.ts b/frontend/src/app/features/work-packages/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.ts index 9e48a4b362..5c24e42ad9 100644 --- a/frontend/src/app/features/work-packages/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.ts +++ b/frontend/src/app/features/work-packages/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.ts @@ -64,10 +64,12 @@ export class WorkPackageViewToggleButtonComponent extends UntilDestroyedMixin im timeline: this.I18n.t('js.views.timeline'), }; - constructor(readonly I18n:I18nService, + constructor( + readonly I18n:I18nService, readonly cdRef:ChangeDetectorRef, readonly wpDisplayRepresentationService:WorkPackageViewDisplayRepresentationService, - readonly wpTableTimeline:WorkPackageViewTimelineService) { + readonly wpTableTimeline:WorkPackageViewTimelineService, + ) { super(); } diff --git a/frontend/src/app/features/work-packages/components/wp-list/wp-states-initialization.service.ts b/frontend/src/app/features/work-packages/components/wp-list/wp-states-initialization.service.ts index 0b48a9c53e..978df3cc02 100644 --- a/frontend/src/app/features/work-packages/components/wp-list/wp-states-initialization.service.ts +++ b/frontend/src/app/features/work-packages/components/wp-list/wp-states-initialization.service.ts @@ -7,6 +7,7 @@ import { WorkPackageViewHighlightingService } from 'core-app/features/work-packa import { take } from 'rxjs/operators'; import { WorkPackageViewOrderService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-order.service'; import { WorkPackageViewDisplayRepresentationService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-display-representation.service'; +import { WorkPackageViewIncludeSubprojectsService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-include-subprojects.service'; import { WorkPackageViewSumService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-sum.service'; import { WorkPackageViewColumnsService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-columns.service'; import { WorkPackageViewSortByService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-sort-by.service'; @@ -27,7 +28,8 @@ import { WorkPackagesListChecksumService } from './wp-list-checksum.service'; @Injectable() export class WorkPackageStatesInitializationService { - constructor(protected states:States, + constructor( + protected states:States, protected querySpace:IsolatedQuerySpace, protected wpTableColumns:WorkPackageViewColumnsService, protected wpTableGroupBy:WorkPackageViewGroupByService, @@ -45,8 +47,9 @@ export class WorkPackageStatesInitializationService { protected apiV3Service:ApiV3Service, protected wpListChecksumService:WorkPackagesListChecksumService, protected authorisationService:AuthorisationService, - protected wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService) { - } + protected wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService, + protected wpIncludeSubprojects:WorkPackageViewIncludeSubprojectsService, + ) { } /** * Initialize the query and table states from the given query and results. @@ -128,6 +131,8 @@ export class WorkPackageStatesInitializationService { this.wpDisplayRepresentation.initialize(query, results); + this.wpIncludeSubprojects.initialize(query, results); + this.querySpace.additionalRequiredWorkPackages .values$() .pipe(take(1)) @@ -151,6 +156,7 @@ export class WorkPackageStatesInitializationService { this.wpTableHierarchies.initialize(query, results); this.wpTableHighlighting.initialize(query, results); this.wpDisplayRepresentation.initialize(query, results); + this.wpIncludeSubprojects.initialize(query, results); this.authorisationService.initModelAuth('query', query.$links); this.authorisationService.initModelAuth('work_packages', results.$links); @@ -168,6 +174,7 @@ export class WorkPackageStatesInitializationService { this.wpTableHierarchies.applyToQuery(query); this.wpTableOrder.applyToQuery(query); this.wpDisplayRepresentation.applyToQuery(query); + this.wpIncludeSubprojects.applyToQuery(query); } public clearStates() { @@ -186,6 +193,7 @@ export class WorkPackageStatesInitializationService { this.wpTableGroupBy.clear(reason); this.wpTableGroupFold.clear(reason); this.wpDisplayRepresentation.clear(reason); + this.wpIncludeSubprojects.clear(reason); this.wpTableSum.clear(reason); // Clear rendered state diff --git a/frontend/src/app/features/work-packages/components/wp-query/url-params-helper.spec.ts b/frontend/src/app/features/work-packages/components/wp-query/url-params-helper.spec.ts index cb10952b5f..c783925295 100644 --- a/frontend/src/app/features/work-packages/components/wp-query/url-params-helper.spec.ts +++ b/frontend/src/app/features/work-packages/components/wp-query/url-params-helper.spec.ts @@ -238,6 +238,7 @@ describe('UrlParamsHelper', () => { sortBy: JSON.stringify([['type', 'desc'], ['status', 'asc']]), timelineVisible: false, showHierarchies: false, + includeSubprojects: false, highlightingMode: 'inline', 'highlightedAttributes[]': ['a', 'b'], offset: 10, @@ -298,6 +299,7 @@ describe('UrlParamsHelper', () => { timelineVisible: false, showHierarchies: false, highlightingMode: 'inline', + includeSubprojects: false, sortBy: '[]', }; diff --git a/frontend/src/app/features/work-packages/components/wp-query/url-params-helper.ts b/frontend/src/app/features/work-packages/components/wp-query/url-params-helper.ts index 51ceff4941..0f782a65fe 100644 --- a/frontend/src/app/features/work-packages/components/wp-query/url-params-helper.ts +++ b/frontend/src/app/features/work-packages/components/wp-query/url-params-helper.ts @@ -67,6 +67,8 @@ export interface QueryProps { hla?:string[]; // Display representation dr?:string; + // Inlude subprojects + is?:boolean; // Pagination pa?:string|number; pp?:string|number; @@ -118,6 +120,7 @@ export class UrlParamsHelperService { hi: !!query.showHierarchies, g: _.get(query.groupBy, 'id', ''), dr: query.displayRepresentation, + is: query.includeSubprojects, ...this.encodeSums(query), ...this.encodeTimelineVisible(query), ...this.encodeHighlightingMode(query), @@ -217,7 +220,7 @@ export class UrlParamsHelperService { return queryData; } - const properties = JSON.parse(updateJson); + const properties = JSON.parse(updateJson) as QueryProps; if (properties.c) { queryData['columns[]'] = properties.c.map((column:any) => column); @@ -242,6 +245,10 @@ export class UrlParamsHelperService { queryData.displayRepresentation = properties.dr; } + if (properties.is !== undefined) { + queryData.includeSubprojects = properties.is; + } + if (properties.hl) { queryData.highlightingMode = properties.hl; } @@ -250,7 +257,7 @@ export class UrlParamsHelperService { queryData['highlightedAttributes[]'] = properties.hla.map((column:any) => column); } - if (properties.hi === false || properties.hi === true) { + if (properties.hi !== undefined) { queryData.showHierarchies = properties.hi; } @@ -317,6 +324,7 @@ export class UrlParamsHelperService { queryData.displayRepresentation = query.displayRepresentation; } + queryData.includeSubprojects = !!query.includeSubprojects; queryData.showHierarchies = !!query.showHierarchies; queryData.groupBy = _.get(query.groupBy, 'id', ''); diff --git a/frontend/src/app/features/work-packages/directives/query-space/isolated-query-space.ts b/frontend/src/app/features/work-packages/directives/query-space/isolated-query-space.ts index daaea2d562..c7e160b1c7 100644 --- a/frontend/src/app/features/work-packages/directives/query-space/isolated-query-space.ts +++ b/frontend/src/app/features/work-packages/directives/query-space/isolated-query-space.ts @@ -1,5 +1,9 @@ import { - derive, input, InputState, State, StatesGroup, + derive, + input, + InputState, + State, + StatesGroup, } from 'reactivestates'; import { Subject } from 'rxjs'; import { Injectable } from '@angular/core'; diff --git a/frontend/src/app/features/work-packages/directives/query-space/wp-isolated-query-space.directive.ts b/frontend/src/app/features/work-packages/directives/query-space/wp-isolated-query-space.directive.ts index 6334bc06d3..84ae852e3e 100644 --- a/frontend/src/app/features/work-packages/directives/query-space/wp-isolated-query-space.directive.ts +++ b/frontend/src/app/features/work-packages/directives/query-space/wp-isolated-query-space.directive.ts @@ -59,6 +59,7 @@ import { WorkPackageViewOrderService } from 'core-app/features/work-packages/rou import { CausedUpdatesService } from 'core-app/features/boards/board/caused-updates/caused-updates.service'; import { WorkPackageCardViewService } from 'core-app/features/work-packages/components/wp-card-view/services/wp-card-view.service'; import { WorkPackageViewDisplayRepresentationService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-display-representation.service'; +import { WorkPackageViewIncludeSubprojectsService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-include-subprojects.service'; import { WorkPackageViewHierarchyIdentationService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-hierarchy-indentation.service'; import { HalResourceNotificationService } from 'core-app/features/hal/services/hal-resource-notification.service'; import { WorkPackageNotificationService } from 'core-app/features/work-packages/services/notifications/work-package-notification.service'; @@ -101,6 +102,7 @@ import { WorkPackageService } from 'core-app/features/work-packages/services/wor WorkPackageViewFocusService, WorkPackageViewHighlightingService, WorkPackageViewDisplayRepresentationService, + WorkPackageViewIncludeSubprojectsService, WorkPackageViewOrderService, WorkPackageViewHierarchyIdentationService, CausedUpdatesService, diff --git a/frontend/src/app/features/work-packages/routing/wp-list-view/wp-list-view.component.ts b/frontend/src/app/features/work-packages/routing/wp-list-view/wp-list-view.component.ts index 11b86f51b7..17febaf012 100644 --- a/frontend/src/app/features/work-packages/routing/wp-list-view/wp-list-view.component.ts +++ b/frontend/src/app/features/work-packages/routing/wp-list-view/wp-list-view.component.ts @@ -91,7 +91,8 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements dragAndDropEnabled: true, }; - constructor(readonly I18n:I18nService, + constructor( + readonly I18n:I18nService, readonly injector:Injector, readonly $state:StateService, readonly keepTab:KeepTabService, @@ -102,7 +103,8 @@ export class WorkPackageListViewComponent extends UntilDestroyedMixin implements readonly wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService, readonly cdRef:ChangeDetectorRef, readonly elementRef:ElementRef, - private ngZone:NgZone) { + private ngZone:NgZone, + ) { super(); } diff --git a/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-base.service.ts b/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-base.service.ts index 17feeb5975..1b5083d150 100644 --- a/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-base.service.ts +++ b/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-base.service.ts @@ -45,8 +45,9 @@ export abstract class WorkPackageViewBaseService { /** Internal pristine state filled during +initialize+ only */ protected pristineState = input(); - constructor(protected readonly querySpace:IsolatedQuerySpace) { - } + constructor( + protected readonly querySpace:IsolatedQuerySpace, + ) { } /** * Get the state value from the current query. diff --git a/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-display-representation.service.ts b/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-display-representation.service.ts index e974323cd7..63ffff9038 100644 --- a/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-display-representation.service.ts +++ b/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-display-representation.service.ts @@ -38,8 +38,10 @@ export type WorkPackageDisplayRepresentationValue = 'list'|'card'; @Injectable() export class WorkPackageViewDisplayRepresentationService extends WorkPackageQueryStateService { - public constructor(readonly states:States, - readonly querySpace:IsolatedQuerySpace) { + public constructor( + readonly states:States, + readonly querySpace:IsolatedQuerySpace, + ) { super(querySpace); } diff --git a/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-include-subprojects.service.ts b/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-include-subprojects.service.ts new file mode 100644 index 0000000000..bbeb643d2c --- /dev/null +++ b/frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-include-subprojects.service.ts @@ -0,0 +1,66 @@ +// -- copyright +// OpenProject is an open source project management software. +// Copyright (C) 2012-2022 the OpenProject GmbH +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License version 3. +// +// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +// Copyright (C) 2006-2013 Jean-Philippe Lang +// Copyright (C) 2010-2013 the ChiliProject Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// See COPYRIGHT and LICENSE files for more details. +//++ + +import { QueryResource } from 'core-app/features/hal/resources/query-resource'; +import { States } from 'core-app/core/states/states.service'; +import { IsolatedQuerySpace } from 'core-app/features/work-packages/directives/query-space/isolated-query-space'; +import { Injectable } from '@angular/core'; +import { WorkPackageQueryStateService } from './wp-view-base.service'; + +@Injectable() +export class WorkPackageViewIncludeSubprojectsService extends WorkPackageQueryStateService { + public constructor( + readonly states:States, + readonly querySpace:IsolatedQuerySpace, + ) { + super(querySpace); + } + + public hasChanged(query:QueryResource):boolean { + return this.current !== query.includeSubprojects; + } + + valueFromQuery(query:QueryResource):boolean { + return query.includeSubprojects || false; + } + + public applyToQuery(query:QueryResource):boolean { + const { current } = this; + query.includeSubprojects = current; // eslint-disable-line no-param-reassign + + return true; + } + + public get current():boolean { + return this.lastUpdatedState.getValueOr(false); + } + + public setIncludeSubprojects(include:boolean):void { + this.update(include); + } +} diff --git a/frontend/src/app/features/work-packages/routing/wp-view-base/work-packages-view.base.ts b/frontend/src/app/features/work-packages/routing/wp-view-base/work-packages-view.base.ts index dd3e7dfb50..1bf5f33334 100644 --- a/frontend/src/app/features/work-packages/routing/wp-view-base/work-packages-view.base.ts +++ b/frontend/src/app/features/work-packages/routing/wp-view-base/work-packages-view.base.ts @@ -52,6 +52,7 @@ import { WorkPackageQueryStateService } from 'core-app/features/work-packages/ro import { WorkPackageStatesInitializationService } from 'core-app/features/work-packages/components/wp-list/wp-states-initialization.service'; import { WorkPackageViewOrderService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-order.service'; import { WorkPackageViewDisplayRepresentationService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-display-representation.service'; +import { WorkPackageViewIncludeSubprojectsService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-include-subprojects.service'; import { HalEvent, HalEventsService } from 'core-app/features/hal/services/hal-events.service'; import { DeviceService } from 'core-app/core/browser/device.service'; import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decorator'; @@ -106,6 +107,8 @@ export abstract class WorkPackagesViewBase extends UntilDestroyedMixin implement @InjectField() wpDisplayRepresentation:WorkPackageViewDisplayRepresentationService; + @InjectField() wpIncludeSubprojects:WorkPackageViewIncludeSubprojectsService; + @InjectField() halEvents:HalEventsService; @InjectField() deviceService:DeviceService; @@ -156,6 +159,7 @@ export abstract class WorkPackagesViewBase extends UntilDestroyedMixin implement this.setupChangeObserver(this.wpTableHighlighting); this.setupChangeObserver(this.wpTableOrder); this.setupChangeObserver(this.wpDisplayRepresentation); + this.setupChangeObserver(this.wpIncludeSubprojects); } /** diff --git a/frontend/src/app/shared/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts b/frontend/src/app/shared/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts index 3f23364dd5..e73feb4d5c 100644 --- a/frontend/src/app/shared/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts +++ b/frontend/src/app/shared/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts @@ -41,11 +41,13 @@ import { WorkPackageViewTimelineService } from 'core-app/features/work-packages/ selector: '[wpViewDropdown]', }) export class WorkPackageViewDropdownMenuDirective extends OpContextMenuTrigger { - constructor(readonly elementRef:ElementRef, + constructor( + readonly elementRef:ElementRef, readonly opContextMenu:OPContextMenuService, readonly I18n:I18nService, readonly wpDisplayRepresentationService:WorkPackageViewDisplayRepresentationService, - readonly wpTableTimeline:WorkPackageViewTimelineService) { + readonly wpTableTimeline:WorkPackageViewTimelineService, + ) { super(elementRef, opContextMenu); } diff --git a/frontend/src/app/shared/components/project-include/project-include.component.html b/frontend/src/app/shared/components/project-include/project-include.component.html index 6306721f01..7bab05992b 100644 --- a/frontend/src/app/shared/components/project-include/project-include.component.html +++ b/frontend/src/app/shared/components/project-include/project-include.component.html @@ -35,7 +35,7 @@ [disabled]="!(areProjectsLoaded$ | async)" [placeholder]="text.search_placeholder" name="project-include-search" - [(ngModel)]="query" + [(ngModel)]="searchText" [ngModelOptions]="{standalone: true}" data-qa-selector="project-include-search" > @@ -51,14 +51,24 @@ op-project-list [projects]="projects$ | async" [selected]="selectedProjects" - [query]="query" + [includeSubprojects]="includeSubprojects$ | async" + [searchText]="searchText" (update)="selectedProjects = $event" data-qa-selector="project-include-list" >
-
+
+ +
@@ -15,6 +16,7 @@ @@ -22,6 +24,7 @@ @@ -29,6 +32,7 @@ @@ -114,6 +118,14 @@ Currently selected value is {{ toggleValue }}
Child checkbox item
+
    +
  • + +
  • +
  • @@ -217,18 +232,24 @@ Currently selected value is {{ toggleValue }}

    Drop Modal

    - + + + + + + + + + +