diff --git a/src/app/account-transfers/list-standing-instructions/list-standing-instructions.component.ts b/src/app/account-transfers/list-standing-instructions/list-standing-instructions.component.ts index b0e4f0aff..ae476ad0b 100644 --- a/src/app/account-transfers/list-standing-instructions/list-standing-instructions.component.ts +++ b/src/app/account-transfers/list-standing-instructions/list-standing-instructions.component.ts @@ -68,7 +68,6 @@ export class ListStandingInstructionsComponent implements OnInit { this.standingIntructionsTemplateData = data.standingIntructionsTemplate; if (data.standingIntructionsTemplate.fromClient) { this.clientName = this.standingIntructionsTemplateData.fromClient.displayName; - console.log('here'); this.getStandingInstructions(); } this.setParams(); diff --git a/src/app/core/shell/sidenav/sidenav.component.html b/src/app/core/shell/sidenav/sidenav.component.html index 098736766..4464ae862 100644 --- a/src/app/core/shell/sidenav/sidenav.component.html +++ b/src/app/core/shell/sidenav/sidenav.component.html @@ -97,6 +97,12 @@ Chart of Accounts + + + + + Help + diff --git a/src/app/core/shell/sidenav/sidenav.component.ts b/src/app/core/shell/sidenav/sidenav.component.ts index 917ac279f..3f55f0ae0 100644 --- a/src/app/core/shell/sidenav/sidenav.component.ts +++ b/src/app/core/shell/sidenav/sidenav.component.ts @@ -43,4 +43,8 @@ export class SidenavComponent implements OnInit { .subscribe(() => this.router.navigate(['/login'], { replaceUrl: true })); } + help() { + window.open('https://mifosforge.jira.com/wiki/spaces/docs/pages/52035622/User+Manual', '_blank'); + } + } diff --git a/src/app/core/shell/toolbar/toolbar.component.html b/src/app/core/shell/toolbar/toolbar.component.html index 39e584f33..f947bf1ad 100644 --- a/src/app/core/shell/toolbar/toolbar.component.html +++ b/src/app/core/shell/toolbar/toolbar.component.html @@ -49,6 +49,10 @@ + + @@ -100,7 +104,7 @@ Settings - - diff --git a/src/app/reports/xbrl-report/xbrl-report.component.html b/src/app/reports/xbrl-report/xbrl-report.component.html index e59125996..e58b3a1e6 100644 --- a/src/app/reports/xbrl-report/xbrl-report.component.html +++ b/src/app/reports/xbrl-report/xbrl-report.component.html @@ -24,7 +24,7 @@ - + diff --git a/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.html b/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.html new file mode 100644 index 000000000..238a57038 --- /dev/null +++ b/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.html @@ -0,0 +1,18 @@ +

Keyboard Shortcuts

