LP1812414 Keyboard shortcut to log out collab/sleary/lp1812414-logout-shortcut
authorStephanie Leary <stephanie.leary@equinoxoli.org>
Wed, 3 May 2023 20:25:31 +0000 (20:25 +0000)
committerStephanie Leary <stephanie.leary@equinoxoli.org>
Fri, 5 May 2023 15:33:57 +0000 (15:33 +0000)
Allows the user to log out by pressing Alt + Shift + Q.

Also adds an optional confirmation dialog to keyboard shortcuts. If a
confirmation message is given as an input, a confirmation dialog will be
shown using that message, and the user must confirm before the action is
performed.

Logging out is currently the only keyboard shortcut that requires a
confirmation.

Signed-off-by: Stephanie Leary <stephanie.leary@equinoxoli.org>
Open-ILS/src/eg2/src/app/share/accesskey/accesskey.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/accesskey/accesskey.directive.ts [deleted file]
Open-ILS/src/eg2/src/app/share/accesskey/accesskey.service.ts
Open-ILS/src/eg2/src/app/staff/common.module.ts
Open-ILS/src/eg2/src/app/staff/nav.component.html

diff --git a/Open-ILS/src/eg2/src/app/share/accesskey/accesskey.component.ts b/Open-ILS/src/eg2/src/app/share/accesskey/accesskey.component.ts
new file mode 100644 (file)
index 0000000..ba94d29
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * Assign access keys to <a> tags.
+ *
+ * Access key action is peformed via .click(). hrefs, routerLinks,
+ * and (click) actions are all supported.
+ *
+ *   <a
+ *     routerLink="/staff/splash"
+ *     egAccessKey
+ *     keySpec="alt+h" i18n-keySpec
+ *     keyDesc="My Description" 18n-keyDesc
+ *   >
+ */
+import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
+import { ConfirmDialogComponent } from '@eg/share/dialog/confirm.component';
+import { AccessKeyService } from '@eg/share/accesskey/accesskey.service';
+
+@Component({
+  selector: '[egAccessKey]',
+  template: '<eg-confirm-dialog #confirmDialog dialogBody="{{confirm}}" i18n-dialogBody></eg-confirm-dialog>'
+})
+export class AccessKeyComponent implements OnInit {
+
+    // Space-separated list of key combinations
+    // E.g. "ctrl+h", "alt+h ctrl+y"
+    @Input() keySpec: string;
+
+    // Description to display in the accesskey info dialog
+    @Input() keyDesc: string;
+
+    // Context info to display in the accesskey info dialog
+    // E.g. "navbar"
+    @Input() keyCtx: string;
+
+    // Optional; if set, a confirmation dialog will be shown
+    // and the click() action will be performed on confirmation
+    @Input() confirm?: string;
+
+    @ViewChild('confirmDialog', { static: true }) confirmDialog: ConfirmDialogComponent;
+
+    constructor(
+        private elm: ElementRef,
+        private keyService: AccessKeyService
+    ) { }
+
+    ngOnInit() {
+
+        if (!this.keySpec) {
+            console.warn('AccessKey no keySpec provided');
+            return;
+        }
+
+        this.keySpec.split(/ /).forEach(keySpec => {
+            this.keyService.assign({
+                key: keySpec,
+                desc: this.keyDesc,
+                ctx: this.keyCtx,
+                action: () => {
+                    // if a confirmation message was specified, show the dialog
+                    if (this.confirm && this.confirm.length > 0) {
+                        this.confirmDialog.open().subscribe(confirmed => {
+                            if (!confirmed) { return; }
+
+                            // confirmed? now we do the click()
+                            this.elm.nativeElement.click();
+                        });
+                    }
+                    // if no confirmation message was given, just do the click()
+                    else
+                        this.elm.nativeElement.click();
+                }
+            });
+        });
+    }
+}
+
+
diff --git a/Open-ILS/src/eg2/src/app/share/accesskey/accesskey.directive.ts b/Open-ILS/src/eg2/src/app/share/accesskey/accesskey.directive.ts
deleted file mode 100644 (file)
index dfc835d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Assign access keys to <a> tags.
- *
- * Access key action is peformed via .click(). hrefs, routerLinks,
- * and (click) actions are all supported.
- *
- *   <a
- *     routerLink="/staff/splash"
- *     egAccessKey
- *     keySpec="alt+h" i18n-keySpec
- *     keyDesc="My Description" 18n-keyDesc
- *   >
- */
-import {Directive, ElementRef, Input, OnInit} from '@angular/core';
-import {AccessKeyService} from '@eg/share/accesskey/accesskey.service';
-
-@Directive({
-  selector: '[egAccessKey]'
-})
-export class AccessKeyDirective implements OnInit {
-
-    // Space-separated list of key combinations
-    // E.g. "ctrl+h", "alt+h ctrl+y"
-    @Input() keySpec: string;
-
-    // Description to display in the accesskey info dialog
-    @Input() keyDesc: string;
-
-    // Context info to display in the accesskey info dialog
-    // E.g. "navbar"
-    @Input() keyCtx: string;
-
-    constructor(
-        private elm: ElementRef,
-        private keyService: AccessKeyService
-    ) { }
-
-    ngOnInit() {
-
-        if (!this.keySpec) {
-            console.warn('AccessKey no keySpec provided');
-            return;
-        }
-
-        this.keySpec.split(/ /).forEach(keySpec => {
-            this.keyService.assign({
-                key: keySpec,
-                desc: this.keyDesc,
-                ctx: this.keyCtx,
-                action: () => this.elm.nativeElement.click()
-            });
-        });
-    }
-}
-
-
index 3b73234..dcb4736 100644 (file)
@@ -6,6 +6,7 @@ export interface AccessKeyAssignment {
     ctx: string;      // template context
     action: Function; // handler function
     shadowed?: boolean; // Has this assignemnt been shadowed by another.
+    confirm?: string;   // If present, a confirm dialog is required before the click() action runs.
 }
 
 @Injectable()
