From 02d57fdabf7094a0b93c27aa7a67051214588922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Kiss?= Date: Mon, 29 Jan 2018 22:54:29 +0100 Subject: [PATCH] feat(keymap): add description to keymap (#559) * feat(keymap): add description to keymaps * add new feature request * preserve new lines --- .../editable-text.component.html | 31 +++++++ .../editable-text.component.scss | 26 ++++++ .../editable-text/editable-text.component.ts | 82 +++++++++++++++++++ .../slider/keyboard-slider.component.html | 2 + .../slider/keyboard-slider.component.ts | 5 +- .../keymap/edit/keymap-edit.component.html | 3 +- .../keymap/edit/keymap-edit.component.ts | 8 +- .../svg/keyboard/svg-keyboard.component.html | 27 +++--- .../svg/keyboard/svg-keyboard.component.scss | 7 +- .../svg/keyboard/svg-keyboard.component.ts | 2 + .../svg/wrap/svg-keyboard-wrap.component.html | 2 + .../svg/wrap/svg-keyboard-wrap.component.ts | 19 ++++- .../autofocus/autofocus.directive.ts | 16 ++++ .../src/app/models/ChangeKeymapDescription.ts | 4 + packages/uhk-web/src/app/shared.module.ts | 6 +- .../uhk-web/src/app/store/actions/keymap.ts | 14 +++- .../src/app/store/effects/user-config.ts | 2 +- .../uhk-web/src/app/store/reducers/preset.ts | 2 +- .../app/store/reducers/user-configuration.ts | 12 +++ 19 files changed, 246 insertions(+), 24 deletions(-) create mode 100644 packages/uhk-web/src/app/components/editable-text/editable-text.component.html create mode 100644 packages/uhk-web/src/app/components/editable-text/editable-text.component.scss create mode 100644 packages/uhk-web/src/app/components/editable-text/editable-text.component.ts create mode 100644 packages/uhk-web/src/app/directives/autofocus/autofocus.directive.ts create mode 100644 packages/uhk-web/src/app/models/ChangeKeymapDescription.ts diff --git a/packages/uhk-web/src/app/components/editable-text/editable-text.component.html b/packages/uhk-web/src/app/components/editable-text/editable-text.component.html new file mode 100644 index 00000000..cacf7a4c --- /dev/null +++ b/packages/uhk-web/src/app/components/editable-text/editable-text.component.html @@ -0,0 +1,31 @@ +
+ + {{ placeholder }} + + + + + +
+ +
+ +
+ + +
+
diff --git a/packages/uhk-web/src/app/components/editable-text/editable-text.component.scss b/packages/uhk-web/src/app/components/editable-text/editable-text.component.scss new file mode 100644 index 00000000..348cea73 --- /dev/null +++ b/packages/uhk-web/src/app/components/editable-text/editable-text.component.scss @@ -0,0 +1,26 @@ +:host { + margin-top: 0.5em; + + span.placeholder { + color: gray; + display: inline-block; + + .glyphicon { + color: black; + } + } + + span.editable, + span.placeholder { + cursor: pointer; + } + + textarea.text-editor { + display: block; + width: 100%; + } + + .buttons { + margin-top: 0.5em; + } +} diff --git a/packages/uhk-web/src/app/components/editable-text/editable-text.component.ts b/packages/uhk-web/src/app/components/editable-text/editable-text.component.ts new file mode 100644 index 00000000..bff9f9ad --- /dev/null +++ b/packages/uhk-web/src/app/components/editable-text/editable-text.component.ts @@ -0,0 +1,82 @@ +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, Input } from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; + +@Component({ + selector: 'editable-text', + templateUrl: './editable-text.component.html', + styleUrls: ['./editable-text.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + {provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => EditableTextComponent), multi: true} + ] +}) +export class EditableTextComponent implements ControlValueAccessor { + + @Input() placeholder = 'No editable content'; + text: string; + originalText: string; + editing = false; + + get isSaveDisabled(): boolean { + return !this.text || this.text.trim().length === 0; + } + + get displayText(): string { + return this.text && this.text.replace(/\n/g, '
'); + } + + constructor(private cdr: ChangeDetectorRef) { + + } + + writeValue(obj: any): void { + if (this.text === obj) { + return; + } + + this.text = obj; + this.cdr.markForCheck(); + } + + registerOnChange(fn: any): void { + this.textChange = fn; + } + + registerOnTouched(fn: any): void { + } + + saveText(): void { + this.originalText = null; + this.editing = false; + this.textChange(this.text); + } + + editText(): void { + this.originalText = this.text; + this.editing = true; + } + + cancelEditText(): void { + this.text = this.originalText; + this.editing = false; + } + + keydownEnter(): void { + if (this.isSaveDisabled) { + return; + } + + this.saveText(); + } + + get showPlaceholder(): boolean { + return !this.editing && !this.text; + } + + get showText(): boolean { + return !this.editing && !!this.text; + } + + private textChange: any = () => { + } +} diff --git a/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.html b/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.html index 1817459f..87b2279a 100644 --- a/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.html +++ b/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.html @@ -7,8 +7,10 @@ [selectedKey]="selectedKey" [selected]="selectedKey?.layerId === index" [keyboardLayout]="keyboardLayout" + [description]="description" (keyClick)="keyClick.emit($event)" (keyHover)="keyHover.emit($event)" (capture)="capture.emit($event)" + (descriptionChanged)="descriptionChanged.emit($event)" > diff --git a/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.ts b/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.ts index 889127d6..ed590348 100644 --- a/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.ts +++ b/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.ts @@ -1,4 +1,4 @@ -import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; import { animate, keyframes, state, style, transition, trigger } from '@angular/animations'; import { Layer } from 'uhk-common'; @@ -81,11 +81,14 @@ export class KeyboardSliderComponent implements OnChanges { @Input() halvesSplit: boolean; @Input() selectedKey: { layerId: number, moduleId: number, keyId: number }; @Input() keyboardLayout = KeyboardLayout.ANSI; + @Input() description: string; @Output() keyClick = new EventEmitter(); @Output() keyHover = new EventEmitter(); @Output() capture = new EventEmitter(); + @Output() descriptionChanged = new EventEmitter(); layerAnimationState: AnimationKeyboard[]; + ngOnChanges(changes: SimpleChanges) { if (changes['layers']) { this.layerAnimationState = this.layers.map(() => 'initOut'); diff --git a/packages/uhk-web/src/app/components/keymap/edit/keymap-edit.component.html b/packages/uhk-web/src/app/components/keymap/edit/keymap-edit.component.html index 2ca36ac2..8a5487ae 100644 --- a/packages/uhk-web/src/app/components/keymap/edit/keymap-edit.component.html +++ b/packages/uhk-web/src/app/components/keymap/edit/keymap-edit.component.html @@ -4,7 +4,8 @@ (downloadClick)="downloadKeymap()"> + [keyboardLayout]="keyboardLayout$ | async" + (descriptionChanged)="descriptionChanged($event)">
diff --git a/packages/uhk-web/src/app/components/keymap/edit/keymap-edit.component.ts b/packages/uhk-web/src/app/components/keymap/edit/keymap-edit.component.ts index b6c252f1..e03d5858 100644 --- a/packages/uhk-web/src/app/components/keymap/edit/keymap-edit.component.ts +++ b/packages/uhk-web/src/app/components/keymap/edit/keymap-edit.component.ts @@ -18,6 +18,8 @@ import { AppState, getKeyboardLayout } from '../../../store'; import { getKeymap, getKeymaps, getUserConfiguration } from '../../../store/reducers/user-configuration'; import { SvgKeyboardWrapComponent } from '../../svg/wrap'; import { KeyboardLayout } from '../../../keyboard/keyboard-layout.enum'; +import { KeymapActions } from '../../../store/actions'; +import { ChangeKeymapDescription } from '../../../models/ChangeKeymapDescription'; @Component({ selector: 'keymap-edit', @@ -64,7 +66,7 @@ export class KeymapEditComponent { const keymap = latest[0]; const exportableJSON = latest[1]; const fileName = keymap.name + '_keymap.json'; - saveAs(new Blob([exportableJSON], { type: 'application/json' }), fileName); + saveAs(new Blob([exportableJSON], {type: 'application/json'}), fileName); }); } @@ -73,6 +75,10 @@ export class KeymapEditComponent { this.keyboardSplit = !this.keyboardSplit; } + descriptionChanged(event: ChangeKeymapDescription): void { + this.store.dispatch(new KeymapActions.EditDescriptionAction(event)); + } + private toExportableJSON(keymap: Keymap): Observable { return this.store .let(getUserConfiguration()) diff --git a/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.html b/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.html index 4388195f..ffd3c0bf 100644 --- a/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.html +++ b/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.html @@ -1,16 +1,19 @@ + diff --git a/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.scss b/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.scss index 78c410a3..4cec8da7 100644 --- a/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.scss +++ b/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.scss @@ -1,5 +1,10 @@ :host { - display: flex; + display: block; width: 100%; position: relative; } +editable-text { + padding-left: 2em; + padding-right: 2em; + display: block; +} diff --git a/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.ts b/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.ts index cace0d08..f74e0dd2 100644 --- a/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.ts +++ b/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.ts @@ -31,9 +31,11 @@ export class SvgKeyboardComponent implements OnInit { @Input() selected: boolean; @Input() halvesSplit: boolean; @Input() keyboardLayout = KeyboardLayout.ANSI; + @Input() description: string; @Output() keyClick = new EventEmitter(); @Output() keyHover = new EventEmitter(); @Output() capture = new EventEmitter(); + @Output() descriptionChanged = new EventEmitter(); modules: SvgModule[]; viewBox: string; diff --git a/packages/uhk-web/src/app/components/svg/wrap/svg-keyboard-wrap.component.html b/packages/uhk-web/src/app/components/svg/wrap/svg-keyboard-wrap.component.html index e6289c7a..a04dcdb9 100644 --- a/packages/uhk-web/src/app/components/svg/wrap/svg-keyboard-wrap.component.html +++ b/packages/uhk-web/src/app/components/svg/wrap/svg-keyboard-wrap.component.html @@ -7,9 +7,11 @@ [selectedKey]="selectedKey" [halvesSplit]="halvesSplit" [keyboardLayout]="keyboardLayout" + [description]="keymap.description" (keyClick)="onKeyClick($event.moduleId, $event.keyId, $event.keyTarget)" (keyHover)="onKeyHover($event.moduleId, $event.event, $event.over, $event.keyId)" (capture)="onCapture($event.moduleId, $event.keyId, $event.captured)" + (descriptionChanged)="onDescriptionChanged($event)" > diff --git a/packages/uhk-web/src/app/components/svg/wrap/svg-keyboard-wrap.component.ts b/packages/uhk-web/src/app/components/svg/wrap/svg-keyboard-wrap.component.ts index 2e20c48e..eda56268 100644 --- a/packages/uhk-web/src/app/components/svg/wrap/svg-keyboard-wrap.component.ts +++ b/packages/uhk-web/src/app/components/svg/wrap/svg-keyboard-wrap.component.ts @@ -2,14 +2,16 @@ import { ChangeDetectionStrategy, Component, ElementRef, - Renderer, + EventEmitter, HostBinding, HostListener, Input, OnChanges, OnInit, - ViewChild, - SimpleChanges + Output, + Renderer, + SimpleChanges, + ViewChild } from '@angular/core'; import { Observable } from 'rxjs/Observable'; @@ -25,10 +27,10 @@ import { KeystrokeAction, Layer, LayerName, - SecondaryRoleAction, MouseAction, MouseActionParam, PlayMacroAction, + SecondaryRoleAction, SwitchKeymapAction, SwitchLayerAction } from 'uhk-common'; @@ -38,6 +40,7 @@ import { AppState } from '../../../store'; import { KeymapActions } from '../../../store/actions'; import { PopoverComponent } from '../../popover'; import { KeyboardLayout } from '../../../keyboard/keyboard-layout.enum'; +import { ChangeKeymapDescription } from '../../../models/ChangeKeymapDescription'; interface NameValuePair { name: string; @@ -56,6 +59,7 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges { @Input() tooltipEnabled: boolean = false; @Input() halvesSplit: boolean; @Input() keyboardLayout: KeyboardLayout.ANSI; + @Output() descriptionChanged = new EventEmitter(); @ViewChild(PopoverComponent, { read: ElementRef }) popover: ElementRef; @@ -237,6 +241,13 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges { return this.currentLayer; } + onDescriptionChanged(description: string): void { + this.descriptionChanged.emit({ + description, + abbr: this.keymap.abbreviation + }); + } + private getKeyActionContent(keyAction: KeyAction): Observable { if (keyAction instanceof KeystrokeAction) { const keystrokeAction: KeystrokeAction = keyAction; diff --git a/packages/uhk-web/src/app/directives/autofocus/autofocus.directive.ts b/packages/uhk-web/src/app/directives/autofocus/autofocus.directive.ts new file mode 100644 index 00000000..25d62019 --- /dev/null +++ b/packages/uhk-web/src/app/directives/autofocus/autofocus.directive.ts @@ -0,0 +1,16 @@ +import { AfterViewInit, Directive, ElementRef } from '@angular/core'; + +@Directive({ + selector: '[autofocus]' +}) +export class Autofocus implements AfterViewInit { + constructor(private el: ElementRef) { + } + + ngOnInit() { + } + + ngAfterViewInit() { + this.el.nativeElement.focus(); + } +} diff --git a/packages/uhk-web/src/app/models/ChangeKeymapDescription.ts b/packages/uhk-web/src/app/models/ChangeKeymapDescription.ts new file mode 100644 index 00000000..3ba444f0 --- /dev/null +++ b/packages/uhk-web/src/app/models/ChangeKeymapDescription.ts @@ -0,0 +1,4 @@ +export interface ChangeKeymapDescription { + abbr: string; + description: string; +} diff --git a/packages/uhk-web/src/app/shared.module.ts b/packages/uhk-web/src/app/shared.module.ts index eb101e23..b9e7d25f 100644 --- a/packages/uhk-web/src/app/shared.module.ts +++ b/packages/uhk-web/src/app/shared.module.ts @@ -101,6 +101,8 @@ import { UhkDeviceLoadingGuard } from './services/uhk-device-loading.guard'; import { UhkDeviceLoadedGuard } from './services/uhk-device-loaded.guard'; import { XtermComponent } from './components/xterm/xterm.component'; import { SliderWrapperComponent } from './components/slider-wrapper/slider-wrapper.component'; +import { EditableTextComponent } from './components/editable-text/editable-text.component'; +import { Autofocus } from './directives/autofocus/autofocus.directive'; @NgModule({ declarations: [ @@ -169,7 +171,9 @@ import { SliderWrapperComponent } from './components/slider-wrapper/slider-wrapp ProgressButtonComponent, LoadingDevicePageComponent, XtermComponent, - SliderWrapperComponent + SliderWrapperComponent, + EditableTextComponent, + Autofocus ], imports: [ CommonModule, diff --git a/packages/uhk-web/src/app/store/actions/keymap.ts b/packages/uhk-web/src/app/store/actions/keymap.ts index f8d2f1d3..557467a4 100644 --- a/packages/uhk-web/src/app/store/actions/keymap.ts +++ b/packages/uhk-web/src/app/store/actions/keymap.ts @@ -1,6 +1,7 @@ import { Action } from '@ngrx/store'; import { KeyAction, Keymap, Macro } from 'uhk-common'; import { UndoUserConfigData } from '../../models/undo-user-config-data'; +import { ChangeKeymapDescription } from '../../models/ChangeKeymapDescription'; export type KeymapAction = KeymapActions.AddKeymapAction | @@ -11,7 +12,8 @@ export type KeymapAction = KeymapActions.SetDefaultAction | KeymapActions.RemoveKeymapAction | KeymapActions.SaveKeyAction | - KeymapActions.CheckMacroAction; + KeymapActions.CheckMacroAction | + KeymapActions.EditDescriptionAction; export namespace KeymapActions { export const ADD = '[Keymap] Add keymap'; @@ -98,6 +100,16 @@ export namespace KeymapActions { payload: UndoUserConfigData }; + export const EDIT_DESCRIPTION = '[Keymap] Edit description'; + + export class EditDescriptionAction { + type = EDIT_DESCRIPTION; + + constructor(public payload: ChangeKeymapDescription) { + + } + } + export function loadKeymaps(): Action { return { type: KeymapActions.LOAD_KEYMAPS diff --git a/packages/uhk-web/src/app/store/effects/user-config.ts b/packages/uhk-web/src/app/store/effects/user-config.ts index b4ee416d..c8809412 100644 --- a/packages/uhk-web/src/app/store/effects/user-config.ts +++ b/packages/uhk-web/src/app/store/effects/user-config.ts @@ -81,7 +81,7 @@ export class UserConfigEffects { @Effect() saveUserConfig$: Observable = (this.actions$ .ofType( KeymapActions.ADD, KeymapActions.DUPLICATE, KeymapActions.EDIT_NAME, KeymapActions.EDIT_ABBR, - KeymapActions.SET_DEFAULT, KeymapActions.REMOVE, KeymapActions.SAVE_KEY, + KeymapActions.SET_DEFAULT, KeymapActions.REMOVE, KeymapActions.SAVE_KEY, KeymapActions.EDIT_DESCRIPTION, MacroActions.ADD, MacroActions.DUPLICATE, MacroActions.EDIT_NAME, MacroActions.REMOVE, MacroActions.ADD_ACTION, MacroActions.SAVE_ACTION, MacroActions.DELETE_ACTION, MacroActions.REORDER_ACTION, ActionTypes.RENAME_USER_CONFIGURATION, ActionTypes.SET_USER_CONFIGURATION_VALUE) as diff --git a/packages/uhk-web/src/app/store/reducers/preset.ts b/packages/uhk-web/src/app/store/reducers/preset.ts index d89efa58..5e1180ac 100644 --- a/packages/uhk-web/src/app/store/reducers/preset.ts +++ b/packages/uhk-web/src/app/store/reducers/preset.ts @@ -7,7 +7,7 @@ export const initialState: Keymap[] = []; export function reducer(state = initialState, action: KeymapAction): Keymap[] { switch (action.type) { case KeymapActions.LOAD_KEYMAPS_SUCCESS: { - return action.payload; + return (action as KeymapActions.LoadKeymapSuccessAction).payload ; } default: diff --git a/packages/uhk-web/src/app/store/reducers/user-configuration.ts b/packages/uhk-web/src/app/store/reducers/user-configuration.ts index 6afe11a8..d8a8e9e3 100644 --- a/packages/uhk-web/src/app/store/reducers/user-configuration.ts +++ b/packages/uhk-web/src/app/store/reducers/user-configuration.ts @@ -263,6 +263,18 @@ export function reducer(state = initialState, action: Action & { payload?: any } break; } + case KeymapActions.EDIT_DESCRIPTION: { + const data = (action as KeymapActions.EditDescriptionAction).payload; + + changedUserConfiguration.keymaps = state.keymaps.map(keymap => { + if (keymap.abbreviation === data.abbr) { + keymap.description = data.description; + } + return keymap; + }); + break; + } + default: break; }