From 936590fd678b7dae6631c2680676208bbed5cd26 Mon Sep 17 00:00:00 2001 From: Henriette Dinger Date: Fri, 28 Jun 2019 16:11:26 +0200 Subject: [PATCH] Remove toggled multi select and replace last occurrence with ng-select --- .../_table_configuration_modal.sass | 8 +- .../tabs/highlighting-tab.component.html | 48 +++--- .../tabs/highlighting-tab.component.ts | 88 ++++------- .../multi-toggled-select.component.html | 69 --------- .../multi-toggled-select.component.ts | 143 ------------------ .../common/openproject-common.module.ts | 6 - .../table_configuration/highlighting.rb | 26 ++-- 7 files changed, 79 insertions(+), 309 deletions(-) delete mode 100644 frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.html delete mode 100644 frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.ts diff --git a/app/assets/stylesheets/content/work_packages/_table_configuration_modal.sass b/app/assets/stylesheets/content/work_packages/_table_configuration_modal.sass index 637dbda904..05479260e3 100644 --- a/app/assets/stylesheets/content/work_packages/_table_configuration_modal.sass +++ b/app/assets/stylesheets/content/work_packages/_table_configuration_modal.sass @@ -6,6 +6,10 @@ float: left margin-right: 20px + &.-multi-line + margin-bottom: 0 + line-height: 40px + input margin-top: 0px @@ -19,5 +23,5 @@ .ee-attribute-highlighting-upsale margin-bottom: 1.5rem - multi-toggled-select - display: inline-block + ng-select + width: fit-content diff --git a/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html b/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html index 68f325e590..6272e09b86 100644 --- a/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html +++ b/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html @@ -9,21 +9,28 @@

