Use new createAutocompleter for selectFields. This is the preparation for special selectFields that enable creating new elements from within the autocompleter.

pull/7317/head
Henriette Dinger 6 years ago
parent 04513e5b12
commit f4c67ec873
  1. 2
      frontend/src/app/modules/boards/board/add-list-modal/add-list-modal.html
  2. 54
      frontend/src/app/modules/common/autocomplete/create-autocompleter.component.ts
  3. 10
      frontend/src/app/modules/common/autocomplete/version-autocompleter.component.ts
  4. 12
      frontend/src/app/modules/common/openproject-common.module.ts
  5. 25
      frontend/src/app/modules/fields/edit/field-types/select-edit-field.component.html
  6. 23
      frontend/src/app/modules/fields/edit/field-types/select-edit-field.component.ts
  7. 19
      frontend/src/app/modules/work_packages/openproject-work-packages.module.ts
  8. 2
      lib/api/v3/versions/create_form_api.rb

@ -19,7 +19,7 @@
<div class="form--select-container">
<label class="form--label" [textContent]="actionService.localizedName"></label>
<ndc-dynamic [ndcDynamicComponent]="autocompleterComponent()"
[ndcDynamicInputs]="{ availableValues: availableValues }"
[ndcDynamicInputs]="{ availableValues: availableValues, appendTo: 'body', model: '' }"
[ndcDynamicOutputs]="referenceOutputs"
[ndcDynamicAttributes]="{ class: 'new-list--action-select' }">
</ndc-dynamic>

