WIP feat: replace ng2-select2 => ngx-select-ex (#706)

* feat: replace ng2-select2 => ngx-select-ex

* feat: style the ngrx-select

* feat: replace secondary role select2

* feat: replace Select2OptionData => SelectOptionData

* feat: replace select2 => ngx-select in macro-tab component

* feat: replace select2 => ngx-select in keymap-tab component

* feat: fix styles

* chore: remove select2 from dependencies

* fix: macro editor overflow

* fix: set the same font size for the toggle button

* fix: overflow

* chore: use @ert78gb/ngx-select-ex version of ngx-select-ex
This commit is contained in:
Róbert Kiss
2018-07-02 23:44:39 +02:00
committed by László Monda
parent cfc0af9655
commit 15df8d7129
23 changed files with 200 additions and 190 deletions

View File

@@ -8,10 +8,11 @@
<icon *ngIf="deletable" name="trash" (click)="deleteAction()"></icon>
</div>
<div class="list-group-item macro-action-editor__container"
[@toggler]="((editable && editing) || newItem) ? 'active' : 'inactive'">
<macro-action-editor
[macroAction]="macroAction"
(cancel)="cancelEdit()"
(save)="saveEditedAction($event)">
</macro-action-editor>
</div>
[@toggler]="((editable && editing) || newItem) ? 'active' : 'inactive'"
[style.overflow]="overflow">
<macro-action-editor
[macroAction]="macroAction"
(cancel)="cancelEdit()"
(save)="saveEditedAction($event)">
</macro-action-editor>
</div>

View File

@@ -1,7 +1,7 @@
@import '../../../../styles/variables';
:host {
overflow: hidden;
overflow: visible;
display: block;
&.macro-item:first-of-type {

View File

@@ -45,6 +45,7 @@ export class MacroItemComponent implements OnInit, OnChanges {
iconName: string;
editing: boolean;
newItem: boolean = false;
overflow = 'hidden';
constructor(private mapper: MapperService) { }
@@ -53,6 +54,7 @@ export class MacroItemComponent implements OnInit, OnChanges {
if (!this.macroAction) {
this.editing = true;
this.newItem = true;
this.overflow = 'visible';
}
}
@@ -65,6 +67,7 @@ export class MacroItemComponent implements OnInit, OnChanges {
saveEditedAction(editedAction: MacroAction): void {
this.macroAction = editedAction;
this.editing = false;
this.overflow = 'hidden';
this.updateView();
this.save.emit(editedAction);
}
@@ -77,10 +80,12 @@ export class MacroItemComponent implements OnInit, OnChanges {
this.editing = true;
this.edit.emit();
this.setOverflow('visible');
}
cancelEdit(): void {
this.editing = false;
this.overflow = 'hidden';
this.cancel.emit();
}
@@ -202,4 +207,12 @@ export class MacroItemComponent implements OnInit, OnChanges {
});
this.title += selectedButtonLabels.join(', ');
}
private setOverflow(value: string): void {
// tslint:disable: align
setTimeout(() => {
this.overflow = value;
}, 600);
// tslint:enable: align
}
}

View File

@@ -116,23 +116,6 @@
}
}
.select2-item {
position: relative;
font-size: 1.5rem;
&.keymap-name--wrapper {
padding-left: 50px;
}
.layout-segment-code {
height: 2rem;
position: absolute;
left: 0;
top: 50%;
margin-top: -1rem;
}
}
.popover-action-form {
margin-top: 4px;

View File

@@ -4,12 +4,23 @@
<ng-template [ngIf]="keymapOptions.length > 0">
<div>
<b>Switch to keymap:</b>
<select2
[data]="keymapOptions"
[value]="selectedKeymap?.abbreviation || -1"
(valueChanged)="onChange($event)"
[width]="'100%'"
></select2>
<ngx-select [items]="keymapOptions"
[ngModel]="selectedKeymap?.abbreviation || -1"
[autoActiveOnMouseEnter]="false"
size="small"
optionValueField="id"
optionTextField="text"
(select)="onChange($event)">
<ng-template ngx-select-option let-option>
<span [ngClass]="{'indent-dropdown-item':option.data.id !== '-1'}">
<span>{{ option.text }}</span>
<span class="scancode--searchterm">
{{ option.data.additional?.explanation}}
</span>
</span>
</ng-template>
</ngx-select>
</div>
<div>
<div class="empty" *ngIf="!selectedKeymap?.abbreviation">

View File

@@ -16,7 +16,7 @@
margin-right: 7px;
}
select2 {
ngx-select {
flex: 1;
}
}