index 853576f..608f482 100644 (file)
@@ -5,7 +5,7 @@ import {AudioService} from '@eg/share/util/audio.service';
 import {GridModule} from '@eg/share/grid/grid.module';
 import {CatalogCommonModule} from '@eg/share/catalog/catalog-common.module';
 import {StaffBannerComponent} from './share/staff-banner.component';
-import {AccessKeyDirective} from '@eg/share/accesskey/accesskey.directive';
+import {AccessKeyComponent} from '@eg/share/accesskey/accesskey.component';
 import {AccessKeyService} from '@eg/share/accesskey/accesskey.service';
 import {AccessKeyInfoComponent} from '@eg/share/accesskey/accesskey-info.component';
 import {OpChangeComponent} from '@eg/staff/share/op-change/op-change.component';
@@ -33,7 +33,7 @@ import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-loca
 @NgModule({
   declarations: [
     StaffBannerComponent,
-    AccessKeyDirective,
+    AccessKeyComponent,
     AccessKeyInfoComponent,
     TitleComponent,
     OpChangeComponent,
@@ -61,7 +61,7 @@ import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-loca
     GridModule,
     CatalogCommonModule,
     StaffBannerComponent,
-    AccessKeyDirective,
+    AccessKeyComponent,
     AccessKeyInfoComponent,
     TitleComponent,
     OpChangeComponent,
index facd33c..d7ad618 100644 (file)
             <span class="material-icons" aria-hidden="true">transform</span>
             <span i18n>Restore Operator</span>
           </a>
-          <a class="dropdown-item" (click)="logout()">
+          <a class="dropdown-item" (click)="logout()"
+              egAccessKey keyCtx="navbar" i18n-keySpec i18n-keyDesc i18n-confirm
+              keySpec="alt+shift+q" keyDesc="Logout (Quit)" confirm="Log out now?">
             <span class="material-icons" aria-hidden="true">lock_outline</span>
             <span i18n>Logout</span>
           </a>