Exclude projects from the default filter application on work package creation. This became necessary due to the new project include functionality..

Add test case for regression #42271 where work packages where created in the wrong project
pull/10689/head
Henriette Darge 3 years ago committed by Oliver Günther
parent 4557cb924d
commit 41dc368a5a
  1. 58
      frontend/src/app/features/work-packages/components/wp-new/wp-create.service.ts
  2. 32
      spec/features/work_packages/table/work_packages_table_project_include_spec.rb

@ -26,8 +26,14 @@
// See COPYRIGHT and LICENSE files for more details.
//++
import { Injectable, Injector } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import {
Injectable,
Injector,
} from '@angular/core';
import {
Observable,
Subject,
} from 'rxjs';
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
import { HookService } from 'core-app/features/plugins/hook-service';
import { WorkPackageFilterValues } from 'core-app/features/work-packages/components/wp-edit-form/work-package-filter-values';
@ -43,11 +49,17 @@ import { HalEventsService } from 'core-app/features/hal/services/hal-events.serv
import { AuthorisationService } from 'core-app/core/model-auth/model-auth.service';
import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin';
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
import { HalResource, HalSource, HalSourceLink } from 'core-app/features/hal/resources/hal-resource';
import {
HalResource,
HalSource,
HalSourceLink,
} from 'core-app/features/hal/resources/hal-resource';
import idFromLink from 'core-app/features/hal/helpers/id-from-link';
import { SchemaResource } from 'core-app/features/hal/resources/schema-resource';
import { SchemaCacheService } from 'core-app/core/schemas/schema-cache.service';
import { HalResourceService } from 'core-app/features/hal/services/hal-resource.service';
import { ResourceChangeset } from 'core-app/shared/components/fields/changeset/resource-changeset';
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
export const newWorkPackageHref = '/api/v3/work_packages/new';
@ -58,7 +70,8 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
// Allow callbacks to happen on newly created work packages
protected newWorkPackageCreatedSubject = new Subject<WorkPackageResource>();
constructor(protected injector:Injector,
constructor(
protected injector:Injector,
protected hooks:HookService,
protected apiV3Service:ApiV3Service,
protected halResourceService:HalResourceService,
@ -66,7 +79,9 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
protected authorisationService:AuthorisationService,
protected halEditing:HalResourceEditingService,
protected schemaCache:SchemaCacheService,
protected halEvents:HalEventsService) {
protected halEvents:HalEventsService,
protected currentProject:CurrentProjectService,
) {
super();
this.halEditing
@ -90,7 +105,7 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
});
}
protected newWorkPackageCreated(wp:WorkPackageResource) {
protected newWorkPackageCreated(wp:WorkPackageResource):void {
this.reset();
this.newWorkPackageCreatedSubject.next(wp);
}
@ -121,7 +136,7 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
return change;
}
public copyWorkPackage(copyFrom:WorkPackageChangeset) {
public copyWorkPackage(copyFrom:WorkPackageChangeset):Promise<WorkPackageChangeset> {
const request = copyFrom.pristineResource.$source;
// Ideally we would make an empty request before to get the create schema (cannot use the update schema of the source changeset)
@ -164,23 +179,32 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
return this.form;
}
public cancelCreation() {
public cancelCreation():void {
this.halEditing.stopEditing({ href: newWorkPackageHref });
this.reset();
}
public changesetUpdates$() {
public changesetUpdates$():Observable<ResourceChangeset> {
return this
.halEditing
.state(newWorkPackageHref)
.values$();
}
public createOrContinueWorkPackage(projectIdentifier:string|null|undefined, type?:number, defaults?:HalSource) {
public createOrContinueWorkPackage(projectIdentifier:string|null|undefined, type?:number, defaults?:HalSource):Promise<WorkPackageChangeset> {
let changePromise = this.continueExistingEdit(type);
const extendedDefaults:HalSource = defaults || { _links: {} };
const projectId = this.currentProject.id;
// Special case due to the introduction of the project include dropdown
// If we are in a project, we want the create wp to be part of that project.
// Only on the global WP page, the filters should be applied.
if (projectId) {
extendedDefaults._links.project = { href: this.apiV3Service.projects.id(projectId).path };
}
if (!changePromise) {
changePromise = this.createNewWithDefaults(projectIdentifier, defaults);
changePromise = this.createNewWithDefaults(projectIdentifier, extendedDefaults);
}
return changePromise.then((change:WorkPackageChangeset) => {
@ -196,7 +220,7 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
});
}
protected reset() {
protected reset():void {
this
.apiV3Service
.work_packages
@ -205,7 +229,7 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
this.form = undefined;
}
protected continueExistingEdit(type?:number) {
protected continueExistingEdit(type?:number):Promise<WorkPackageChangeset>|null {
const change = this.halEditing.state(newWorkPackageHref).value as WorkPackageChangeset;
if (change !== undefined) {
const changeType = change.projectedResource.type;
@ -231,10 +255,10 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
* The first can be employed to e.g. provide the type or the parent of the work package.
* The later can be employed to create a work package that adheres to the filter values.
*
* @params projectIdentifier The project the work package is to be created in.
* @param projectIdentifier The project the work package is to be created in.
* @param defaults Values the new work package should possess on creation.
*/
protected createNewWithDefaults(projectIdentifier:string|null|undefined, defaults?:HalSource) {
protected createNewWithDefaults(projectIdentifier:string|null|undefined, defaults?:HalSource):Promise<WorkPackageChangeset> {
return this
.withFiltersPayload(projectIdentifier, defaults)
.then((filterDefaults) => {
@ -261,10 +285,10 @@ export class WorkPackageCreateService extends UntilDestroyedMixin {
*
* The ignoring functionality could be generalized.
*
* @params object
* @param object
* @param defaults
*/
private defaultsFromFilters(object:HalSource|WorkPackageChangeset, defaults?:HalSource) {
private defaultsFromFilters(object:HalSource|WorkPackageChangeset, defaults?:HalSource):void {
// Not using WorkPackageViewFiltersService here as the embedded table does not load the form
// which will result in that service having empty current filters.
const query = this.querySpace.query.value;

@ -29,8 +29,10 @@
require 'spec_helper'
require_relative '../project_include/project_include_shared_examples'
describe 'Calendar project include', type: :feature, js: true do
describe 'Work package project include', type: :feature, js: true do
shared_let(:enabled_modules) { %w[work_package_tracking] }
shared_let(:status) { create(:default_status) }
shared_let(:priority) { create(:default_priority) }
shared_let(:permissions) { %i[view_work_packages edit_work_packages add_work_packages save_queries manage_public_queries] }
it_behaves_like 'has a project include dropdown' do
@ -67,5 +69,33 @@ describe 'Calendar project include', type: :feature, js: true do
work_package_view.expect_work_package_listed(task, other_task, sub_bug, sub_sub_bug, other_other_task)
end
it 'creates new work packages in the host project of the work package view (regression #42271)' do
dropdown.expect_count 1
# Make sure the filter gets set once
dropdown.toggle!
dropdown.expect_open
dropdown.toggle_checkbox(other_sub_sub_project.id)
dropdown.click_button 'Apply'
dropdown.expect_count 2
work_package_view.click_inline_create
subject_field = work_package_view.edit_field(nil, :subject)
subject_field.expect_active!
# Save the WP
subject_field.set_value 'Foobar!'
subject_field.submit_by_enter
work_package_view.expect_and_dismiss_toaster(
message: 'Successful creation. Click here to open this work package in fullscreen view.'
)
work_package_view.expect_work_package_subject 'Foobar!'
inline_created = WorkPackage.last
expect(inline_created.project).to eq(project)
end
end
end

Loading…
Cancel
Save