-
@@ -36,20 +43,19 @@ [value]="true" name="entire_row_switch"> - &ngsp; - + + +
diff --git a/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts b/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts index 3dbc511c41..bd5ac07fe0 100644 --- a/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts +++ b/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts @@ -3,10 +3,8 @@ import {TabComponent} from 'core-components/wp-table/configuration-modal/tab-por import {WorkPackageTableHighlightingService} from 'core-components/wp-fast-table/state/wp-table-highlighting.service'; import {I18nService} from "core-app/modules/common/i18n/i18n.service"; import {HighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const"; -import {MultiToggledSelectOption} from "core-app/modules/common/multi-toggled-select/multi-toggled-select.component"; import {HalResource} from "core-app/modules/hal/resources/hal-resource"; import {States} from "core-app/components/states.service"; -import {WorkPackageTableHighlight} from "core-components/wp-fast-table/wp-table-highlight"; import {BannersService} from "core-app/modules/common/enterprise/banners.service"; import {IsolatedQuerySpace} from "core-app/modules/work_packages/query-space/isolated-query-space"; @@ -21,9 +19,10 @@ export class WpTableConfigurationHighlightingTab implements TabComponent { public lastEntireRowAttribute:HighlightingMode = 'status'; public eeShowBanners:boolean = false; - public availableMappedHighlightedAttributes:MultiToggledSelectOption[] = []; + public availableInlineHighlightedAttributes:HalResource[] = []; + public selectedAttributes:any[] = []; - public selectedAttributes:MultiToggledSelectOption[] = []; + public availableRowHighlightedAttributes:{name:string; value:HighlightingMode}[] = []; public text = { title: this.I18n.t('js.work_packages.table_configuration.highlighting'), @@ -49,28 +48,26 @@ export class WpTableConfigurationHighlightingTab implements TabComponent { readonly wpTableHighlight:WorkPackageTableHighlightingService) { } - public onSave() { - let mode = this.highlightingMode; - let highlightedAttributes:HalResource[] = this.selectedAttributesAsHal(); - this.wpTableHighlight.update({ mode: mode, selectedAttributes: highlightedAttributes }); - } + ngOnInit() { + this.availableInlineHighlightedAttributes = this.availableHighlightedAttributes; + this.availableRowHighlightedAttributes = [ + {name: this.text.highlighting_mode.status, value: 'status'}, + {name: this.text.highlighting_mode.priority, value: 'priority'}, + ]; - private selectedAttributesAsHal() { - if (this.isAllOptionSelected()) { - return []; - } else { - return this.multiToggleValuesToHal(this.selectedAttributes); - } - } + this.setSelectedValues(); + + this.eeShowBanners = this.Banners.eeShowBanners; + this.updateMode(this.wpTableHighlight.current.mode); - private multiToggleValuesToHal(values:MultiToggledSelectOption[]) { - return values.map(el => { - return _.find(this.availableHighlightedAttributes, (column) => column.href === el.value)!; - }); + if (this.eeShowBanners) { + this.updateMode('none'); + } } - private isAllOptionSelected() { - return this.selectedAttributes.length === 1 && _.get(this.selectedAttributes[0], 'value') === 'all'; + public onSave() { + let mode = this.highlightingMode; + this.wpTableHighlight.update({ mode: mode, selectedAttributes: this.selectedAttributes }); } public updateMode(mode:HighlightingMode | 'entire-row') { @@ -80,7 +77,7 @@ export class WpTableConfigurationHighlightingTab implements TabComponent { this.highlightingMode = mode; } - if (['status', 'priority', 'type'].indexOf(this.highlightingMode) !== -1) { + if (['status', 'priority'].indexOf(this.highlightingMode) !== -1) { this.lastEntireRowAttribute = this.highlightingMode; this.entireRowMode = true; } else { @@ -88,52 +85,25 @@ export class WpTableConfigurationHighlightingTab implements TabComponent { } } + public updateHighlightingAttributes(model:HalResource[]) { + this.selectedAttributes = model; + } + public disabledValue(value:boolean):string | null { return value ? 'disabled' : null; } - ngOnInit() { - this.availableMappedHighlightedAttributes = - [this.allAttributesOption].concat(this.getAvailableAttributes()); - - this.setSelectedValues(); - - this.eeShowBanners = this.Banners.eeShowBanners; - this.updateMode(this.wpTableHighlight.current.mode); - - if (this.eeShowBanners) { - this.updateMode('none'); - } + public get availableHighlightedAttributes():HalResource[] { + const schema = this.querySpace.queryForm.value!.schema; + return schema.highlightedAttributes.allowedValues; } private setSelectedValues() { const currentValues = this.wpTableHighlight.current.selectedAttributes; if (currentValues === undefined) { - this.selectedAttributes = [this.allAttributesOption]; + this.selectedAttributes = this.availableInlineHighlightedAttributes; } else { - this.selectedAttributes = this.mapAttributes(currentValues); + this.selectedAttributes = currentValues; } } - - public get availableHighlightedAttributes():HalResource[] { - const schema = this.querySpace.queryForm.value!.schema; - return schema.highlightedAttributes.allowedValues; - } - - public getAvailableAttributes():MultiToggledSelectOption[] { - return this.mapAttributes(this.availableHighlightedAttributes); - } - - private mapAttributes(input:HalResource[]):MultiToggledSelectOption[] { - return input.map((el:HalResource) => ({name: el.name, value: el.$href!})); - } - - private get allAttributesOption():MultiToggledSelectOption { - return { - name: this.text.highlighting_mode.inline_all_attributes, - singleOnly: true, - selectWhenEmptySelection: true, - value: 'all' - }; - } } diff --git a/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.html b/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.html deleted file mode 100644 index 6fa902212e..0000000000 --- a/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.html +++ /dev/null @@ -1,69 +0,0 @@ -
- - - - - - - - -
diff --git a/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.ts b/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.ts deleted file mode 100644 index 181aa9fff2..0000000000 --- a/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.ts +++ /dev/null @@ -1,143 +0,0 @@ -// -- copyright -// OpenProject is a project management system. -// Copyright (C) 2012-2015 the OpenProject Foundation (OPF) -// -// 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 doc/COPYRIGHT.rdoc for more details. -// ++ - -import {Component, EventEmitter, Input, OnInit, Output} from "@angular/core"; -import {I18nService} from "core-app/modules/common/i18n/i18n.service"; -import {AngularTrackingHelpers} from "core-components/angular/tracking-functions"; - -export interface MultiToggledSelectOption { - name:string; - singleOnly?:true; - selectWhenEmptySelection?:true; - value:any; -} - -@Component({ - selector: 'multi-toggled-select', - templateUrl: './multi-toggled-select.component.html' -}) -export class MultiToggledSelectComponent implements OnInit { - @Input() availableOptions:T[]; - @Input() initialSelection:T[]|undefined; - @Input() selectHtmlId:string|undefined; - @Input() isRequired:boolean = false; - @Input() isDisabled:boolean = false; - @Input() currentValueInvalid:boolean = false; - - @Output() onValueChange = new EventEmitter(); - @Output() onMultiToggle = new EventEmitter(); - @Output() onValueKeydown = new EventEmitter(); - - public text = { - requiredPlaceholder: this.I18n.t('js.placeholders.selection'), - placeholder: this.I18n.t('js.placeholders.default'), - switch_to_single_select: this.I18n.t('js.work_packages.label_switch_to_single_select'), - switch_to_multi_select: this.I18n.t('js.work_packages.label_switch_to_multi_select'), - }; - - /** Whether we're currently multi-selecting */ - public isMultiselect = false; - - /** Comparer function for values */ - public compareByValue = AngularTrackingHelpers.compareByAttribute('value'); - - /** Current selected option */ - private _selectedOption:T|T[]|undefined; - - constructor(protected readonly I18n:I18nService) { - } - - ngOnInit() { - this.ensureSingleInitialSelectionIsNotArray(); - this.isMultiselect = this.hasMultipleSelectedOptions(); - } - - public hasMultipleSelectedOptions() { - return (this.selectedOption instanceof Array) && this.selectedOption.length > 1; - } - - public emitValueChange() { - this.onValueChange.emit(_.castArray(this.selectedOption || [])); - } - - public toggleMultiselect() { - this.isMultiselect = !this.isMultiselect; - - if (this.isMultiselect ) { - /** Switching to multi select. - * Ensure selectedOption is either an empty Array or the selectedOption, - * Preventing cases such as `[undefined]`. **/ - this._selectedOption = _.castArray(this.selectedOption || []); - } else { - /** Switching to single select. **/ - if (Array.isArray(this.selectedOption)) { - if (this.selectedOption.length === 0) { - this.onEmptySelection(); - } else { - this._selectedOption = (this.selectedOption as T[])[0]; - } - this.emitValueChange(); - } - } - } - - public get availableMultiOptions() { - return this.availableOptions.filter(el => el.singleOnly !== true); - } - - public get selectedOption():T|T[]|undefined { - return this._selectedOption; - } - - public set selectedOption(val:T|T[]|undefined) { - this._selectedOption = val; - } - - public get nullOption():T { - return { name: this.text.placeholder, value: '' } as T; - } - - /** Ensure that the initialSelection becomes an Array. - * `undefined` becomes an empty Array. **/ - private ensureSingleInitialSelectionIsNotArray():void { - if (Array.isArray(this.initialSelection)) { - if (this.initialSelection.length === 1) { - this.selectedOption = this.initialSelection[0]; - } else { - this.selectedOption = this.initialSelection; - } - } - } - - private onEmptySelection():void { - const newSelection = _.find(this.availableOptions, option => option.selectWhenEmptySelection === true); - if (newSelection) { - this.selectedOption = newSelection; - } - } -} diff --git a/frontend/src/app/modules/common/openproject-common.module.ts b/frontend/src/app/modules/common/openproject-common.module.ts index 509815cd1a..91492f2959 100644 --- a/frontend/src/app/modules/common/openproject-common.module.ts +++ b/frontend/src/app/modules/common/openproject-common.module.ts @@ -57,7 +57,6 @@ import {highlightColBootstrap} from "./highlight-col/highlight-col.directive"; import {HookService} from "../plugins/hook-service"; import {HTMLSanitizeService} from "./html-sanitize/html-sanitize.service"; import {ColorsAutocompleter} from "core-app/modules/common/colors/colors-autocompleter.component"; -import {MultiToggledSelectComponent} from "core-app/modules/common/multi-toggled-select/multi-toggled-select.component"; import {BannersService} from "core-app/modules/common/enterprise/banners.service"; import {ResizerComponent} from "core-app/modules/common/resizer/resizer.component"; import {TablePaginationComponent} from 'core-components/table-pagination/table-pagination.component'; @@ -150,9 +149,6 @@ export function bootstrapModule(injector:Injector) { // Table highlight HighlightColDirective, - // Multi select component - MultiToggledSelectComponent, - ResizerComponent, TablePaginationComponent, @@ -213,8 +209,6 @@ export function bootstrapModule(injector:Injector) { CopyToClipboardDirective, ColorsAutocompleter, - MultiToggledSelectComponent, - ResizerComponent, TablePaginationComponent, diff --git a/spec/support/components/work_packages/table_configuration/highlighting.rb b/spec/support/components/work_packages/table_configuration/highlighting.rb index 0bd921820a..77738f710e 100644 --- a/spec/support/components/work_packages/table_configuration/highlighting.rb +++ b/spec/support/components/work_packages/table_configuration/highlighting.rb @@ -44,23 +44,31 @@ module Components def switch_entire_row_highlight(label) modal_open? or open_modal choose "Entire row by" - page.all(".form--field")[1].select label + + # Open select field + within(page.all(".form--field")[1]) do + page.find('.ng-input input').click + end + page.find('.ng-dropdown-panel .ng-option', text: label).click apply end def switch_inline_attribute_highlight(*labels) modal_open? or open_modal choose "Highlighted attribute(s)" + + # Open select field within(page.all(".form--field")[0]) do - if labels.size == 1 - select labels.first - elsif labels.size > 1 - find('[class*="--toggle-multiselect"]').click - labels.each do |label| - select label - end - end + page.find('.ng-input input').click end + + # Delete all previously selected options + page.all('.ng-dropdown-panel .ng-option-selected').each { |option| option.click } + + labels.each do |label| + page.find('.ng-dropdown-panel .ng-option', text: label).click + end + apply end