diff --git a/.gitignore b/.gitignore index 59218d55..a319be88 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ npm-debug.log dist .idea *.iml +*.sublime-project +*.sublime-workspace diff --git a/package.json b/package.json index 4e076518..4d31b0dd 100644 --- a/package.json +++ b/package.json @@ -36,16 +36,19 @@ "@angular/common": "2.0.0-rc.6", "@angular/compiler": "2.0.0-rc.6", "@angular/core": "2.0.0-rc.6", + "@angular/forms": "2.0.0-rc.6", "@angular/platform-browser": "2.0.0-rc.6", "@angular/platform-browser-dynamic": "2.0.0-rc.6", "@angular/router": "3.0.0-rc.2", "bootstrap": "^3.3.7", "browser-stdout": "^1.3.0", "core-js": "2.4.1", + "dragula": "^3.7.1", "font-awesome": "^4.6.3", "handlebars": "^4.0.5", "jquery": "3.1.0", "json-loader": "^0.5.4", + "ng2-dragula": "^1.2.0", "ng2-select2": "0.4.2", "rxjs": "5.0.0-beta.11", "select2": "^4.0.3", diff --git a/src/app.module.ts b/src/app.module.ts index cc5004d9..6022dd55 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,14 +1,24 @@ import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; +import { DragulaModule } from 'ng2-dragula/ng2-dragula'; import { Select2Component } from 'ng2-select2/ng2-select2'; -import { MainAppComponent, appRoutingProviders, routing } from './main-app'; +import { ContenteditableDirective } from './directives/contenteditable'; import { KeymapAddComponent, KeymapComponent } from './components/keymap'; import { LayersComponent } from './components/layers'; import { LegacyLoaderComponent } from './components/legacy-loader'; -import { MacroComponent } from './components/macro'; +import { + MacroActionEditorComponent, + MacroComponent, + MacroDelayTabComponent, + MacroItemComponent, + MacroKeyTabComponent, + MacroMouseTabComponent, + MacroTextTabComponent +} from './components/macro'; import { NotificationComponent } from './components/notification'; import { PopoverComponent } from './components/popover'; import { @@ -19,7 +29,6 @@ import { MouseTabComponent, NoneTabComponent } from './components/popover/tab'; -import { MacroItemComponent } from './components/popover/tab/macro'; import { CaptureKeystrokeButtonComponent } from './components/popover/widgets/capture-keystroke'; import { IconComponent } from './components/popover/widgets/icon'; import { SideMenuComponent } from './components/side-menu'; @@ -36,17 +45,17 @@ import { } from './components/svg/keys'; import { SvgModuleComponent } from './components/svg/module'; import { SvgKeyboardWrapComponent } from './components/svg/wrap'; +import { MainAppComponent, appRoutingProviders, routing } from './main-app'; import { DataProviderService } from './services/data-provider.service'; import { MapperService } from './services/mapper.service'; -import {UhkConfigurationService} from './services/uhk-configuration.service'; +import { UhkConfigurationService } from './services/uhk-configuration.service'; @NgModule({ declarations: [ Select2Component, MainAppComponent, KeymapComponent, - MacroComponent, LegacyLoaderComponent, NotificationComponent, SvgIconTextKeyComponent, @@ -73,10 +82,19 @@ import {UhkConfigurationService} from './services/uhk-configuration.service'; NoneTabComponent, CaptureKeystrokeButtonComponent, IconComponent, - MacroItemComponent + MacroComponent, + MacroItemComponent, + MacroActionEditorComponent, + MacroDelayTabComponent, + MacroKeyTabComponent, + MacroMouseTabComponent, + MacroTextTabComponent, + ContenteditableDirective ], imports: [ BrowserModule, + FormsModule, + DragulaModule, routing ], providers: [ diff --git a/src/components/macro/index.ts b/src/components/macro/index.ts index 5e1543e6..1bf72a94 100644 --- a/src/components/macro/index.ts +++ b/src/components/macro/index.ts @@ -1,2 +1,5 @@ export * from './macro.component'; export * from './macro.routes'; +export * from './macro-item'; +export * from './macro-action-editor'; +export * from './macro-action-editor/tab'; diff --git a/src/components/macro/macro-action-editor/index.ts b/src/components/macro/macro-action-editor/index.ts new file mode 100644 index 00000000..a236a40f --- /dev/null +++ b/src/components/macro/macro-action-editor/index.ts @@ -0,0 +1 @@ +export { MacroActionEditorComponent } from './macro-action-editor.component'; diff --git a/src/components/macro/macro-action-editor/macro-action-editor.component.html b/src/components/macro/macro-action-editor/macro-action-editor.component.html new file mode 100644 index 00000000..2d9428bc --- /dev/null +++ b/src/components/macro/macro-action-editor/macro-action-editor.component.html @@ -0,0 +1,46 @@ +
+
+ +
+ + + + +
+
+
+
+
+ + +
+
+
+
\ No newline at end of file diff --git a/src/components/macro/macro-action-editor/macro-action-editor.component.scss b/src/components/macro/macro-action-editor/macro-action-editor.component.scss new file mode 100644 index 00000000..cc7983a1 --- /dev/null +++ b/src/components/macro/macro-action-editor/macro-action-editor.component.scss @@ -0,0 +1,80 @@ +.action--editor { + padding-top: 0; + padding-bottom: 0; + border-radius: 0; + border: 0; +} + +.nav { + padding-bottom: 1rem; + + li { + a { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + + &.selected { + font-style: italic; + } + + &:hover { + cursor: pointer; + } + } + + &.active { + z-index: 2; + + a { + &.selected { + font-style: normal; + } + + &:after { + content: ''; + display: block; + position: absolute; + width: 0; + height: 0; + top: 0; + right: -4rem; + border-color: transparent transparent transparent #337ab7; + border-style: solid; + border-width: 2rem; + } + } + } + } +} + +.editor { + &__tabs, + &__tab-links { + padding-top: 1rem; + } + + &__tabs { + border-left: 1px solid #ddd; + margin-left: -1.6rem; + padding-left: 3rem; + } + + &__actions { + float: right; + + &-container { + background: #f5f5f5; + border-top: 1px solid #ddd; + padding: 1rem 1.5rem; + } + } +} + +.flex-button-wrapper { + display: flex; + flex-direction: row-reverse; +} + +.flex-button { + align-self: flex-end; +} diff --git a/src/components/macro/macro-action-editor/macro-action-editor.component.ts b/src/components/macro/macro-action-editor/macro-action-editor.component.ts new file mode 100644 index 00000000..b35d6443 --- /dev/null +++ b/src/components/macro/macro-action-editor/macro-action-editor.component.ts @@ -0,0 +1,107 @@ +import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; + +import { + EditableMacroAction, + MacroAction, + TextMacroAction, + macroActionType +} from '../../../config-serializer/config-items/macro-action'; +import { MacroKeyTabComponent } from './tab/macro-key'; + +enum TabName { + Keypress, + Text, + Mouse, + Delay +}; + +@Component({ + selector: 'macro-action-editor', + template: require('./macro-action-editor.component.html'), + styles: [require('./macro-action-editor.component.scss')], + host: { 'class': 'macro-action-editor' } +}) +export class MacroActionEditorComponent implements OnInit { + @Input() macroAction: MacroAction; + + @Output() save = new EventEmitter(); + @Output() cancel = new EventEmitter(); + + @ViewChild('tab') selectedTab: any; + + private editableMacroAction: EditableMacroAction; + private activeTab: TabName; + /* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */ + /* tslint:disable:no-unused-variable: It is used in the template. */ + private TabName = TabName; + /* tslint:enable:no-unused-variable */ + /* tslint:enable:variable-name */ + + ngOnInit() { + let macroAction: MacroAction = this.macroAction ? this.macroAction : new TextMacroAction(); + this.editableMacroAction = new EditableMacroAction(macroAction.toJsObject()); + let tab: TabName = this.getTabName(this.editableMacroAction); + this.activeTab = tab; + } + + onCancelClick(): void { + this.cancel.emit(); + } + + onSaveClick(): void { + try { + const action = this.editableMacroAction; + if (action.isKeyAction()) { + // Could updating the saved keys be done in a better way? + const tab = this.selectedTab as MacroKeyTabComponent; + action.fromKeyAction(tab.getKeyAction()); + } + this.save.emit(action.toClass()); + } catch (e) { + // TODO: show error dialog + console.error(e); + } + } + + selectTab(tab: TabName): void { + this.activeTab = tab; + this.editableMacroAction.macroActionType = this.getTabMacroActionType(tab); + } + + getTabName(action: EditableMacroAction): TabName { + switch (action.macroActionType) { + // Delay action + case macroActionType.DelayMacroAction: + return TabName.Delay; + // Text action + case macroActionType.TextMacroAction: + return TabName.Text; + // Keypress actions + case macroActionType.KeyMacroAction: + return TabName.Keypress; + // Mouse actions + case macroActionType.MouseButtonMacroAction: + case macroActionType.MoveMouseMacroAction: + case macroActionType.ScrollMouseMacroAction: + return TabName.Mouse; + default: + return TabName.Keypress; + } + } + + getTabMacroActionType(tab: TabName): string { + switch (tab) { + case TabName.Delay: + return macroActionType.DelayMacroAction; + case TabName.Keypress: + return macroActionType.KeyMacroAction; + case TabName.Mouse: + return macroActionType.MouseButtonMacroAction; + case TabName.Text: + return macroActionType.TextMacroAction; + default: + throw new Error('Could not get macro action type'); + } + } + +} diff --git a/src/components/macro/macro-action-editor/tab/index.ts b/src/components/macro/macro-action-editor/tab/index.ts new file mode 100644 index 00000000..1a9cd2b1 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/index.ts @@ -0,0 +1,4 @@ +export { MacroDelayTabComponent } from './macro-delay'; +export { MacroKeyTabComponent } from './macro-key'; +export { MacroMouseTabComponent } from './macro-mouse'; +export { MacroTextTabComponent } from './macro-text'; diff --git a/src/components/macro/macro-action-editor/tab/macro-delay/index.ts b/src/components/macro/macro-action-editor/tab/macro-delay/index.ts new file mode 100644 index 00000000..39690db4 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-delay/index.ts @@ -0,0 +1 @@ +export { MacroDelayTabComponent } from './macro-delay.component'; diff --git a/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.html b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.html new file mode 100644 index 00000000..3b45d463 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.html @@ -0,0 +1,26 @@ +
+
+
+

Enter delay in seconds

+
+
+
+
+ +
+
+
+
+
Choose a preset
+ +
+
+
diff --git a/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.scss b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.scss new file mode 100644 index 00000000..91c61376 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.scss @@ -0,0 +1,16 @@ +:host { + display: flex; + flex-direction: column; + position: relative; +} + +.macro-delay { + &__presets { + margin-top: 1rem; + + button { + margin-right: 0.25rem; + margin-bottom: 0.25rem; + } + } +} diff --git a/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.ts b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.ts new file mode 100644 index 00000000..f43385b1 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.ts @@ -0,0 +1,35 @@ +import { AfterViewInit, Component, ElementRef, Input, OnInit, Renderer, ViewChild } from '@angular/core'; + +import { EditableMacroAction } from '../../../../../config-serializer/config-items/macro-action'; + +const INITIAL_DELAY = 0.5; // In seconds + +@Component({ + selector: 'macro-delay-tab', + template: require('./macro-delay.component.html'), + styles: [require('./macro-delay.component.scss')], + host: { 'class': 'macro__delay' } +}) +export class MacroDelayTabComponent implements AfterViewInit, OnInit { + @Input() macroAction: EditableMacroAction; + @ViewChild('macroDelayInput') input: ElementRef; + private delay: number; + /* tslint:disable:no-unused-variable: It is used in the template. */ + private presets: number[] = [0.3, 0.5, 0.8, 1, 2, 3, 4, 5]; + /* tslint:enable:no-unused-variable */ + + constructor(private renderer: Renderer) { } + + ngOnInit() { + this.delay = this.macroAction.delay > 0 ? this.macroAction.delay / 1000 : INITIAL_DELAY; + } + + ngAfterViewInit() { + this.renderer.invokeElementMethod(this.input.nativeElement, 'focus'); + } + + setDelay(value: number): void { + this.delay = value; + this.macroAction.delay = this.delay * 1000; + } +} diff --git a/src/components/macro/macro-action-editor/tab/macro-key/index.ts b/src/components/macro/macro-action-editor/tab/macro-key/index.ts new file mode 100644 index 00000000..f9fe969b --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-key/index.ts @@ -0,0 +1 @@ +export { MacroKeyTabComponent } from './macro-key.component'; diff --git a/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.html b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.html new file mode 100644 index 00000000..9437ceb0 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.html @@ -0,0 +1,32 @@ +
+ +
+
+

Press key

+

Hold key

+

Release key

+ +
+
+
\ No newline at end of file diff --git a/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.scss b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.scss new file mode 100644 index 00000000..1929f3e8 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.scss @@ -0,0 +1,25 @@ +.macro-key { + &__container { + padding: 0; + } + + &__types { + margin-left: 0; + padding: 0 0 1rem; + } + + &__action { + &-container { + margin-top: -1rem; + padding-top: 1rem; + border-left: 1px solid #ddd; + } + + padding-left: 3rem; + padding-bottom: 1rem; + } +} + +.fa { + min-width: 14px; +} diff --git a/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.ts b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.ts new file mode 100644 index 00000000..1e3f0921 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.ts @@ -0,0 +1,74 @@ +import { Component, Input, OnInit, ViewChild } from '@angular/core'; + +import { KeyAction } from '../../../../../config-serializer/config-items/key-action'; +import { EditableMacroAction, MacroSubAction } from '../../../../../config-serializer/config-items/macro-action'; +import { KeypressTabComponent } from '../../../../popover/tab'; +import { Tab } from '../../../../popover/tab'; + +enum TabName { + Keypress, + Hold, + Release +} + +@Component({ + selector: 'macro-key-tab', + template: require('./macro-key.component.html'), + styles: [ + require('../../macro-action-editor.component.scss'), + require('./macro-key.component.scss') + ], + host: { 'class': 'macro__mouse' } +}) +export class MacroKeyTabComponent implements OnInit { + @Input() macroAction: EditableMacroAction; + @ViewChild('tab') selectedTab: Tab; + @ViewChild('keypressTab') keypressTab: KeypressTabComponent; + + private defaultKeyAction: KeyAction; + + private activeTab: TabName; + /* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */ + /* tslint:disable:no-unused-variable: It is used in the template. */ + private TabName = TabName; + /* tslint:enable:no-unused-variable */ + /* tslint:enable:variable-name */ + + ngOnInit() { + this.defaultKeyAction = this.macroAction.toKeystrokeAction(); + this.selectTab(this.getTabName(this.macroAction)); + } + + selectTab(tab: TabName): void { + this.activeTab = tab; + this.macroAction.action = this.getActionType(tab); + } + + getTabName(action: EditableMacroAction): TabName { + if (!action.action || action.isOnlyPressAction()) { + return TabName.Keypress; + } else if (action.isOnlyHoldAction()) { + return TabName.Hold; + } else if (action.isOnlyReleaseAction()) { + return TabName.Release; + } + } + + getActionType(tab: TabName): MacroSubAction { + switch (tab) { + case TabName.Keypress: + return MacroSubAction.press; + case TabName.Hold: + return MacroSubAction.hold; + case TabName.Release: + return MacroSubAction.release; + default: + throw new Error('Invalid tab type'); + } + } + + getKeyAction(): KeyAction { + return this.keypressTab.toKeyAction(); + } + +} diff --git a/src/components/macro/macro-action-editor/tab/macro-mouse/index.ts b/src/components/macro/macro-action-editor/tab/macro-mouse/index.ts new file mode 100644 index 00000000..039a889d --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-mouse/index.ts @@ -0,0 +1 @@ +export { MacroMouseTabComponent } from './macro-mouse.component'; diff --git a/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.html b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.html new file mode 100644 index 00000000..c5568cbd --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.html @@ -0,0 +1,77 @@ +
+ +
+
+

Move pointer

+

Use negative values to move down or left from current position.

+
+
+ + pixels +
+
+ + pixels +
+
+
+
+

Scroll

+

Use negative values to move down or left from current position.

+
+
+ + pixels +
+
+ + pixels +
+
+
+
+

Click mouse button

+

Hold mouse button

+

Release mouse button

+
+ +
+
+
+
\ No newline at end of file diff --git a/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.scss b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.scss new file mode 100644 index 00000000..50596da0 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.scss @@ -0,0 +1,43 @@ +.macro-mouse { + &__container { + padding: 0; + } + + &__types { + border-right: 1px solid #ddd; + border-left: 0; + margin-top: -1rem; + margin-left: 0; + padding: 1rem 0; + } + + &__actions { + padding-left: 3rem; + padding-bottom: 1rem; + } + + &__buttons { + margin-top: 3rem; + margin-bottom: 1rem; + } +} + +.fa { + min-width: 14px; +} + +.form-horizontal { + .form-group { + margin: 0 0 0.5rem; + } + + label { + display: inline-block; + margin-right: 0.5rem; + } + + .form-control { + display: inline-block; + width: 60%; + } +} diff --git a/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.ts b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.ts new file mode 100644 index 00000000..a0b3f468 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.ts @@ -0,0 +1,107 @@ +import { Component, Input, OnInit, ViewChild } from '@angular/core'; + +import { EditableMacroAction, MacroSubAction, macroActionType } from '../../../../../config-serializer/config-items/macro-action'; +import { Tab } from '../../../../popover/tab'; + +enum TabName { + Move, + Scroll, + Click, + Hold, + Release +} + +@Component({ + selector: 'macro-mouse-tab', + template: require('./macro-mouse.component.html'), + styles: [ + require('../../macro-action-editor.component.scss'), + require('./macro-mouse.component.scss') + ], + host: { 'class': 'macro__mouse' } +}) +export class MacroMouseTabComponent implements OnInit { + @Input() macroAction: EditableMacroAction; + @ViewChild('tab') selectedTab: Tab; + + private activeTab: TabName; + private buttonLabels: string[]; + private selectedButtons: boolean[]; + /* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */ + /* tslint:disable:no-unused-variable: It is used in the template. */ + private TabName = TabName; + /* tslint:enable:no-unused-variable */ + /* tslint:enable:variable-name */ + + constructor() { + this.buttonLabels = ['Left', 'Middle', 'Right']; + this.selectedButtons = Array(this.buttonLabels.length).fill(false); + } + + ngOnInit() { + const tabName = this.getTabName(this.macroAction); + this.selectTab(tabName); + const buttonActions = [TabName.Click, TabName.Hold, TabName.Release]; + if (buttonActions.includes(this.activeTab)) { + this.selectedButtons = this.macroAction.getMouseButtons(); + } + } + + selectTab(tab: TabName): void { + this.activeTab = tab; + this.macroAction.macroActionType = this.getMacroActionType(tab); + if (this.macroAction.macroActionType === macroActionType.MouseButtonMacroAction) { + this.macroAction.action = this.getAction(tab); + } + } + + setMouseClick(index: number): void { + this.selectedButtons[index] = !this.selectedButtons[index]; + this.macroAction.setMouseButtons(this.selectedButtons); + } + + hasButton(index: number): boolean { + return this.selectedButtons[index]; + } + + getAction(tab: TabName): MacroSubAction { + switch (tab) { + case TabName.Click: + return MacroSubAction.press; + case TabName.Hold: + return MacroSubAction.hold; + case TabName.Release: + return MacroSubAction.release; + default: + throw new Error('Invalid tab name'); + } + } + + getTabName(action: EditableMacroAction): TabName { + if (action.macroActionType === macroActionType.MouseButtonMacroAction) { + if (!action.action || action.isOnlyPressAction()) { + return TabName.Click; + } else if (action.isOnlyPressAction()) { + return TabName.Hold; + } else if (action.isOnlyReleaseAction()) { + return TabName.Release; + } + } else if (action.macroActionType === macroActionType.MoveMouseMacroAction) { + return TabName.Move; + } else if (action.macroActionType === macroActionType.ScrollMouseMacroAction) { + return TabName.Scroll; + } + return TabName.Move; + } + + getMacroActionType(tab: TabName): string { + if (tab === TabName.Click || tab === TabName.Hold || tab === TabName.Release) { + return macroActionType.MouseButtonMacroAction; + } else if (tab === TabName.Move) { + return macroActionType.MoveMouseMacroAction; + } else if (tab === TabName.Scroll) { + return macroActionType.ScrollMouseMacroAction; + } + } + +} diff --git a/src/components/macro/macro-action-editor/tab/macro-text/index.ts b/src/components/macro/macro-action-editor/tab/macro-text/index.ts new file mode 100644 index 00000000..913e5171 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-text/index.ts @@ -0,0 +1 @@ +export { MacroTextTabComponent } from './macro-text.component'; diff --git a/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.html b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.html new file mode 100644 index 00000000..ab8590ad --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.html @@ -0,0 +1,5 @@ +
+

Type text

+

Input the text you want to type with this macro action.

+ +
\ No newline at end of file diff --git a/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.scss b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.scss new file mode 100644 index 00000000..b991040a --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.scss @@ -0,0 +1,11 @@ +:host { + display: flex; + flex-direction: column; + position: relative; +} + +.macro__text-input { + width: 100%; + min-height: 10rem; + margin-bottom: 1rem; +} diff --git a/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.ts b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.ts new file mode 100644 index 00000000..11d3a592 --- /dev/null +++ b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.ts @@ -0,0 +1,28 @@ +import { + AfterViewInit, + Component, + ElementRef, + Input, + Renderer, + ViewChild +} from '@angular/core'; + +import { EditableMacroAction } from '../../../../../config-serializer/config-items/macro-action'; + +@Component({ + selector: 'macro-text-tab', + template: require('./macro-text.component.html'), + styles: [require('./macro-text.component.scss')], + host: { 'class': 'macro__text' } +}) +export class MacroTextTabComponent implements AfterViewInit { + @Input() macroAction: EditableMacroAction; + @ViewChild('macroTextInput') input: ElementRef; + + constructor(private renderer: Renderer) {} + + ngAfterViewInit() { + this.renderer.invokeElementMethod(this.input.nativeElement, 'focus'); + } + +} diff --git a/src/components/macro/macro-item/index.ts b/src/components/macro/macro-item/index.ts new file mode 100644 index 00000000..f9155da6 --- /dev/null +++ b/src/components/macro/macro-item/index.ts @@ -0,0 +1 @@ +export { MacroItemComponent } from './macro-item.component'; diff --git a/src/components/macro/macro-item/macro-item.component.html b/src/components/macro/macro-item/macro-item.component.html new file mode 100644 index 00000000..b790ee61 --- /dev/null +++ b/src/components/macro/macro-item/macro-item.component.html @@ -0,0 +1,15 @@ +
+ + +
{{ title }}
+ + +
+
+ +
\ No newline at end of file diff --git a/src/components/macro/macro-item/macro-item.component.scss b/src/components/macro/macro-item/macro-item.component.scss new file mode 100644 index 00000000..a71b434e --- /dev/null +++ b/src/components/macro/macro-item/macro-item.component.scss @@ -0,0 +1,53 @@ +:host { + &.macro-item:first-of-type { + .list-group-item { + border-radius: 4px 4px 0 0; + } + } + + &.macro-item:last-of-type { + .list-group-item { + border-bottom: 0; + } + } + + .action { + &--item { + display: flex; + flex-shrink: 0; + border: 0; + border-bottom: 1px solid #ddd; + + icon { + margin: 0 5px; + } + + > div { + display: flex; + flex: 1; + } + + &:first-child { + border-radius: 0; + } + + &.is-editing { + background: #f5f5f5; + } + } + + &--movable { + &:hover { + cursor: move; + } + } + } + + .macro-action-editor__container { + padding-top: 0; + padding-bottom: 0; + border-radius: 0; + border-left: 0; + border-right: 0; + } +} diff --git a/src/components/macro/macro-item/macro-item.component.ts b/src/components/macro/macro-item/macro-item.component.ts new file mode 100644 index 00000000..c559ba61 --- /dev/null +++ b/src/components/macro/macro-item/macro-item.component.ts @@ -0,0 +1,195 @@ +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; + +import { KeyModifiers } from '../../../config-serializer/config-items/KeyModifiers'; +import { + DelayMacroAction, + KeyMacroAction, + MacroAction, + MouseButtonMacroAction, + MoveMouseMacroAction, + ScrollMouseMacroAction, + TextMacroAction +} from '../../../config-serializer/config-items/macro-action'; + +import { MapperService } from '../../../services/mapper.service'; + +@Component({ + selector: 'macro-item', + template: require('./macro-item.component.html'), + styles: [require('./macro-item.component.scss')], + host: { 'class': 'macro-item' } +}) +export class MacroItemComponent implements OnInit, OnChanges { + + @Input() macroAction: MacroAction; + @Input() editable: boolean; + @Input() deletable: boolean; + @Input() moveable: boolean; + + @Output() save = new EventEmitter(); + @Output() cancel = new EventEmitter(); + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + + private title: string; + private iconName: string; + private editing: boolean; + + constructor(private mapper: MapperService) { } + + ngOnInit() { + this.updateView(); + if (!this.macroAction) { + this.editing = true; + } + } + + ngOnChanges(changes: SimpleChanges) { + /* tslint:disable:no-string-literal */ + if (changes['macroAction']) { + /* tslint:enable:no-string-literal */ + this.updateView(); + } + } + + saveEditedAction(editedAction: MacroAction): void { + // @todo save this to keyboard + console.log('Saved action', editedAction); + this.macroAction = editedAction; + this.editing = false; + this.updateView(); + this.save.emit(editedAction); + } + + editAction(): void { + if (!this.editable) { + return; + } + this.editing = true; + this.edit.emit(); + } + + cancelEdit(): void { + this.editing = false; + this.cancel.emit(); + } + + deleteAction(): void { + this.delete.emit(); + } + + private updateView(): void { + if (!this.macroAction) { + this.title = 'New macro action'; + } else if (this.macroAction instanceof DelayMacroAction) { + // Delay + this.iconName = 'clock'; + let action: DelayMacroAction = this.macroAction as DelayMacroAction; + const delay = action.delay > 0 ? action.delay / 1000 : 0; + this.title = `Delay of ${delay}s`; + } else if (this.macroAction instanceof TextMacroAction) { + // Write text + let action: TextMacroAction = this.macroAction as TextMacroAction; + this.iconName = 'font'; + this.title = `Write text: ${action.text}`; + } else if (this.macroAction instanceof KeyMacroAction) { + // Key pressed/held/released + const action: KeyMacroAction = this.macroAction as KeyMacroAction; + this.setKeyActionContent(action); + } else if (this.macroAction instanceof MouseButtonMacroAction) { + // Mouse button clicked/held/released + const action: MouseButtonMacroAction = this.macroAction as MouseButtonMacroAction; + this.setMouseButtonActionContent(action); + } else if (this.macroAction instanceof MoveMouseMacroAction || this.macroAction instanceof ScrollMouseMacroAction) { + // Mouse moved or scrolled + this.setMouseMoveScrollActionContent(this.macroAction); + } else { + this.title = this.macroAction.constructor.name; + } + } + + private setKeyActionContent(action: KeyMacroAction): void { + if (!action.hasScancode() && !action.hasModifiers()) { + this.title = 'Invalid keypress'; + return; + } + + if (action.isPressAction()) { + // Press key + this.iconName = 'hand-pointer'; + this.title = 'Press key: '; + } else if (action.isHoldAction()) { + // Hold key + this.iconName = 'hand-rock'; + this.title = 'Hold key: '; + } else if (action.isReleaseAction()) { + // Release key + this.iconName = 'hand-paper'; + this.title = 'Release key: '; + } + + if (action.hasScancode()) { + const scancode: string = this.mapper.scanCodeToText(action.scancode).join(' '); + if (scancode) { + this.title += scancode; + } + } + + if (action.hasModifiers()) { + // Press/hold/release modifiers + for (let i = KeyModifiers.leftCtrl; i !== KeyModifiers.rightGui; i <<= 1) { + if (action.isModifierActive(i)) { + this.title += ' ' + KeyModifiers[i]; + } + } + } + } + + private setMouseMoveScrollActionContent(action: MacroAction): void { + let typedAction: any; + if (action instanceof MoveMouseMacroAction) { + // Move mouse pointer + this.iconName = 'mouse-pointer'; + this.title = 'Move pointer'; + typedAction = this.macroAction as MoveMouseMacroAction; + } else { + // Scroll mouse + this.iconName = 'mouse-pointer'; + this.title = 'Scroll'; + typedAction = this.macroAction as ScrollMouseMacroAction; + } + + let needAnd: boolean; + if (Math.abs(typedAction.x) !== 0) { + this.title += ` by ${Math.abs(typedAction.x)}px ${typedAction.x > 0 ? 'left' : 'right'}`; + needAnd = true; + } + if (Math.abs(typedAction.y) !== 0) { + this.title += ` ${needAnd ? 'and' : 'by'} ${Math.abs(typedAction.y)}px ${typedAction.y > 0 ? 'down' : 'up'}`; + } + } + + private setMouseButtonActionContent(action: MouseButtonMacroAction): void { + // Press/hold/release mouse buttons + if (action.isOnlyPressAction()) { + this.iconName = 'mouse-pointer'; + this.title = 'Click mouse button: '; + } else if (action.isOnlyHoldAction()) { + this.iconName = 'hand-rock'; + this.title = 'Hold mouse button: '; + } else if (action.isOnlyReleaseAction()) { + this.iconName = 'hand-paper'; + this.title = 'Release mouse button: '; + } + + const buttonLabels: string[] = ['Left', 'Middle', 'Right']; + const selectedButtons: boolean[] = action.getMouseButtons(); + const selectedButtonLabels: string[] = []; + selectedButtons.forEach((isSelected, idx) => { + if (isSelected && buttonLabels[idx]) { + selectedButtonLabels.push(buttonLabels[idx]); + } + }); + this.title += selectedButtonLabels.join(', '); + } +} diff --git a/src/components/macro/macro.component.html b/src/components/macro/macro.component.html index a7c4ea8b..5e8a17e1 100644 --- a/src/components/macro/macro.component.html +++ b/src/components/macro/macro.component.html @@ -1,74 +1,38 @@ -
-
-

- - Macro1 -

-
-
-
-
- - Move pointer by 100px leftward - - -
- -
- - Press letter A - - -
-
- - Press Alt+Tab - - -
-
- - Delay of 235ms - - -
-
- - Press button 1 - - -
-
- - Scroll by 150px downward - - -
+
+

+ + {{macro.name}} +

+
+
+
+
+ +
+
-
+
-

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut - labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo - dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor - sit amet.

+

Remember to save your changes!

- - + +
diff --git a/src/components/macro/macro.component.scss b/src/components/macro/macro.component.scss index ab3f7d22..b1e1f861 100644 --- a/src/components/macro/macro.component.scss +++ b/src/components/macro/macro.component.scss @@ -1,3 +1,20 @@ +:host { + display: flex; + flex-direction: column; + height: 100%; + + .list-container { + display: flex; + flex: 1; + + > div { + display: flex; + flex-direction: column; + flex: 1; + } + } +} + .main-wrapper { width: 500px; } @@ -6,33 +23,50 @@ h1 { margin-bottom: 3rem; } -.action--item { - padding-left: 8px; +.action { + &--edit__form { + background-color: #fff; + margin-left: -0.5rem; + margin-right: -15px; + margin-top: 15px; + padding-top: 15px; + border-top: 1px solid #ddd; + } + + &--item { + padding-left: 8px; + + &.active, + &.active:hover { + background-color: white; + font-weight: bold; + color: black; + border-color: black; + z-index: 10; + } + } } -.action--item.active, -.action--item.active:hover { - background-color: white; - font-weight: bold; - color: black; - border-color: black; - z-index: 10; +.macro__name { + border-bottom: 2px dotted #999; + padding: 0 0.5rem; + margin: 0 0.25rem; } .macro-settings { border: 1px solid black; border-top-color: #999; z-index: 100; -} -.macro-settings .helper { - position: absolute; - display: block; - height: 13px; - background: #fff; - width: 100%; - left: 0; - top: -14px; + .helper { + position: absolute; + display: block; + height: 13px; + background: #fff; + width: 100%; + left: 0; + top: -14px; + } } .action--item.active.callout, @@ -40,38 +74,18 @@ h1 { box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.5); } +.macro-actions-container { + overflow: auto; + margin-bottom: 0; + border-radius: 4px 4px 0 0; + border: 1px solid #ddd; + border-bottom: 0; +} + .list-group-item .move-handle:hover { cursor: move; } -.action--edit { - float: right; -} - -.action--edit:hover { - color: #337ab7; - cursor: pointer; -} - -.action--trash { - float: right; - margin-right: 1rem; -} - -.action--trash:hover { - color: #d9534f; - cursor: pointer; -} - -.action--edit__form { - background-color: #fff; - margin-left: -0.5rem; - margin-right: -15px; - margin-top: 15px; - padding-top: 15px; - border-top: 1px solid #ddd; -} - .flex-button-wrapper { display: flex; flex-direction: row-reverse; @@ -81,13 +95,22 @@ h1 { align-self: flex-end; } -.add-new__action-item:hover { - cursor: pointer; +.add-new__action-container { + border-top: 1px solid #ddd; } -.add-new__action-item--link, -.add-new__action-item--link:active, -.add-new__action-item--link:hover { - text-decoration: none; - color: #337ab7; +.add-new__action-item { + border-radius: 0 0 4px 4px; + border-top: 0; + + &:hover { + cursor: pointer; + } + + &--link, + &--link:active, + &--link:hover { + text-decoration: none; + color: #337ab7; + } } diff --git a/src/components/macro/macro.component.ts b/src/components/macro/macro.component.ts index 945dacc6..c3fa4f48 100644 --- a/src/components/macro/macro.component.ts +++ b/src/components/macro/macro.component.ts @@ -1,12 +1,116 @@ -import { Component } from '@angular/core'; +import { Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { Subscription } from 'rxjs/Subscription'; + +import { DragulaService } from 'ng2-dragula/ng2-dragula'; + +import { Macro } from '../../config-serializer/config-items/Macro'; +import { MacroAction } from '../../config-serializer/config-items/macro-action'; +import { MacroItemComponent } from './macro-item/macro-item.component'; + +import { UhkConfigurationService } from '../../services/uhk-configuration.service'; @Component({ selector: 'macro', template: require('./macro.component.html'), - styles: [require('./macro.component.scss')] + styles: [require('./macro.component.scss')], + viewProviders: [DragulaService] }) -export class MacroComponent { +export class MacroComponent implements OnInit, OnDestroy { + @ViewChildren(MacroItemComponent) macroItems: QueryList; - constructor() { + private macro: Macro; + + private routeSubscription: Subscription; + private hasChanges: boolean = false; + private dragEnabled: boolean; + + constructor( + private uhkConfigurationService: UhkConfigurationService, + private route: ActivatedRoute, + private dragulaService: DragulaService + ) { + /* tslint:disable:no-unused-variable: Used by Dragula. */ + dragulaService.setOptions('macroActions', { + moves: function (el: any, container: any, handle: any) { + return handle.className.includes('action--movable'); + } + }); + /* tslint:enable:no-unused-variable */ } + + ngOnInit() { + this.routeSubscription = this.route.params.subscribe((params: { id: string }) => { + const id: number = Number(params.id); + this.macro = this.getMacro(id); + this.dragEnabled = true; + this.hasChanges = false; + }); + } + + getMacro(id: number): Macro { + const config = this.uhkConfigurationService.getUhkConfiguration(); + const macro: Macro = config.macros.elements.find(item => item.id === id); + if (macro) { + // Clone macro for editing + return new Macro().fromJsObject(macro.toJsObject()); + } + // @todo replace with notification + throw new Error('Macro not found'); + } + + saveMacro() { + // @todo Save macro to keyboard + } + + addAction() { + this.hideOtherActionEditors(this.macro.macroActions.elements.length); + this.macro.macroActions.elements.push(undefined); + } + + discardChanges() { + const id: number = this.macro.id; + this.macro = this.getMacro(id); + this.hasChanges = false; + } + + hideOtherActionEditors(index: number) { + this.macroItems.toArray().forEach((macroItem: MacroItemComponent, idx: number) => { + if (idx !== index) { + macroItem.cancelEdit(); + } + }); + } + + onNameChange() { + this.hasChanges = true; + } + + onEditAction(index: number) { + // Hide other editors when clicking edit button of a macro action + this.hideOtherActionEditors(index); + this.dragEnabled = false; + } + + onCancelEditAction() { + this.dragEnabled = true; + } + + onSaveAction(macroAction: MacroAction, index: number) { + this.dragEnabled = true; + this.hasChanges = true; + this.macro.macroActions.elements[index] = macroAction; + } + + onDeleteAction(index: number) { + // @ todo show confirm action dialog + this.macro.macroActions.elements.splice(index, 1); + this.hasChanges = true; + } + + ngOnDestroy() { + this.routeSubscription.unsubscribe(); + } + } diff --git a/src/components/popover/popover.component.html b/src/components/popover/popover.component.html index 5d08b10e..311904c7 100644 --- a/src/components/popover/popover.component.html +++ b/src/components/popover/popover.component.html @@ -42,7 +42,7 @@
- + diff --git a/src/components/popover/tab/keypress/keypress-tab.component.html b/src/components/popover/tab/keypress/keypress-tab.component.html index b4492276..c0ea90d6 100644 --- a/src/components/popover/tab/keypress/keypress-tab.component.html +++ b/src/components/popover/tab/keypress/keypress-tab.component.html @@ -21,7 +21,7 @@
-
+
Long press action: diff --git a/src/components/popover/tab/keypress/keypress-tab.component.ts b/src/components/popover/tab/keypress/keypress-tab.component.ts index 3879a0d4..271485d8 100644 --- a/src/components/popover/tab/keypress/keypress-tab.component.ts +++ b/src/components/popover/tab/keypress/keypress-tab.component.ts @@ -13,6 +13,7 @@ import {Tab} from '../tab'; }) export class KeypressTabComponent implements OnInit, Tab { @Input() defaultKeyAction: KeyAction; + @Input() longPressEnabled: boolean; private leftModifiers: string[]; private rightModifiers: string[]; diff --git a/src/components/popover/tab/macro/index.ts b/src/components/popover/tab/macro/index.ts index 58cac3e1..ef6b932a 100644 --- a/src/components/popover/tab/macro/index.ts +++ b/src/components/popover/tab/macro/index.ts @@ -1,2 +1 @@ -export * from './macro-item.component'; export * from './macro-tab.component'; diff --git a/src/components/popover/tab/macro/macro-item.component.html b/src/components/popover/tab/macro/macro-item.component.html deleted file mode 100644 index 06ed0384..00000000 --- a/src/components/popover/tab/macro/macro-item.component.html +++ /dev/null @@ -1,5 +0,0 @@ - - -
{{ title }}
- - \ No newline at end of file diff --git a/src/components/popover/tab/macro/macro-item.component.scss b/src/components/popover/tab/macro/macro-item.component.scss deleted file mode 100644 index 25b3534f..00000000 --- a/src/components/popover/tab/macro/macro-item.component.scss +++ /dev/null @@ -1,13 +0,0 @@ -:host { - display: flex; - flex-shrink: 0; - - icon { - margin: 0 5px; - } - - div { - display: flex; - flex: 1; - } -} diff --git a/src/components/popover/tab/macro/macro-item.component.ts b/src/components/popover/tab/macro/macro-item.component.ts deleted file mode 100644 index 09da57d4..00000000 --- a/src/components/popover/tab/macro/macro-item.component.ts +++ /dev/null @@ -1,102 +0,0 @@ -/// - -import { Component, Input, OnChanges, OnInit } from '@angular/core'; - -import {KeyModifiers} from '../../../../config-serializer/config-items/KeyModifiers'; -import { - DelayMacroAction, - KeyMacroAction, - MacroAction, - MoveMouseMacroAction, - ScrollMouseMacroAction, - TextMacroAction -} from '../../../../config-serializer/config-items/macro-action'; - -import {MapperService} from '../../../../services/mapper.service'; - -@Component({ - selector: 'macro-item', - template: require('./macro-item.component.html'), - styles: [require('./macro-item.component.scss')] -}) -export class MacroItemComponent implements OnInit, OnChanges { - - @Input() macroAction: MacroAction; - @Input() editable: boolean; - @Input() deletable: boolean; - @Input() moveable: boolean; - - private iconName: string; - private title: string; - - constructor(private mapper: MapperService) { } - - ngOnInit() { - this.updateView(); - } - - ngOnChanges() { - // TODO: check if macroAction changed - this.updateView(); - } - - private updateView(): void { - - this.title = this.macroAction.constructor.name; - if (this.macroAction instanceof MoveMouseMacroAction) { - this.iconName = 'mouse-pointer'; - this.title = 'Move pointer'; - - let action: MoveMouseMacroAction = this.macroAction as MoveMouseMacroAction; - let needAnd: boolean; - if (Math.abs(action.x) > 0) { - this.title += ` by ${Math.abs(action.x)}px ${action.x > 0 ? 'left' : 'right'}ward`; - needAnd = true; - } - if (Math.abs(action.y) > 0) { - this.title += ` ${needAnd ? 'and' : 'by'} ${Math.abs(action.y)}px ${action.y > 0 ? 'down' : 'up'}ward`; - } - } else if (this.macroAction instanceof DelayMacroAction) { - this.iconName = 'clock'; - let action: DelayMacroAction = this.macroAction as DelayMacroAction; - this.title = `Delay of ${action.delay}ms`; - } else if (this.macroAction instanceof TextMacroAction) { - let action: TextMacroAction = this.macroAction as TextMacroAction; - this.title = `Write text: ${action.text}`; - } else if (this.macroAction instanceof ScrollMouseMacroAction) { - this.iconName = 'mouse-pointer'; - this.title = 'Scroll'; - let action: ScrollMouseMacroAction = this.macroAction as ScrollMouseMacroAction; - let needAnd: boolean; - if (Math.abs(action.x) > 0) { - this.title += ` by ${Math.abs(action.x)}px ${action.x > 0 ? 'left' : 'right'}ward`; - needAnd = true; - } - if (Math.abs(action.y) > 0) { - this.title += ` ${needAnd ? 'and' : 'by'} ${Math.abs(action.y)}px ${action.y > 0 ? 'down' : 'up'}ward`; - } - } else if (this.macroAction instanceof KeyMacroAction) { - const keyMacroAction: KeyMacroAction = this.macroAction; - this.title += 'KeyMacroAction: '; - if (keyMacroAction.isPressAction()) { - this.title = 'Press'; - } else if (keyMacroAction.isHoldAction()) { - this.title = 'Hold'; - } else { - this.title = 'Release'; - } - if (keyMacroAction.hasScancode()) { - this.title += ' ' + this.mapper.scanCodeToText(keyMacroAction.scancode).join(' '); - } - this.iconName = 'square'; - - for (let i = KeyModifiers.leftCtrl; i !== KeyModifiers.rightCtrl; i <<= 1) { - if (keyMacroAction.isModifierActive(i)) { - this.title += ' ' + KeyModifiers[i]; - } - } - } - // TODO: finish for all MacroAction - } - -} diff --git a/src/components/popover/tab/macro/macro-tab.component.html b/src/components/popover/tab/macro/macro-tab.component.html index 8552b7bb..075d63ad 100644 --- a/src/components/popover/tab/macro/macro-tab.component.html +++ b/src/components/popover/tab/macro/macro-tab.component.html @@ -2,10 +2,12 @@ Play macro:
-
+
\ No newline at end of file diff --git a/src/components/popover/tab/macro/macro-tab.component.scss b/src/components/popover/tab/macro/macro-tab.component.scss index 94a91b20..aac3085a 100644 --- a/src/components/popover/tab/macro/macro-tab.component.scss +++ b/src/components/popover/tab/macro/macro-tab.component.scss @@ -25,22 +25,16 @@ margin: 20px 0; overflow-x: hidden; overflow-y: auto; + border-radius: 4px; + border: 1px solid #ddd; - macro-item { - border: 1px solid #ddd; - padding: 10px; - margin-bottom: -1px; + &.inactive { + border: 0; } - macro-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; - } - - macro-item:last-child { - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; + .list-group { margin-bottom: 0; + border: 0; } } } diff --git a/src/components/popover/tab/mouse/mouse-tab.component.ts b/src/components/popover/tab/mouse/mouse-tab.component.ts index 0e4fd85c..4ca8f3f0 100644 --- a/src/components/popover/tab/mouse/mouse-tab.component.ts +++ b/src/components/popover/tab/mouse/mouse-tab.component.ts @@ -1,7 +1,6 @@ import {Component, Input, OnInit} from '@angular/core'; import {KeyAction, MouseAction, MouseActionParam} from '../../../../config-serializer/config-items/key-action'; - import {Tab} from '../tab'; @Component({ diff --git a/src/components/popover/widgets/icon/icon.component.html b/src/components/popover/widgets/icon/icon.component.html index 0264ad81..5c9037b9 100644 --- a/src/components/popover/widgets/icon/icon.component.html +++ b/src/components/popover/widgets/icon/icon.component.html @@ -1,8 +1,12 @@
+ + + + diff --git a/src/components/popover/widgets/icon/icon.component.scss b/src/components/popover/widgets/icon/icon.component.scss index f9b77422..fc014389 100644 --- a/src/components/popover/widgets/icon/icon.component.scss +++ b/src/components/popover/widgets/icon/icon.component.scss @@ -2,3 +2,21 @@ display: flex; align-items: center; } + +.action { + + &--edit { + &:hover { + color: #337ab7; + cursor: pointer; + } + } + + &--trash { + &:hover { + color: #d9534f; + cursor: pointer; + } + } + +} diff --git a/src/components/side-menu/side-menu.component.html b/src/components/side-menu/side-menu.component.html index 7f984448..d4a36b79 100644 --- a/src/components/side-menu/side-menu.component.html +++ b/src/components/side-menu/side-menu.component.html @@ -19,7 +19,7 @@