* Issue - 141 - Validate macro actions (#141) * review: refactor validation logic based on each macro tab component emitted event * review: mouse key macro invalid if any of the X, Y fields are empty * review: apply review comments for shorthand if conditions and imports
This commit is contained in:
committed by
László Monda
parent
ee93466a08
commit
c73ecdbde9
@@ -29,17 +29,17 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-lg-9 editor__tabs" [ngSwitch]="activeTab">
|
<div class="col-xs-12 col-lg-9 editor__tabs" [ngSwitch]="activeTab">
|
||||||
<macro-text-tab #tab *ngSwitchCase="TabName.Text" [macroAction]="editableMacroAction"></macro-text-tab>
|
<macro-text-tab #tab *ngSwitchCase="TabName.Text" [macroAction]="editableMacroAction" (valid)="onValid($event)"></macro-text-tab>
|
||||||
<macro-key-tab #tab *ngSwitchCase="TabName.Keypress" [macroAction]="editableMacroAction"></macro-key-tab>
|
<macro-key-tab #tab *ngSwitchCase="TabName.Keypress" [macroAction]="editableMacroAction" (valid)="onValid($event)"></macro-key-tab>
|
||||||
<macro-mouse-tab #tab *ngSwitchCase="TabName.Mouse" [macroAction]="editableMacroAction"></macro-mouse-tab>
|
<macro-mouse-tab #tab *ngSwitchCase="TabName.Mouse" [macroAction]="editableMacroAction" (valid)="onValid($event)"></macro-mouse-tab>
|
||||||
<macro-delay-tab #tab *ngSwitchCase="TabName.Delay" [macroAction]="editableMacroAction"></macro-delay-tab>
|
<macro-delay-tab #tab *ngSwitchCase="TabName.Delay" [macroAction]="editableMacroAction" (valid)="onValid($event)"></macro-delay-tab>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 flex-button-wrapper editor__actions-container">
|
<div class="col-xs-12 flex-button-wrapper editor__actions-container">
|
||||||
<div class="editor__actions">
|
<div class="editor__actions">
|
||||||
<button class="btn btn-sm btn-default flex-button" type="button" (click)="onCancelClick()"> Cancel </button>
|
<button class="btn btn-sm btn-default flex-button" type="button" (click)="onCancelClick()"> Cancel </button>
|
||||||
<button class="btn btn-sm btn-primary flex-button" type="button" (click)="onSaveClick()"> Save </button>
|
<button class="btn btn-sm btn-primary flex-button" type="button" (click)="onSaveClick()" [disabled]="!isSelectedMacroValid"> Save </button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export class MacroActionEditorComponent implements OnInit {
|
|||||||
/* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */
|
/* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */
|
||||||
TabName = TabName;
|
TabName = TabName;
|
||||||
/* tslint:enable:variable-name */
|
/* tslint:enable:variable-name */
|
||||||
|
isSelectedMacroValid = false;
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.updateEditableMacroAction();
|
this.updateEditableMacroAction();
|
||||||
@@ -66,12 +67,15 @@ export class MacroActionEditorComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onValid = (isMacroValid: boolean) => this.isSelectedMacroValid = isMacroValid;
|
||||||
|
|
||||||
selectTab(tab: TabName): void {
|
selectTab(tab: TabName): void {
|
||||||
this.activeTab = tab;
|
this.activeTab = tab;
|
||||||
if (tab === this.getTabName(this.macroAction)) {
|
if (tab === this.getTabName(this.macroAction)) {
|
||||||
this.updateEditableMacroAction();
|
this.updateEditableMacroAction();
|
||||||
} else {
|
} else {
|
||||||
this.editableMacroAction = undefined;
|
this.editableMacroAction = undefined;
|
||||||
|
this.isSelectedMacroValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
step="0.1"
|
step="0.1"
|
||||||
placeholder="Delay amount"
|
placeholder="Delay amount"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
[attr.value]="delay"
|
[value]="delay"
|
||||||
(change)="setDelay($event)">
|
(change)="setDelay(macroDelayInput.value)">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row macro-delay__presets">
|
<div class="row macro-delay__presets">
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { DelayMacroAction } from '../../../../../config-serializer/config-items/macro-action';
|
import { DelayMacroAction } from '../../../../../config-serializer/config-items/macro-action';
|
||||||
|
import { MacroBaseComponent } from '../macro-base.component';
|
||||||
|
|
||||||
const INITIAL_DELAY = 0.5; // In seconds
|
const INITIAL_DELAY = 0.5; // In seconds
|
||||||
|
|
||||||
@@ -18,24 +19,29 @@ const INITIAL_DELAY = 0.5; // In seconds
|
|||||||
host: { 'class': 'macro__delay' },
|
host: { 'class': 'macro__delay' },
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class MacroDelayTabComponent implements OnInit {
|
export class MacroDelayTabComponent extends MacroBaseComponent implements OnInit {
|
||||||
@Input() macroAction: DelayMacroAction;
|
@Input() macroAction: DelayMacroAction;
|
||||||
@ViewChild('macroDelayInput') input: ElementRef;
|
@ViewChild('macroDelayInput') input: ElementRef;
|
||||||
|
|
||||||
delay: number;
|
delay: number;
|
||||||
presets: number[] = [0.3, 0.5, 0.8, 1, 2, 3, 4, 5];
|
presets: number[] = [0.3, 0.5, 0.8, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
constructor() { }
|
constructor() { super(); }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (!this.macroAction) {
|
if (!this.macroAction) {
|
||||||
this.macroAction = new DelayMacroAction();
|
this.macroAction = new DelayMacroAction();
|
||||||
}
|
}
|
||||||
this.delay = this.macroAction.delay > 0 ? this.macroAction.delay / 1000 : INITIAL_DELAY;
|
this.delay = this.macroAction.delay > 0 ? this.macroAction.delay / 1000 : INITIAL_DELAY;
|
||||||
|
this.validate(); // initial validation as it has defaults
|
||||||
}
|
}
|
||||||
|
|
||||||
setDelay(value: number): void {
|
setDelay(value: number): void {
|
||||||
this.delay = value;
|
this.delay = value;
|
||||||
this.macroAction.delay = this.delay * 1000;
|
this.macroAction.delay = this.delay * 1000;
|
||||||
|
this.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMacroValid = () => this.macroAction.delay !== 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ export { MacroDelayTabComponent } from './delay';
|
|||||||
export { MacroKeyTabComponent } from './key';
|
export { MacroKeyTabComponent } from './key';
|
||||||
export { MacroMouseTabComponent } from './mouse';
|
export { MacroMouseTabComponent } from './mouse';
|
||||||
export { MacroTextTabComponent } from './text';
|
export { MacroTextTabComponent } from './text';
|
||||||
|
export { MacroBaseComponent } from './macro-base.component';
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<h4 *ngIf="activeTab === TabName.Keypress">Press key</h4>
|
<h4 *ngIf="activeTab === TabName.Keypress">Press key</h4>
|
||||||
<h4 *ngIf="activeTab === TabName.Hold">Hold key</h4>
|
<h4 *ngIf="activeTab === TabName.Hold">Hold key</h4>
|
||||||
<h4 *ngIf="activeTab === TabName.Release">Release key</h4>
|
<h4 *ngIf="activeTab === TabName.Release">Release key</h4>
|
||||||
<keypress-tab #keypressTab [defaultKeyAction]="defaultKeyAction" [longPressEnabled]="false"></keypress-tab>
|
<keypress-tab #keypressTab [defaultKeyAction]="defaultKeyAction" [longPressEnabled]="false" (validAction)="validate()"></keypress-tab>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -3,6 +3,7 @@ import { Component, Input, OnInit, ViewChild } from '@angular/core';
|
|||||||
import { KeystrokeAction } from '../../../../../config-serializer/config-items/key-action';
|
import { KeystrokeAction } from '../../../../../config-serializer/config-items/key-action';
|
||||||
import { KeyMacroAction, MacroSubAction } from '../../../../../config-serializer/config-items/macro-action';
|
import { KeyMacroAction, MacroSubAction } from '../../../../../config-serializer/config-items/macro-action';
|
||||||
import { KeypressTabComponent, Tab } from '../../../../popover/tab';
|
import { KeypressTabComponent, Tab } from '../../../../popover/tab';
|
||||||
|
import { MacroBaseComponent } from '../macro-base.component';
|
||||||
|
|
||||||
enum TabName {
|
enum TabName {
|
||||||
Keypress,
|
Keypress,
|
||||||
@@ -19,7 +20,7 @@ enum TabName {
|
|||||||
],
|
],
|
||||||
host: { 'class': 'macro__mouse' }
|
host: { 'class': 'macro__mouse' }
|
||||||
})
|
})
|
||||||
export class MacroKeyTabComponent implements OnInit {
|
export class MacroKeyTabComponent extends MacroBaseComponent implements OnInit {
|
||||||
@Input() macroAction: KeyMacroAction;
|
@Input() macroAction: KeyMacroAction;
|
||||||
@ViewChild('tab') selectedTab: Tab;
|
@ViewChild('tab') selectedTab: Tab;
|
||||||
@ViewChild('keypressTab') keypressTab: KeypressTabComponent;
|
@ViewChild('keypressTab') keypressTab: KeypressTabComponent;
|
||||||
@@ -40,6 +41,7 @@ export class MacroKeyTabComponent implements OnInit {
|
|||||||
|
|
||||||
selectTab(tab: TabName): void {
|
selectTab(tab: TabName): void {
|
||||||
this.activeTab = tab;
|
this.activeTab = tab;
|
||||||
|
this.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
getTabName(macroAction: KeyMacroAction): TabName {
|
getTabName(macroAction: KeyMacroAction): TabName {
|
||||||
@@ -71,4 +73,9 @@ export class MacroKeyTabComponent implements OnInit {
|
|||||||
return keyMacroAction;
|
return keyMacroAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMacroValid = () => {
|
||||||
|
const keyMacroAction = this.getKeyMacroAction();
|
||||||
|
return !!keyMacroAction.scancode || !!keyMacroAction.modifierMask;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { Output, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
|
export interface MacroValidator {
|
||||||
|
isMacroValid: () => boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class MacroBaseComponent implements MacroValidator {
|
||||||
|
|
||||||
|
@Output() valid = new EventEmitter<boolean>();
|
||||||
|
abstract isMacroValid: () => boolean;
|
||||||
|
|
||||||
|
validate = () => this.valid.emit(this.isMacroValid());
|
||||||
|
|
||||||
|
}
|
||||||
@@ -40,11 +40,11 @@
|
|||||||
<div class="form-horizontal">
|
<div class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="move-mouse-x">X</label>
|
<label for="move-mouse-x">X</label>
|
||||||
<input id="move-mouse-x" type="number" class="form-control" [(ngModel)]="macroAction['x']"> pixels
|
<input id="move-mouse-x" type="number" class="form-control" [(ngModel)]="macroAction['x']" (keyup)="validate()"> pixels
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="move-mouse-y">Y</label>
|
<label for="move-mouse-y">Y</label>
|
||||||
<input id="move-mouse-y" type="number" class="form-control" [(ngModel)]="macroAction['y']"> pixels
|
<input id="move-mouse-y" type="number" class="form-control" [(ngModel)]="macroAction['y']" (keyup)="validate()"> pixels
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,11 +54,11 @@
|
|||||||
<div class="form-horizontal">
|
<div class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="scroll-mouse-x">X</label>
|
<label for="scroll-mouse-x">X</label>
|
||||||
<input id="scroll-mouse-x" type="number" class="form-control" [(ngModel)]="macroAction['x']"> pixels
|
<input id="scroll-mouse-x" type="number" class="form-control" [(ngModel)]="macroAction['x']" (keyup)="validate()"> pixels
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="scroll-mouse-y">Y</label>
|
<label for="scroll-mouse-y">Y</label>
|
||||||
<input id="scroll-mouse-y" type="number" class="form-control" [(ngModel)]="macroAction['y']"> pixels
|
<input id="scroll-mouse-y" type="number" class="form-control" [(ngModel)]="macroAction['y']" (keyup)="validate()"> pixels
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
MacroSubAction
|
MacroSubAction
|
||||||
} from '../../../../../config-serializer/config-items/macro-action';
|
} from '../../../../../config-serializer/config-items/macro-action';
|
||||||
import { Tab } from '../../../../popover/tab';
|
import { Tab } from '../../../../popover/tab';
|
||||||
|
import { MacroBaseComponent } from '../macro-base.component';
|
||||||
|
|
||||||
type MouseMacroAction = MouseButtonMacroAction | MoveMouseMacroAction | ScrollMouseMacroAction;
|
type MouseMacroAction = MouseButtonMacroAction | MoveMouseMacroAction | ScrollMouseMacroAction;
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ enum TabName {
|
|||||||
],
|
],
|
||||||
host: { 'class': 'macro__mouse' }
|
host: { 'class': 'macro__mouse' }
|
||||||
})
|
})
|
||||||
export class MacroMouseTabComponent implements OnInit {
|
export class MacroMouseTabComponent extends MacroBaseComponent implements OnInit {
|
||||||
@Input() macroAction: MouseMacroAction;
|
@Input() macroAction: MouseMacroAction;
|
||||||
@ViewChild('tab') selectedTab: Tab;
|
@ViewChild('tab') selectedTab: Tab;
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ export class MacroMouseTabComponent implements OnInit {
|
|||||||
private selectedButtons: boolean[];
|
private selectedButtons: boolean[];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
super();
|
||||||
this.buttonLabels = ['Left', 'Middle', 'Right'];
|
this.buttonLabels = ['Left', 'Middle', 'Right'];
|
||||||
this.selectedButtons = Array(this.buttonLabels.length).fill(false);
|
this.selectedButtons = Array(this.buttonLabels.length).fill(false);
|
||||||
}
|
}
|
||||||
@@ -65,6 +67,8 @@ export class MacroMouseTabComponent implements OnInit {
|
|||||||
|
|
||||||
if (tab === this.getTabName(this.macroAction)) {
|
if (tab === this.getTabName(this.macroAction)) {
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
this.selectedButtons = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tab) {
|
switch (tab) {
|
||||||
@@ -79,11 +83,13 @@ export class MacroMouseTabComponent implements OnInit {
|
|||||||
this.macroAction.action = this.getAction(tab);
|
this.macroAction.action = this.getAction(tab);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
this.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
setMouseClick(index: number): void {
|
setMouseClick(index: number): void {
|
||||||
this.selectedButtons[index] = !this.selectedButtons[index];
|
this.selectedButtons[index] = !this.selectedButtons[index];
|
||||||
(<MouseButtonMacroAction>this.macroAction).setMouseButtons(this.selectedButtons);
|
(<MouseButtonMacroAction>this.macroAction).setMouseButtons(this.selectedButtons);
|
||||||
|
this.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
hasButton(index: number): boolean {
|
hasButton(index: number): boolean {
|
||||||
@@ -120,4 +126,18 @@ export class MacroMouseTabComponent implements OnInit {
|
|||||||
return TabName.Move;
|
return TabName.Move;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMacroValid = () => {
|
||||||
|
switch (this.macroAction.constructor) {
|
||||||
|
case MoveMouseMacroAction:
|
||||||
|
case ScrollMouseMacroAction:
|
||||||
|
const { x, y } = this.macroAction as MoveMouseMacroAction;
|
||||||
|
return x !== undefined && x !== null && y !== undefined && y !== null;
|
||||||
|
case MouseButtonMacroAction:
|
||||||
|
const { mouseButtonsMask } = this.macroAction as MouseButtonMacroAction;
|
||||||
|
return !!mouseButtonsMask;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<div>
|
<div>
|
||||||
<h4>Type text</h4>
|
<h4>Type text</h4>
|
||||||
<p>Input the text you want to type with this macro action.</p>
|
<p>Input the text you want to type with this macro action.</p>
|
||||||
<textarea #macroTextInput name="macro-text" (change)="onTextChange()" class="macro__text-input">{{ macroAction.text }}</textarea>
|
<textarea #macroTextInput name="macro-text" (change)="onTextChange()"
|
||||||
|
(keyup)="validate()" class="macro__text-input">{{ macroAction?.text }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { TextMacroAction } from '../../../../../config-serializer/config-items/macro-action';
|
import { TextMacroAction } from '../../../../../config-serializer/config-items/macro-action';
|
||||||
|
import { MacroBaseComponent } from '../macro-base.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'macro-text-tab',
|
selector: 'macro-text-tab',
|
||||||
@@ -16,16 +17,14 @@ import { TextMacroAction } from '../../../../../config-serializer/config-items/m
|
|||||||
styleUrls: ['./macro-text.component.scss'],
|
styleUrls: ['./macro-text.component.scss'],
|
||||||
host: { 'class': 'macro__text' }
|
host: { 'class': 'macro__text' }
|
||||||
})
|
})
|
||||||
export class MacroTextTabComponent implements OnInit, AfterViewInit {
|
export class MacroTextTabComponent extends MacroBaseComponent implements OnInit, AfterViewInit {
|
||||||
@Input() macroAction: TextMacroAction;
|
@Input() macroAction: TextMacroAction;
|
||||||
@ViewChild('macroTextInput') input: ElementRef;
|
@ViewChild('macroTextInput') input: ElementRef;
|
||||||
|
|
||||||
constructor(private renderer: Renderer) {}
|
constructor(private renderer: Renderer) { super(); }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (!this.macroAction) {
|
this.init();
|
||||||
this.macroAction = new TextMacroAction();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
@@ -33,7 +32,16 @@ export class MacroTextTabComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onTextChange() {
|
onTextChange() {
|
||||||
|
this.init();
|
||||||
this.macroAction.text = this.input.nativeElement.value;
|
this.macroAction.text = this.input.nativeElement.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMacroValid = () => !!this.input.nativeElement.value;
|
||||||
|
|
||||||
|
private init = () => {
|
||||||
|
if (!this.macroAction) {
|
||||||
|
this.macroAction = new TextMacroAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user