+ +
+
+ +
+ + Ctrl + + Shift + + Alt + + {{ item.key }} + + {{ item.title }} +
+ +
+
+
diff --git a/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.scss b/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.scss new file mode 100644 index 000000000..a45d113be --- /dev/null +++ b/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.scss @@ -0,0 +1,11 @@ +.modifierKey { + border: 1px solid #0000004d; + padding: 0.3rem; + background: #f8f8f8; + font-weight: bold; + border-radius: 0.3rem; +} + +.mat-divider.mat-divider-inset { + margin-left: 0px; +} diff --git a/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.spec.ts b/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.spec.ts new file mode 100644 index 000000000..d5fbea511 --- /dev/null +++ b/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { KeyboardShortcutsDialogComponent } from './keyboard-shortcuts-dialog.component'; + +describe('KeyboardShortcutsDialogComponent', () => { + let component: KeyboardShortcutsDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ KeyboardShortcutsDialogComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(KeyboardShortcutsDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.ts b/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.ts new file mode 100644 index 000000000..f3bd2a90b --- /dev/null +++ b/src/app/shared/keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component.ts @@ -0,0 +1,28 @@ +/** Angular Imports */ +import { Component, OnInit, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { KeyboardShortcutsConfiguration } from '../../keyboards-shortcut-config'; +/** + * Delete dialog component. + */ +@Component({ + selector: 'mifosx-keyboard-shortcuts-dialog', + templateUrl: './keyboard-shortcuts-dialog.component.html', + styleUrls: ['./keyboard-shortcuts-dialog.component.scss'] +}) +export class KeyboardShortcutsDialogComponent implements OnInit { + + buttonConfig: KeyboardShortcutsConfiguration; + + /** + * @param {MatDialogRef} dialogRef Component reference to dialog. + * @param {any} data Provides a deleteContext. + */ + constructor(public dialogRef: MatDialogRef) { } + + ngOnInit() { + this.dialogRef.updateSize(`800px`); + this.buttonConfig = new KeyboardShortcutsConfiguration(); + } + +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 9ad6b1d6f..2e23e0cbb 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -15,6 +15,7 @@ import { ChangePasswordDialogComponent } from './change-password-dialog/change-p import { EnableDialogComponent } from './enable-dialog/enable-dialog.component'; import { DisableDialogComponent } from './disable-dialog/disable-dialog.component'; import { ConfirmationDialogComponent } from './confirmation-dialog/confirmation-dialog.component'; +import { KeyboardShortcutsDialogComponent } from './keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component'; /** Custom Modules */ import { IconsModule } from './icons.module'; @@ -43,7 +44,8 @@ import { MaterialModule } from './material.module'; ChangePasswordDialogComponent, EnableDialogComponent, DisableDialogComponent, - ConfirmationDialogComponent + ConfirmationDialogComponent, + KeyboardShortcutsDialogComponent ], exports: [ FileUploadComponent, @@ -62,7 +64,8 @@ import { MaterialModule } from './material.module'; ChangePasswordDialogComponent, EnableDialogComponent, DisableDialogComponent, - ConfirmationDialogComponent + ConfirmationDialogComponent, + KeyboardShortcutsDialogComponent ] }) export class SharedModule { } diff --git a/src/app/web-app.component.ts b/src/app/web-app.component.ts index 9c98cdbf6..c86333ce7 100644 --- a/src/app/web-app.component.ts +++ b/src/app/web-app.component.ts @@ -1,5 +1,5 @@ /** Angular Imports */ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, HostListener } from '@angular/core'; import { Router, NavigationEnd, ActivatedRoute } from '@angular/router'; import { Title } from '@angular/platform-browser'; import { MatSnackBar } from '@angular/material'; @@ -19,9 +19,11 @@ import { Logger } from './core/logger/logger.service'; import { I18nService } from './core/i18n/i18n.service'; import { ThemeStorageService } from './shared/theme-picker/theme-storage.service'; import { AlertService } from './core/alert/alert.service'; +import { KeyboardShortcutsConfiguration } from './keyboards-shortcut-config'; /** Custom Models */ import { Alert } from './core/alert/alert.model'; +import { AuthenticationService } from './core/authentication/authentication.service'; /** Initialize Logger */ const log = new Logger('MifosX'); @@ -36,6 +38,8 @@ const log = new Logger('MifosX'); }) export class WebAppComponent implements OnInit { + buttonConfig: KeyboardShortcutsConfiguration; + /** * @param {Router} router Router for navigation. * @param {ActivatedRoute} activatedRoute Activated Route. @@ -45,6 +49,7 @@ export class WebAppComponent implements OnInit { * @param {ThemeStorageService} themeStorageService Theme Storage Service. * @param {MatSnackBar} snackBar Material Snackbar for notifications. * @param {AlertService} alertService Alert Service. + * @param {AuthenticationService} authenticationService Authentication service. */ constructor(private router: Router, private activatedRoute: ActivatedRoute, @@ -53,7 +58,8 @@ export class WebAppComponent implements OnInit { private i18nService: I18nService, private themeStorageService: ThemeStorageService, public snackBar: MatSnackBar, - private alertService: AlertService) { } + private alertService: AlertService, + private authenticationService: AuthenticationService) { } /** * Initial Setup: @@ -126,6 +132,55 @@ export class WebAppComponent implements OnInit { verticalPosition: 'top' }); }); + this.buttonConfig = new KeyboardShortcutsConfiguration(); + } + + logout() { + this.authenticationService.logout() + .subscribe(() => this.router.navigate(['/login'], { replaceUrl: true })); + } + + help() { + window.open('https://mifosforge.jira.com/wiki/spaces/docs/pages/52035622/User+Manual', '_blank'); + } + + // Monitor all keyboard events and excute keyboard shortcuts + @HostListener('window:keydown', ['$event']) + onKeydownHandler(event: KeyboardEvent) { + const routeD = this.buttonConfig.buttonCombinations.find(x => (x.ctrlKey === event.ctrlKey && x.shiftKey === event.shiftKey && x.altKey === event.altKey && x.key === event.key)); + if (!(routeD === undefined)) { + switch (routeD.id) { + case 'logout': + this.logout(); + break; + case 'help': + this.help(); + break; + case 'runReport': + document.getElementById('runReport').click(); + break; + case 'cancel': + const cancelButtons = document.querySelectorAll('button'); + const filteredcancelButtons = Array.prototype.filter.call(cancelButtons, function (el: any) { + return el.textContent.trim() === 'Cancel'; + }); + if (filteredcancelButtons.length > 0) { + filteredcancelButtons[0].click(); + } + break; + case 'submit': + const submitButton = document.querySelectorAll('button'); + const filteredSubmitButton = Array.prototype.filter.call(submitButton, function (el: any) { + return el.textContent.trim() === 'Submit'; + }); + if (filteredSubmitButton.length > 0) { + filteredSubmitButton[0].click(); + } + break; + default: + this.router.navigate([routeD.route], { relativeTo: this.activatedRoute }); + } + } } } diff --git a/src/assets/images/keyboard_placeholder.png b/src/assets/images/keyboard_placeholder.png new file mode 100644 index 000000000..8570ba12f Binary files /dev/null and b/src/assets/images/keyboard_placeholder.png differ