@ -38,11 +38,20 @@ import {HalResource} from "core-app/modules/hal/resources/hal-resource";
template: `
<ng-select *ngIf="createAllowed"
#addActionAttributeSelect
[(ngModel)]="model"
[items]="availableValues"
[addTag]="createNewElement.bind(this)"
[virtualScroll]="true"
[required]="required"
[clearable]="!required"
[disabled]="disabled"
[appendTo]="appendTo"
[id]="id"
(change)="changeModel($event)"
bindLabel="name"
appendTo="body">
(open)="opened()"
(close)="closed()"
(keydown)="keyPressed($event)"
bindLabel="name">
<ng-template ng-tag-tmp let-search="searchTerm">
<b [textContent]="text.add_new_action"></b>: {{search}}
</ng-template>
@ -50,10 +59,19 @@ import {HalResource} from "core-app/modules/hal/resources/hal-resource";
<ng-select *ngIf="!createAllowed"
#actionAttributeSelect
[(ngModel)]="model"
[items]="availableValues"
[virtualScroll]="true"
[required]="required"
[clearable]="!required"
[disabled]="disabled"
[appendTo]="appendTo"
[id]="id"
(change)="changeModel($event)"
bindLabel="name"
appendTo="body">
(open)="opened()"
(close)="closed()"
(keydown)="keyPressed($event)"
bindLabel="name">
</ng-select>
`,
selector: 'create-autocompleter'
@ -63,15 +81,24 @@ export class CreateAutocompleterComponent implements AfterViewInit {
@ViewChild('actionAttributeSelect') public autoCompleter:NgSelectComponent;
@Input() public availableValues:any[];
@Input() public appendTo:string;
@Input() public model:any;
@Input() public required:boolean = false;
@Input() public disabled:boolean = false;
@Input() public id:string = '';
@Input() public set createAllowed(val:boolean) {
this._createAllowed = val;
setTimeout(() => {
this.focusInputField();
});
};
}
@Output() public onCreate = new EventEmitter<string>();
@Output() public onChange = new EventEmitter<HalResource>();
@Output() public onKeydown = new EventEmitter<JQueryEventObject>();
@Output() public onOpen = new EventEmitter<void>();
@Output() public onClose = new EventEmitter<void>();
@Output() public onAfterViewInit = new EventEmitter<CreateAutocompleterComponent>();
private _createAllowed:boolean = false;
@ -86,6 +113,11 @@ export class CreateAutocompleterComponent implements AfterViewInit {
ngAfterViewInit() {
this.focusInputField();
this.onAfterViewInit.emit(this);
}
public openSelect() {
this.createAllowed ? this.addAutoCompleter.open() : this.autoCompleter.open();
}
public createNewElement(name:string) {
@ -96,6 +128,18 @@ export class CreateAutocompleterComponent implements AfterViewInit {
this.onChange.emit(element);
}
public opened() {
this.onOpen.emit();
}
public closed() {
this.onClose.emit();
}
public keyPressed(event:JQueryEventObject) {
this.onKeydown.emit(event);
}
public get createAllowed() {
return this._createAllowed;
}

@ -37,9 +37,11 @@ import {HalResource} from "core-app/modules/hal/resources/hal-resource";
@Component({
template: `
<create-autocompleter [availableValues]="availableValues"
[createAllowed]="createAllowed"
(onCreate)="createNewVersion($event)"
(onChange)="onModelChanged($event)">
[createAllowed]="createAllowed"
[appendTo]="'body'"
[model]=""
(onCreate)="createNewVersion($event)"
(onChange)="onModelChanged($event)">
</create-autocompleter>
`,
selector: 'version-autocompleter'
@ -77,7 +79,7 @@ export class VersionAutocompleterComponent implements OnInit {
public createNewVersion(name:string) {
this.versionDm.createVersion(this.getVersionPayload(name)).then((version) => {
this.onCreate.emit(version)
this.onCreate.emit(version);
});
}

@ -81,6 +81,9 @@ import {UserAvatarComponent} from "core-components/user/user-avatar/user-avatar.
import {GonService} from "core-app/modules/common/gon/gon.service";
import {BackRoutingService} from "core-app/modules/common/back-routing/back-routing.service";
import {EnterpriseBannerComponent} from "core-components/enterprise-banner/enterprise-banner.component";
import {DynamicModule} from "ng-dynamic-component";
import {VersionAutocompleterComponent} from "core-app/modules/common/autocomplete/version-autocompleter.component";
import {CreateAutocompleterComponent} from "core-app/modules/common/autocomplete/create-autocompleter.component";
export function bootstrapModule(injector:Injector) {
return () => {
@ -107,6 +110,9 @@ export function bootstrapModule(injector:Injector) {
// Our own A11y module
OpenprojectAccessibilityModule,
NgSelectModule,
DynamicModule.withComponents([VersionAutocompleterComponent,
CreateAutocompleterComponent])
],
exports: [
// Re-export all commonly used
@ -167,6 +173,8 @@ export function bootstrapModule(injector:Injector) {
// Enterprise Edition
EnterpriseBannerComponent,
DynamicModule,
],
declarations: [
OpDatePickerComponent,
@ -223,6 +231,10 @@ export function bootstrapModule(injector:Injector) {
// Enterprise Edition
EnterpriseBannerComponent,
// Autocompleter
CreateAutocompleterComponent,
VersionAutocompleterComponent,
],
entryComponents: [
OpDateTimeComponent,

@ -1,15 +1,10 @@
<ng-select [(ngModel)]="selectedOption"
[ngClass]="'wp-inline-edit--field'"
[required]="required"
[clearable]="!required"
[disabled]="inFlight"
[id]="handler.htmlId"
[items]="valueOptions"
bindLabel="name"
[virtualScroll]="true"
(keydown)="handler.handleUserKeydown($event, true)"
(change)="handler.handleUserSubmit()"
(open)="onOpen()"
(close)="onClose()"
[appendTo]="appendTo">
</ng-select>
<ndc-dynamic [ndcDynamicComponent]="autocompleterComponent()"
[ndcDynamicInputs]="{ availableValues: valueOptions,
appendTo: appendTo,
model: selectedOption ? selectedOption : '',
required: required,
disabled: inFlight,
id: handler.htmlId }"
[ndcDynamicOutputs]="referenceOutputs"
[ndcDynamicAttributes]="{ class: 'wp-inline-edit--field' }">
</ndc-dynamic>

@ -34,6 +34,7 @@ import {EditFieldComponent} from "../edit-field.component";
import {AngularTrackingHelpers} from "core-components/angular/tracking-functions";
import {untilComponentDestroyed} from "ng2-rx-componentdestroyed";
import {NgSelectComponent} from "@ng-select/ng-select";
import {CreateAutocompleterComponent} from "core-app/modules/common/autocomplete/create-autocompleter.component";
export interface ValueOption {
name:string;
@ -44,8 +45,6 @@ export interface ValueOption {
templateUrl: './select-edit-field.component.html'
})
export class SelectEditFieldComponent extends EditFieldComponent implements OnInit {
@ViewChild(NgSelectComponent) public ngSelectComponent:NgSelectComponent;
public options:any[];
public valueOptions:ValueOption[];
public template:string = '/components/wp-edit/field-types/wp-edit-select-field.directive.html';
@ -56,6 +55,16 @@ export class SelectEditFieldComponent extends EditFieldComponent implements OnIn
public halSorting:HalResourceSortingService;
private _autocompleterComponent:CreateAutocompleterComponent;
public referenceOutputs = {
onChange: (value:HalResource) => this.onChange(value),
onKeydown: (event:JQueryEventObject) => this.handler.handleUserKeydown(event, true),
onOpen: () => this.onOpen(),
onClose: () => this.onClose(),
onAfterViewInit: (component:CreateAutocompleterComponent) => this._autocompleterComponent = component
};
protected initialize() {
this.halSorting = this.injector.get(HalResourceSortingService);
this.text = {
@ -72,7 +81,10 @@ export class SelectEditFieldComponent extends EditFieldComponent implements OnIn
.subscribe(() => {
loadingPromise.then(() => this.openAutocompleteSelectField())
});
}
public autocompleterComponent() {
return CreateAutocompleterComponent;
}
public ngOnInit() {
@ -135,12 +147,17 @@ export class SelectEditFieldComponent extends EditFieldComponent implements OnIn
jQuery(this.hiddenOverflowContainer).removeClass('-hidden-overflow');
}
public onChange(value:HalResource) {
this.selectedOption = { name: value.name, $href: value.$href };
this.handler.handleUserSubmit();
}
private openAutocompleteSelectField() {
// The timeout takes care that the opening is added to the end of the current call stack.
// Thus we can be sure that the autocompleter is rendered and ready to be opened.
let that = this;
window.setTimeout(function () {
that.ngSelectComponent.open();
that._autocompleterComponent.openSelect();
}, 0);
}

@ -30,7 +30,6 @@ import {OpenprojectCommonModule} from 'core-app/modules/common/openproject-commo
import {WorkPackageFormAttributeGroupComponent} from 'core-components/wp-form-group/wp-attribute-group.component';
import {OpenprojectFieldsModule} from 'core-app/modules/fields/openproject-fields.module';
import {ChartsModule} from 'ng2-charts';
import {DynamicModule} from 'ng-dynamic-component';
import {APP_INITIALIZER, Injector, NgModule} from '@angular/core';
import {
GroupDescriptor,
@ -157,8 +156,6 @@ import {WorkPackageDmService} from "core-app/modules/hal/dm-services/work-packag
import {WorkPackageRelationsService} from "core-components/wp-relations/wp-relations.service";
import {OpenprojectBcfModule} from "core-app/modules/bcf/openproject-bcf.module";
import {WorkPackageRelationsAutocomplete} from "core-components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.component";
import {CreateAutocompleterComponent} from "core-app/modules/common/autocomplete/create-autocompleter.component";
import {VersionAutocompleterComponent} from "core-app/modules/common/autocomplete/version-autocompleter.component";
@NgModule({
imports: [
@ -177,10 +174,6 @@ import {VersionAutocompleterComponent} from "core-app/modules/common/autocomplet
// Work package custom actions
//WpCustomActionsModule,
DynamicModule.withComponents([WorkPackageFormAttributeGroupComponent,
WorkPackageChildrenQueryComponent,
VersionAutocompleterComponent,
CreateAutocompleterComponent])
],
providers: [
{
@ -368,10 +361,6 @@ import {VersionAutocompleterComponent} from "core-app/modules/common/autocomplet
// Card view
WorkPackageCardViewComponent,
// Autocompleter
CreateAutocompleterComponent,
VersionAutocompleterComponent,
],
entryComponents: [
// Split view
@ -446,10 +435,6 @@ import {VersionAutocompleterComponent} from "core-app/modules/common/autocomplet
// Card view
WorkPackageCardViewComponent,
// Autocompleter
CreateAutocompleterComponent,
VersionAutocompleterComponent,
],
exports: [
WorkPackagesTableController,
@ -460,10 +445,6 @@ import {VersionAutocompleterComponent} from "core-app/modules/common/autocomplet
WorkPackageFilterButtonComponent,
WorkPackageFilterContainerComponent,
WorkPackageIsolatedQuerySpaceDirective,
CreateAutocompleterComponent,
VersionAutocompleterComponent,
DynamicModule,
]
})
export class OpenprojectWorkPackagesModule {

@ -31,7 +31,7 @@ module API
module Versions
class CreateFormAPI < ::API::OpenProjectAPI
resource :form do
before do
after_validation do
authorize :manage_versions, global: true
end

Loading…
Cancel
Save