View File

@@ -1,8 +1,8 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { Select2OptionData } from 'ng2-select2/ng2-select2';
import { Keymap, KeyAction, SwitchKeymapAction } from 'uhk-common';
import { Tab } from '../tab';
import { SelectOptionData } from '../../../../models/select-option-data';
@Component({
selector: 'keymap-tab',
@@ -14,7 +14,7 @@ export class KeymapTabComponent extends Tab implements OnChanges {
@Input() defaultKeyAction: KeyAction;
@Input() keymaps: Keymap[];
keymapOptions: Array<Select2OptionData>;
keymapOptions: Array<SelectOptionData>;
selectedKeymap: Keymap;
constructor() {
@@ -25,7 +25,7 @@ export class KeymapTabComponent extends Tab implements OnChanges {
ngOnChanges(changes: SimpleChanges) {
if (changes.keymaps) {
this.keymapOptions = this.keymaps
.map((keymap: Keymap): Select2OptionData => {
.map((keymap: Keymap): SelectOptionData => {
return {
id: keymap.abbreviation,
text: keymap.name
@@ -40,12 +40,11 @@ export class KeymapTabComponent extends Tab implements OnChanges {
this.validAction.emit(true);
}
// TODO: change to the correct type when the wrapper has added it.
onChange(event: any) {
if (event.value === '-1') {
onChange(event: string) {
if (event === '-1') {
this.selectedKeymap = undefined;
} else {
this.selectedKeymap = this.keymaps.find((keymap: Keymap) => keymap.abbreviation === event.value);
this.selectedKeymap = this.keymaps.find((keymap: Keymap) => keymap.abbreviation === event);
}
}

View File

@@ -1,12 +1,27 @@
<div class="scancode-options">
<b class="setting-label">Scancode:</b>
<select2
[data]="scanCodeGroups"
[value]="selectedScancodeOption.id"
(valueChanged)="onScancodeChange($event)"
[width]="200"
[options]="options"
></select2>
<div class="scancode-container">
<ngx-select [items]="scanCodeGroups"
[ngModel]="selectedScancodeOption.id"
[autoActiveOnMouseEnter]="false"
size="small"
optionValueField="id"
optionTextField="text"
optGroupLabelField="text"
optGroupOptionsField="children"
(select)="onScancodeChange($event)">
<ng-template ngx-select-option let-option>
<span [ngClass]="{'indent-dropdown-item':option.data.id !== '0'}">
<span>{{ option.text }}</span>
<span class="scancode--searchterm">
{{ option.data.additional?.explanation}}
</span>
</span>
</ng-template>
</ngx-select>
</div>
<icon name="question-circle"
data-toggle="tooltip"
html="true"
@@ -41,12 +56,28 @@
</div>
<div class="long-press-container" *ngIf="secondaryRoleEnabled">
<b class="setting-label">Secondary role:</b>
<select2 #secondaryRoleSelect
[data]="secondaryRoleGroups"
[value]="selectedSecondaryRoleIndex.toString()"
(valueChanged)="onSecondaryRoleChange($event)"
[width]="140"
></select2>
<div class="secondary-role-groups-container">
<ngx-select [items]="secondaryRoleGroups"
[ngModel]="selectedSecondaryRoleIndex.toString()"
[autoActiveOnMouseEnter]="false"
size="small"
optionValueField="id"
optionTextField="text"
optGroupLabelField="text"
optGroupOptionsField="children"
(select)="onSecondaryRoleChange($event)">
<ng-template ngx-select-option let-option>
<span [ngClass]="{'indent-dropdown-item':option.data.id !== '-1'}">
<span>{{ option.text }}</span>
<span class="scancode--searchterm">
{{ option.data.additional?.explanation}}
</span>
</span>
</ng-template>
</ngx-select>
</div>
<icon name="question-circle"
data-toggle="tooltip"
html="true"

View File

@@ -79,4 +79,14 @@
display: block;
}
}
.scancode-container {
display: inline-block;
width: 200px;
}
.secondary-role-groups-container {
display: inline-block;
width: 140px;
}
}

View File

@@ -1,9 +1,9 @@
import { Component, Input, OnChanges } from '@angular/core';
import { Select2OptionData, Select2TemplateFunction } from 'ng2-select2';
import { KeyAction, KeystrokeAction, KeystrokeType, SCANCODES, SECONDARY_ROLES } from 'uhk-common';
import { Tab } from '../tab';
import { MapperService } from '../../../../services/mapper.service';
import { SelectOptionData } from '../../../../models/select-option-data';
@Component({
selector: 'keypress-tab',
@@ -20,11 +20,10 @@ export class KeypressTabComponent extends Tab implements OnChanges {
leftModifierSelects: boolean[];
rightModifierSelects: boolean[];
scanCodeGroups: Array<Select2OptionData>;
secondaryRoleGroups: Array<Select2OptionData>;
options: Select2Options;
scanCodeGroups: Array<SelectOptionData>;
secondaryRoleGroups: Array<SelectOptionData>;
selectedScancodeOption: Select2OptionData;
selectedScancodeOption: SelectOptionData;
selectedSecondaryRoleIndex: number;
constructor(private mapper: MapperService) {
@@ -41,18 +40,6 @@ export class KeypressTabComponent extends Tab implements OnChanges {
this.rightModifierSelects = Array(this.rightModifiers.length).fill(false);
this.selectedScancodeOption = this.scanCodeGroups[0];
this.selectedSecondaryRoleIndex = -1;
this.options = {
templateResult: this.scanCodeTemplateResult,
matcher: (term: string, text: string, data: Select2OptionData) => {
let found = text.toUpperCase().indexOf(term.toUpperCase()) > -1;
if (!found && data.additional && data.additional.explanation) {
found = data.additional.explanation.toUpperCase().indexOf(term.toUpperCase()) > -1;
}
return found;
}
};
}
ngOnChanges() {
@@ -134,25 +121,6 @@ export class KeypressTabComponent extends Tab implements OnChanges {
}
}
scanCodeTemplateResult: Select2TemplateFunction = (state: Select2OptionData): JQuery | string => {
if (!state.id) {
return state.text;
}
if (state.additional && state.additional.explanation) {
return jQuery(
'<span class="select2-item">'
+ '<span>' + state.text + '</span>'
+ '<span class="scancode--searchterm"> '
+ state.additional.explanation
+ '</span>' +
'</span>'
);
} else {
return jQuery('<span class="select2-item">' + state.text + '</span>');
}
}
toggleModifier(right: boolean, index: number) {
const modifierSelects: boolean[] = right ? this.rightModifierSelects : this.leftModifierSelects;
modifierSelects[index] = !modifierSelects[index];
@@ -160,24 +128,20 @@ export class KeypressTabComponent extends Tab implements OnChanges {
this.validAction.emit(this.keyActionValid());
}
onSecondaryRoleChange(event: { value: string }) {
this.selectedSecondaryRoleIndex = +event.value;
onSecondaryRoleChange(id: string) {
this.selectedSecondaryRoleIndex = +id;
}
onScancodeChange(event: { value: string }) {
const id: string = event.value;
// ng2-select2 should provide the selectedOption in an upcoming release
// TODO: change this when it has become available
onScancodeChange(id: string) {
this.selectedScancodeOption = this.findScancodeOptionById(id);
this.validAction.emit(this.keyActionValid());
}
private findScancodeOptionBy(predicate: (option: Select2OptionData) => boolean): Select2OptionData {
let selectedOption: Select2OptionData;
private findScancodeOptionBy(predicate: (option: SelectOptionData) => boolean): SelectOptionData {
let selectedOption: SelectOptionData;
const scanCodeGroups: Select2OptionData[] = [...this.scanCodeGroups];
const scanCodeGroups: SelectOptionData[] = [...this.scanCodeGroups];
while (scanCodeGroups.length > 0) {
const scanCodeGroup = scanCodeGroups.shift();
if (predicate(scanCodeGroup)) {
@@ -192,14 +156,14 @@ export class KeypressTabComponent extends Tab implements OnChanges {
return selectedOption;
}
private findScancodeOptionById(id: string): Select2OptionData {
private findScancodeOptionById(id: string): SelectOptionData {
return this.findScancodeOptionBy(option => option.id === id);
}
private findScancodeOptionByScancode(scancode: number, type: KeystrokeType): Select2OptionData {
private findScancodeOptionByScancode(scancode: number, type: KeystrokeType): SelectOptionData {
const typeToFind: string =
(type === KeystrokeType.shortMedia || type === KeystrokeType.longMedia) ? 'media' : KeystrokeType[type];
return this.findScancodeOptionBy((option: Select2OptionData) => {
return this.findScancodeOptionBy((option: SelectOptionData) => {
const additional = option.additional;
if (additional && additional.scancode === scancode && additional.type === typeToFind) {
return true;
@@ -211,7 +175,7 @@ export class KeypressTabComponent extends Tab implements OnChanges {
});
}
private toScancodeTypePair(option: Select2OptionData): [number, string] {
private toScancodeTypePair(option: SelectOptionData): [number, string] {
let scanCode: number;
let type: string;
if (option.additional) {

View File

@@ -5,7 +5,23 @@
<p><i>Please note that macro playback is not implemented yet. You can bind macros, but they won't have any effect until firmware support is implemented. We're working on this.</i></p>
<div class="macro-selector">
<b> Play macro: </b>
<select2 [data]="macroOptions" [value]="macroOptions[selectedMacroIndex].id" (valueChanged)="onChange($event)" [width]="'100%'"></select2>
<ngx-select [items]="macroOptions"
[ngModel]="macroOptions[selectedMacroIndex].id"
[autoActiveOnMouseEnter]="false"
size="small"
optionValueField="id"
optionTextField="text"
(select)="onChange($event)">
<ng-template ngx-select-option let-option>
<span [ngClass]="{'indent-dropdown-item':option.data.id !== '-1'}">
<span>{{ option.text }}</span>
<span class="scancode--searchterm">
{{ option.data.additional?.explanation}}
</span>
</span>
</ng-template>
</ngx-select>
</div>
<div class="macro-action-container">
<div class="list-group">
@@ -14,4 +30,4 @@
</macro-item>
</div>
</div>
</ng-template>
</ng-template>

View File

@@ -16,7 +16,7 @@
margin-right: 7px;
}
select2 {
ngx-select {
flex: 1;
}
}

View File

@@ -1,13 +1,13 @@
import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Subscription } from 'rxjs/Subscription';
import { Select2OptionData } from 'ng2-select2/ng2-select2';
import { KeyAction, Macro, PlayMacroAction } from 'uhk-common';
import { Tab } from '../tab';
import { AppState } from '../../../../store/index';
import { AppState } from '../../../../store';
import { getMacros } from '../../../../store/reducers/user-configuration';
import { SelectOptionData } from '../../../../models/select-option-data';
@Component({
selector: 'macro-tab',
@@ -18,7 +18,7 @@ export class MacroTabComponent extends Tab implements OnInit, OnChanges, OnDestr
@Input() defaultKeyAction: KeyAction;
macros: Macro[];
macroOptions: Array<Select2OptionData>;
macroOptions: Array<SelectOptionData>;
selectedMacroIndex: number;
private subscription: Subscription;
@@ -31,7 +31,7 @@ export class MacroTabComponent extends Tab implements OnInit, OnChanges, OnDestr
}
ngOnInit() {
this.macroOptions = this.macros.map(function (macro: Macro, index: number): Select2OptionData {
this.macroOptions = this.macros.map(function (macro: Macro, index: number): SelectOptionData {
return {
id: index.toString(),
text: macro.name
@@ -44,9 +44,8 @@ export class MacroTabComponent extends Tab implements OnInit, OnChanges, OnDestr
this.validAction.emit(true);
}
// TODO: change to the correct type when the wrapper has added it.
onChange(event: any) {
this.selectedMacroIndex = +event.value;
onChange(id: string) {
this.selectedMacroIndex = +id;
}
keyActionValid(): boolean {

View File

@@ -1,3 +1,4 @@
///<reference path="../../../../node_modules/@types/jquery/index.d.ts"/>
import { AfterContentInit, Directive, ElementRef, HostBinding, Input, OnChanges, SimpleChanges } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

View File

@@ -0,0 +1,7 @@
export interface SelectOptionData {
id: string;
text: string;
disabled?: boolean;
children?: Array<SelectOptionData>;
additional?: any;
}

View File

@@ -6,7 +6,7 @@ import { NotifierModule } from 'angular-notifier';
import { ConfirmationPopoverModule } from 'angular-confirmation-popover';
import { DragulaModule } from 'ng2-dragula/ng2-dragula';
import { Select2Module } from 'ng2-select2/ng2-select2';
import { NgxSelectModule } from '@ert78gb/ngx-select-ex';
import { NouisliderModule } from 'ng2-nouislider';
import { ClipboardModule } from 'ngx-clipboard';
@@ -191,7 +191,7 @@ import { AutoGrowInputComponent } from './components/auto-grow-input';
FormsModule,
DragulaModule,
routing,
Select2Module,
NgxSelectModule,
NouisliderModule,
NotifierModule.withConfig(angularNotifierConfig),
ConfirmationPopoverModule.forRoot({

View File

@@ -5,6 +5,7 @@
@import './styles/tooltip';
@import './styles/uhk-icons/uhk-icon';
@import './styles/side-menu';
@import './styles/ngx-select-ex';
html, body {
width: 100%;
@@ -25,10 +26,6 @@ html, body {
transform: rotate(90deg); // svg not aligned properly
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 26px;
}
.main-content {
height: 100%;
}
@@ -39,34 +36,10 @@ html, body {
min-height: 100%;
}
.select2 {
&-container {
z-index: 1100;
.scancode--searchterm {
text-align: right;
color: #b7b7b7;
}
}
&-item {
display: flex;
justify-content: space-between;
}
&-results {
text-align: left;
}
}
.nav-pills > li > a {
cursor: pointer;
}
.select2-container--default .select2-dropdown--below .select2-results > .select2-results__options {
max-height: 300px;
}
ul.btn-list {
& li {
margin-top: 0.5em;

View File

@@ -0,0 +1,40 @@
ngx-select,
.ngx-select {
.ngx-select__toggle {
font-size: 14px;
}
.dropdown-header {
font-weight: bold;
font-size: 1em;
color: black;
padding-left: 6px;
}
.dropdown-divider {
display: none;
}
a {
&.ngx-select__item {
padding-right: 6px;
padding-left: 6px;
}
&.ngx-select__item_active {
background-color: #dddddd;
color: black;
}
}
.indent-dropdown-item {
padding-left: 8px;
display: flex;
justify-content: space-between;
.scancode--searchterm {
text-align: right;
color: #b7b7b7;
}
}
}