LP1948693 Migrate from NgbTabset to ngbNav
authorStephanie Leary <stephanie.leary@equinoxOLI.org>
Wed, 19 Oct 2022 20:49:41 +0000 (15:49 -0500)
committerBill Erickson <berickxx@gmail.com>
Mon, 26 Dec 2022 15:13:40 +0000 (10:13 -0500)
Updates the deprecated NgbTabset components to ngbNav and adds directive
for keyboard navigation.

See https://gist.github.com/stephanieleary/800b9f2b1d9c08cc66d694daaa1788b9 for
a quick guide to the markup changes involved.

Screens to test:

1. /staff/acq/provider, right click an existing provider to show details tabs
2. /staff/admin/local/negative-balances
3. /staff/admin/local/action/survey, edit an existing survey, test Edit Survey
and Q&A tabs
4. /staff/admin/server/actor/org_unit, note that Addresses tab has a second set
of tabs underneath
5. /staff/admin/server/actor/org_unit_type, note that eg-tree has also changed
here
6. /staff/admin/server/permission/grp_tree, choose a group to see tabs
7. /staff/admin/server/config/print_template
8. /staff/booking/create_reservation
9. /staff/booking/manage_reservations, filter reservations section
10. /staff/booking/return
11. /staff/cat/authority/browse
12. /staff/cat/vandelay/import and all import/export tabs
13. /staff/cat/bucket/record/view
14. /staff/catalog/search
15. /staff/circ/holds/pull-list, right click a hold, choose Show Hold Details,
the tabs are at the bottom of the screen

Test plan:

Note that you cannot navigate tabbed interfaces using the tab key on your
keyboard.

Apply the patch, then visit the screens listed above.

You should be able to use the tab key to move sequentially through all the tabs.
Pressing Enter on an inactive tab should make it active, just as clicking it
would. You should not be able to click or press Enter to activate a disabled
tab.

You should be able to move from the last tab in the list into the first
focusable element in the active tab's content panel. If you spot a tab content
panel that doesn't contain a focusable element (i.e. links or inputs), let me
know; we have to set its tabindex attribute manually.

If a tab panel contains a second set of tabs, these should work as well.

Note on ARIA and roles:

Note that neither Bootstrap 5 nor ng-bootstrap are currently following the ARIA
Authoring Practices Guide for tabs with manual activation (the recommended
pattern for tab panels with complicated content, like form inputs or data
tables), which does not recommend sequential movement:
https://www.w3.org/WAI/ARIA/apg/example-index/tabs/tabs-manual.html. Therefore,
we aren't following this pattern either. We can revisit this and/or take it up
with Bootstrap.

For now, running axe DevTools on any screen with navs will show ARIA role errors
on role="tab" attributes. We are using ng-bootstrap's default ARIA roles for
tabs, but they are incorrect. I am trying to get traction on a pull request to
change the problem in ng-bootstrap, but in the meantime, we are not using the
automatic [roles] directive. Role attributes have been set explicitly on all
tabs and their containing elements.

Note on eg-tree CSS:

In the Org Unit Type screens, there was previously some inline CSS related to
eg-tree that was causing compiler errors. I have moved this to a separate CSS
file, and will revisit eg-tree styles more generally in another upcoming
project.

Signed-off-by: Stephanie Leary <stephanie.leary@equinoxOLI.org>
Signed-off-by: Bill Erickson <berickxx@gmail.com>
66 files changed:
Open-ILS/src/eg2/src/app/staff/acq/lineitem/detail.component.html
Open-ILS/src/eg2/src/app/staff/acq/provider/acq-provider.component.html
Open-ILS/src/eg2/src/app/staff/acq/provider/acq-provider.component.ts
Open-ILS/src/eg2/src/app/staff/acq/search/acq-search.component.html
Open-ILS/src/eg2/src/app/staff/admin/acq/claiming-admin.component.html
Open-ILS/src/eg2/src/app/staff/admin/acq/funds/fund-details-dialog.component.html
Open-ILS/src/eg2/src/app/staff/admin/acq/funds/funding-source-transactions-dialog.component.html
Open-ILS/src/eg2/src/app/staff/admin/acq/funds/funds.component.html
Open-ILS/src/eg2/src/app/staff/admin/local/cash-reports/cash-reports.component.html
Open-ILS/src/eg2/src/app/staff/admin/local/circ_limit_set/circ_limit_set_edit.component.html
Open-ILS/src/eg2/src/app/staff/admin/local/copy-loc-order/copy-loc-order.component.ts
Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-material.component.html
Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html
Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.html
Open-ILS/src/eg2/src/app/staff/admin/local/negative-balances/list.component.ts
Open-ILS/src/eg2/src/app/staff/admin/local/survey/survey-edit.component.html
Open-ILS/src/eg2/src/app/staff/admin/local/survey/survey-edit.component.ts
Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.html
Open-ILS/src/eg2/src/app/staff/admin/local/triggers/triggers.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/org-addr.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/org-addr.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/org-unit.component.css [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/admin/server/org-unit.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/org-unit.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/perm-group-tree.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/perm-group-tree.component.ts
Open-ILS/src/eg2/src/app/staff/admin/server/print-template.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/print-template.component.ts
Open-ILS/src/eg2/src/app/staff/booking/create-reservation.component.html
Open-ILS/src/eg2/src/app/staff/booking/create-reservation.component.ts
Open-ILS/src/eg2/src/app/staff/booking/manage-reservations.component.html
Open-ILS/src/eg2/src/app/staff/booking/manage-reservations.component.ts
Open-ILS/src/eg2/src/app/staff/booking/return.component.html
Open-ILS/src/eg2/src/app/staff/booking/return.component.ts
Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.html
Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.ts
Open-ILS/src/eg2/src/app/staff/cat/vandelay/display-attrs.component.html
Open-ILS/src/eg2/src/app/staff/cat/vandelay/display-attrs.component.ts
Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set.component.html
Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set.component.ts
Open-ILS/src/eg2/src/app/staff/cat/vandelay/queued-record.component.html
Open-ILS/src/eg2/src/app/staff/cat/vandelay/queued-record.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.component.html
Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html
Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.css
Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.html
Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.ts
Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.ts
Open-ILS/src/eg2/src/app/staff/circ/item/event-log/event-log.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/bill-statement.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/billing-history.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/edit.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/event-log/event-log.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/holds.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/items.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/patron.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/perms.component.html
Open-ILS/src/eg2/src/app/staff/reporter/simple/simple-reporter.component.html
Open-ILS/src/eg2/src/app/staff/reporter/simple/sr-editor.component.html
Open-ILS/src/eg2/src/app/staff/share/buckets/bucket-dialog.component.html
Open-ILS/src/eg2/src/app/staff/share/holds/detail.component.html
Open-ILS/src/eg2/src/app/staff/share/marc-edit/editor.component.html
Open-ILS/src/eg2/src/styles.css

index 386dfc1..ed3ad66 100644 (file)
@@ -1,8 +1,8 @@
 <hr class="p-1"/>
 
-<ul ngbNav #liDetailNav="ngbNav" class="nav-tabs">
-  <li ngbNavItem="attrs">
-    <a ngbNavLink i18n>Attributes</a>
+<ul ngbNav #liDetailNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+  <li role="presentation" ngbNavItem="attrs">
+    <a role="tab" ngbNavLink i18n role="tab">Attributes</a>
     <ng-template ngbNavContent>
       <ng-container *ngIf="lineitem">
         <div class="mt-3">
@@ -14,8 +14,8 @@
       </ng-container>
     </ng-template>
   </li>
-  <li ngbNavItem="marc-html">
-    <a ngbNavLink i18n>MARC View</a>
+  <li role="presentation" ngbNavItem="marc-html">
+    <a role="tab" ngbNavLink i18n>MARC View</a>
     <ng-template ngbNavContent>
       <ng-container *ngIf="lineitem">
         <div class="mt-3">
@@ -25,8 +25,8 @@
       </ng-container>
     </ng-template>
   </li>
-  <li ngbNavItem="marc-edit">
-    <a ngbNavLink i18n>MARC Edit</a>
+  <li role="presentation" ngbNavItem="marc-edit">
+    <a role="tab" ngbNavLink i18n>MARC Edit</a>
     <ng-template ngbNavContent>
       <ng-container *ngIf="lineitem">
         <div class="mt-3">
index d769a72..30fa372 100644 (file)
 <div class="col">
 <div class="row" id="acq-provider-page" [hidden]="!id">
   <div class="col-lg-12">
-    <ngb-tabset #acqProviderTabs [activeId]="activeTab" (tabChange)="onTabChange($event)">
-      <ngb-tab title="Provider" i18n-title id="details" [disabled]="!id">
-        <ng-template ngbTabContent>
+    <ul ngbNav #acqProviderTabs="ngbNav" [(activeId)]="activeTab" (navChange)="onNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+      <li role="presentation" [ngbNavItem]="'details'" [disabled]="!id">
+        <a i18n ngbNavLink role="tab">Provider</a>
+        <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-12 text-right pb-1">
               <button class="btn btn-secondary btn-sm" [disabled]="activeTab === defaultTabType"
           </div>
           <eg-provider-details #providerDetails (desireSummarize)="onDesireSummarize($event, true)"></eg-provider-details>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Addresses" i18n-title id="addresses" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'addresses'" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
+        <a i18n ngbNavLink role="tab">Addresses</a>
+        <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-12 text-right pb-1">
               <button class="btn btn-secondary btn-sm" [disabled]="activeTab === defaultTabType"
           </div>
           <eg-provider-addresses></eg-provider-addresses>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Contacts" i18n-title id="contacts" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'contacts'" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
+        <a i18n ngbNavLink role="tab">Contacts</a>
+          <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-12 text-right pb-1">
               <button class="btn btn-secondary btn-sm" [disabled]="activeTab === defaultTabType"
           </div>
           <eg-provider-contacts (desireSummarize)="onDesireSummarize($event, true)"></eg-provider-contacts>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Attribute Definitions" i18n-title id="attributes" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'attributes'" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
+        <a i18n ngbNavLink role="tab">Attribute Definitions</a>
+        <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-12 text-right pb-1">
               <button class="btn btn-secondary btn-sm" [disabled]="activeTab === defaultTabType"
           </div>
           <eg-provider-attributes></eg-provider-attributes>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Holdings Definitions" i18n-title id="holdings" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'holdings'" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
+        <a i18n ngbNavLink role="tab">Holdings Definitions</a>
+        <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-12 text-right pb-1">
               <button class="btn btn-secondary btn-sm" [disabled]="activeTab === defaultTabType"
           </div>
           <eg-provider-holdings #providerHoldings></eg-provider-holdings>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="EDI" i18n-title id="edi_accounts" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'edi_accounts'" [disabled]="!id || !this.providerRecord.currentProvider || !this.providerRecord.currentProvider.canAdmin">
+        <a i18n ngbNavLink role="tab">EDI</a>
+        <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-12 text-right pb-1">
               <button class="btn btn-secondary btn-sm" [disabled]="activeTab === defaultTabType"
           </div>
           <eg-provider-edi-accounts (desireSummarize)="onDesireSummarize($event, true)"></eg-provider-edi-accounts>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Invoices" i18n-title id="invoices" [disabled]="!id">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'invoices'" [disabled]="!id">
+        <a i18n ngbNavLink role="tab">Invoices</a>
+        <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-12 text-right pb-1">
               <button class="btn btn-secondary btn-sm" [disabled]="activeTab === defaultTabType"
           </div>
           <eg-provider-invoices></eg-provider-invoices>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="POs" i18n-title id="purchase_orders" [disabled]="!id">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'purchase_orders'" [disabled]="!id">
+        <a i18n ngbNavLink role="tab">POs</a>
+        <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-12 text-right pb-1">
               <button class="btn btn-secondary btn-sm" [disabled]="activeTab === defaultTabType"
           </div>
           <eg-provider-purchase-orders></eg-provider-purchase-orders>
         </ng-template>
-      </ngb-tab>
-    </ngb-tabset>
+      </li>
+    </ul>
+
+    <div [ngbNavOutlet]="acqProviderTabs" class="mt-2"></div>
   </div>
 </div>
 </div>
index 159bcb9..53228fa 100644 (file)
@@ -1,7 +1,7 @@
 import {Component, OnInit, AfterViewInit, ViewChild, ChangeDetectorRef, OnDestroy} from '@angular/core';
 import {filter, takeUntil} from 'rxjs/operators';
 import {Subject, Observable, of} from 'rxjs';
-import {NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {Router, ActivatedRoute, ParamMap, RouterEvent, NavigationEnd} from '@angular/router';
 import {IdlService} from '@eg/core/idl.service';
 import {AcqProviderSummaryPaneComponent} from './summary-pane.component';
@@ -36,7 +36,7 @@ export class AcqProviderComponent implements OnInit, AfterViewInit, OnDestroy {
     @ViewChild('createErrString', { static: false }) createErrString: StringComponent;
     @ViewChild('leaveConfirm', { static: true }) leaveConfirm: ConfirmDialogComponent;
 
-    onTabChange: ($event: NgbTabChangeEvent) => void;
+    onNavChange: ($event: NgbNavChangeEvent) => void;
 
     onDesireSummarize: ($event: number, updateSummaryOnly?: boolean, hideSearchForm?: boolean) => void;
     onSummaryToggled: ($event: boolean) => void;
@@ -112,7 +112,7 @@ export class AcqProviderComponent implements OnInit, AfterViewInit, OnDestroy {
             this.showSearchForm = true;
         }
 
-        this.onTabChange = ($event) => {
+        this.onNavChange = ($event) => {
             $event.preventDefault();
             this.canDeactivate().subscribe(canLeave => {
                 if (!canLeave) { return; }
index 1decc23..1f9798c 100644 (file)
@@ -6,21 +6,21 @@
 </div>
 <div class="row" id="acq-search-page">
   <div class="col-lg-12">
-    <ul ngbNav #acqSearchTabs="ngbNav" class="nav-tabs" [(activeId)]="searchType" (navChange)="onTabChange($event)">
-      <li [ngbNavItem]="'lineitems'">
-        <a ngbNavLink i18n>Line Items Search</a>
+    <ul ngbNav #acqSearchTabs="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist" [(activeId)]="searchType" (navChange)="onTabChange($event)">
+      <li role="presentation" [ngbNavItem]="'lineitems'">
+        <a role="tab" ngbNavLink i18n>Line Items Search</a>
         <ng-template ngbNavContent><eg-lineitem-results [initialSearchTerms]="urlSearchTerms"></eg-lineitem-results></ng-template>
       </li>
-      <li [ngbNavItem]="'purchaseorders'">
-        <a ngbNavLink i18n>Purchase Orders Search</a>
+      <li role="presentation" [ngbNavItem]="'purchaseorders'">
+        <a role="tab" ngbNavLink i18n>Purchase Orders Search</a>
         <ng-template ngbNavContent><eg-purchase-order-results [initialSearchTerms]="urlSearchTerms"></eg-purchase-order-results></ng-template>
       </li>
-      <li [ngbNavItem]="'invoices'">
-        <a ngbNavLink i18n>Invoices Search</a>
+      <li role="presentation" [ngbNavItem]="'invoices'">
+        <a role="tab" ngbNavLink i18n>Invoices Search</a>
         <ng-template ngbNavContent><eg-invoice-results [initialSearchTerms]="urlSearchTerms"></eg-invoice-results></ng-template>
       </li>
-      <li [ngbNavItem]="'selectionlists'">
-        <a ngbNavLink i18n>Selection Lists Search</a>
+      <li role="presentation" [ngbNavItem]="'selectionlists'">
+        <a role="tab" ngbNavLink i18n>Selection Lists Search</a>
         <ng-template ngbNavContent><eg-picklist-results [initialSearchTerms]="urlSearchTerms"></eg-picklist-results></ng-template>
       </li>
     </ul>
index 922b85c..38b4e06 100644 (file)
@@ -3,33 +3,33 @@
 
 <eg-title i18n-prefix prefix="Claiming Administration"></eg-title>
 
-<ul ngbNav #claimingAdminNav="ngbNav" class="nav-tabs">
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Claim Policies</a>
+<ul ngbNav #claimingAdminNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Claim Policies</a>
     <ng-template ngbNavContent>
       <div class="mt-2">
         <eg-admin-page idlClass="acqclp"></eg-admin-page>
        </div>
     </ng-template>
   </li>
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Claim Policy Actions</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Claim Policy Actions</a>
     <ng-template ngbNavContent>
       <div class="mt-2">
         <eg-admin-page idlClass="acqclpa"></eg-admin-page>
        </div>
     </ng-template>
   </li>
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Claim Event Types</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Claim Event Types</a>
     <ng-template ngbNavContent>
       <div class="mt-2">
         <eg-admin-page idlClass="acqclet"></eg-admin-page>
        </div>
     </ng-template>
   </li>
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Claim Types</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Claim Types</a>
     <ng-template ngbNavContent>
       <div class="mt-2">
         <eg-admin-page idlClass="acqclt"></eg-admin-page>
index 86bfa78..2b29dc1 100644 (file)
@@ -34,9 +34,9 @@
           (click)="setDefaultTab()" i18n>Set Default View</button>
       </div>
     </div>
-    <ul ngbNav #fundDetailsNav="ngbNav" [(activeId)]="activeTab" class="nav-tabs">
-      <li [ngbNavItem]="'summary'" *ngIf="fund">
-        <a ngbNavLink i18n>Summary</a>
+    <ul ngbNav #fundDetailsNav="ngbNav" [(activeId)]="activeTab" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+      <li role="presentation" [ngbNavItem]="'summary'" *ngIf="fund">
+        <a role="tab" ngbNavLink i18n>Summary</a>
         <ng-template ngbNavContent>
           <div class="mt-2">
             <div class="row">
@@ -69,8 +69,8 @@
           </div>
         </ng-template>
       </li>
-      <li [ngbNavItem]="'allocations'" *ngIf="fund">
-        <a ngbNavLink i18n>Allocations</a>
+      <li role="presentation" [ngbNavItem]="'allocations'" *ngIf="fund">
+        <a role="tab" ngbNavLink i18n>Allocations</a>
         <ng-template ngbNavContent>
           <div class="mt-2">
             <eg-grid #fundDetailsAllocationsGrid idlClass="acqfa" [dataSource]="acqfaDataSource"
@@ -94,8 +94,8 @@
           </div>
         </ng-template>
       </li>
-      <li [ngbNavItem]="'transfers'" *ngIf="fund">
-        <a ngbNavLink i18n>Transfers</a>
+      <li role="presentation" [ngbNavItem]="'transfers'" *ngIf="fund">
+        <a role="tab" ngbNavLink i18n>Transfers</a>
         <ng-template ngbNavContent>
           <div class="mt-2">
             <eg-grid #fundDetailsTransfersGrid idlClass="acqftr" [dataSource]="acqftrDataSource"
            </div>
         </ng-template>
       </li>
-      <li [ngbNavItem]="'debits'" *ngIf="fund">
-        <a ngbNavLink i18n>Debits</a>
+      <li role="presentation" [ngbNavItem]="'debits'" *ngIf="fund">
+        <a role="tab" ngbNavLink i18n>Debits</a>
         <ng-template ngbNavContent>
           <div class="mt-2">
             <eg-grid #fundDetailsDebitsGrid idlClass="acqfdeb" [dataSource]="acqfdebDataSource"
            </div>
         </ng-template>
       </li>
-      <li [ngbNavItem]="'tags'" *ngIf="fund">
-        <a ngbNavLink i18n>Tags</a>
+      <li role="presentation" [ngbNavItem]="'tags'" *ngIf="fund">
+        <a role="tab" ngbNavLink i18n>Tags</a>
         <ng-template ngbNavContent>
           <div class="mt-2">
             <eg-fund-tags [fundId]="fundId" [fundOwner]="fund.org()"></eg-fund-tags>
index 22d4495..7225ac4 100644 (file)
@@ -20,9 +20,9 @@
     </button>
   </div>
   <div class="modal-body" *ngIf="fundingSource">
-    <ul ngbNav #fundingSourceTransactionsNav="ngbNav" [(activeId)]="activeTab" class="nav-tabs">
-      <li [ngbNavItem]="'credits'">
-        <a ngbNavLink i18n>Credits</a>
+    <ul ngbNav #fundingSourceTransactionsNav="ngbNav" [(activeId)]="activeTab" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+      <li role="presentation" [ngbNavItem]="'credits'">
+        <a role="tab" ngbNavLink i18n>Credits</a>
         <ng-template ngbNavContent>
            <div class="mt-2">
             <eg-grid #creditsGrid idlClass="acqfscred" [dataSource]="acqfscredDataSource"
@@ -42,8 +42,8 @@
           </div>
         </ng-template>
       </li>
-      <li [ngbNavItem]="'allocations'">
-        <a ngbNavLink i18n>Allocations</a>
+      <li role="presentation" [ngbNavItem]="'allocations'">
+        <a role="tab" ngbNavLink i18n>Allocations</a>
         <ng-template ngbNavContent>
           <div class="mt-2">
             <eg-grid #allocationsGrid idlClass="acqfa" [dataSource]="acqfaDataSource"
index 0e4cea9..30c31be 100644 (file)
@@ -4,25 +4,25 @@
 <eg-title i18n-prefix prefix="Fund Administration"></eg-title>
 
 <ul ngbNav #claimingAdminNav="ngbNav" class="nav-tabs" [(activeId)]="activeTab"
-    (navChange)="onNavChange($event)">
-  <li [ngbNavItem]="'fund'">
-    <a ngbNavLink i18n>Funds</a>
+    (navChange)="onNavChange($event)" [keyboard]="true" [roles]="false" role="tablist">
+  <li role="presentation" [ngbNavItem]="'fund'">
+    <a role="tab" ngbNavLink i18n>Funds</a>
     <ng-template ngbNavContent>
       <div class="mt-2">
         <eg-funds-manager [startId]="fundId"></eg-funds-manager>
        </div>
     </ng-template>
   </li>
-  <li [ngbNavItem]="'funding_source'">
-    <a ngbNavLink i18n>Funding Sources</a>
+  <li role="presentation" [ngbNavItem]="'funding_source'">
+    <a role="tab" ngbNavLink i18n>Funding Sources</a>
     <ng-template ngbNavContent>
       <div class="mt-2">
         <eg-funding-sources [startId]="fundingSourceId"></eg-funding-sources>
        </div>
     </ng-template>
   </li>
-  <li [ngbNavItem]="'fund_tag'">
-    <a ngbNavLink i18n>Fund Tags</a>
+  <li role="presentation" [ngbNavItem]="'fund_tag'">
+    <a role="tab" ngbNavLink i18n>Fund Tags</a>
     <ng-template ngbNavContent>
       <div class="mt-2">
         <eg-admin-page idlClass="acqft"></eg-admin-page>
index 37023f2..45e6590 100644 (file)
   </div>
 </div>
 
-<ul ngbNav #cashReportsNav="ngbNav" class="nav-tabs"
+<ul ngbNav #cashReportsNav="ngbNav" class="nav-tabs"  [keyboard]="true" [roles]="false" role="tablist"
   [destroyOnHide]="false" activeId="deskPayments" (navChange)="eraseUserGrid()">
-  <li ngbNavItem="deskPayments">
-    <a ngbNavLink i18n>Desk Payments</a>
+  <li role="presentation" ngbNavItem="deskPayments">
+    <a role="tab" ngbNavLink i18n>Desk Payments</a>
     <ng-template ngbNavContent>
       <div class="mt-3">
         <div class="row">
@@ -66,8 +66,8 @@
       </div>
     </ng-template>
   </li>
-  <li ngbNavItem="userPayments">
-    <a ngbNavLink i18n>Staff User Payments</a>
+  <li role="presentation" ngbNavItem="userPayments">
+    <a role="tab" ngbNavLink i18n>Staff User Payments</a>
     <ng-template ngbNavContent>
       <div class="mt-3">
         <div class="row">
index edeb545..9a14a87 100644 (file)
@@ -1,10 +1,10 @@
 <eg-staff-banner bannerText="Circulation Limit Set - {{recordName}}" i18n-bannerText>
 </eg-staff-banner>
 
-<ul ngbNav #editNav="ngbNav" class="nav-tabs mb-3"
+<ul ngbNav #editNav="ngbNav" class="nav-tabs mb-3" [keyboard]="true" [roles]="false" role="tablist"
     [activeId]="circTab" (navChange)="onTabChange($event)">
-    <li [ngbNavItem]="'limitSet'">
-        <a ngbNavLink i18n>Edit Circulation Limit Set</a>
+    <li role="presentation" [ngbNavItem]="'limitSet'">
+        <a role="tab" ngbNavLink i18n>Edit Circulation Limit Set</a>
         <ng-template ngbNavContent>
             <div class="col-lg-6 offset-lg-3 mt-3">
                 <eg-fm-record-editor displayMode="inline" 
@@ -14,8 +14,8 @@
             </div> 
         </ng-template>
     </li>
-    <li [ngbNavItem]="'linked'">
-        <a ngbNavLink i18n>Edit Linked Entities</a>
+    <li role="presentation" [ngbNavItem]="'linked'">
+        <a role="tab" ngbNavLink i18n>Edit Linked Entities</a>
         <ng-template ngbNavContent>
             <div class="row mt-3">
                 <div class="col-lg-4">
index fb9eb4e..3ac42bc 100644 (file)
@@ -1,7 +1,7 @@
 import {Component, Input, ViewChild, OnInit} from '@angular/core';
 import {tap, concatMap} from 'rxjs/operators';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {OrgService} from '@eg/core/org.service';
 import {AuthService} from '@eg/core/auth.service';
 import {PcrudService} from '@eg/core/pcrud.service';
index f165d26..7f74dc1 100644 (file)
@@ -31,9 +31,9 @@
   <div [ngClass]="isDialog() ? 'modal-body' : ''">
     <div class="row">
       <div [ngClass]="isDialog() ? 'col-md-12' : 'col-md-4'">
-        <ul ngbNav #associateNav="ngbNav" class="nav-tabs">
-          <li ngbNavItem>
-            <a ngbNavLink i18n>Associate item</a>
+        <ul ngbNav #associateNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+          <li role="presentation" ngbNavItem>
+            <a role="tab" ngbNavLink i18n>Associate item</a>
             <ng-template ngbNavContent>
               <div class="row" [ngClass]="isDialog() ? '' : 'mt-3'">
                 <div class="d-flex" [ngClass]="isDialog() ? 'col-md-6' : 'col-md-12'">
               </div>
             </ng-template>
           </li>
-          <li ngbNavItem>
-            <a ngbNavLink i18n>Associate brief record</a>
+          <li role="presentation" ngbNavItem>
+            <a role="tab" ngbNavLink i18n>Associate brief record</a>
             <ng-template ngbNavContent>
               <div class="d-flex" [ngClass]="isDialog() ? 'col-md-6' : 'col-md-12 mt-3'">
                 <div class="input-group">
               </eg-marc-simplified-editor>
             </ng-template>
           </li>
-          <li ngbNavItem>
-            <a ngbNavLink>Associate electronic resource from catalog</a>
+          <li role="presentation" ngbNavItem>
+            <a ngbNavLink role="tab">Associate electronic resource from catalog</a>
             <ng-template ngbNavContent>
               <div class="row" [ngClass]="isDialog() ? '' : 'mt-3'">
                 <div class="d-flex" [ngClass]="isDialog() ? 'col-md-6' : 'col-md-12 mt-3'">
index e2e1315..97ecff8 100644 (file)
@@ -11,9 +11,9 @@
 <eg-string #unarchiveSuccessString i18n-text text="Unarchiving of {{tableName}} succeeded"></eg-string>
 <eg-string #flairTooltip i18n-text text="Limited Editing"></eg-string>
 
-<ul ngbNav #courseListNav="ngbNav" class="nav-tabs">
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Course list</a>
+<ul ngbNav #courseListNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Course list</a>
     <ng-template ngbNavContent>
       <div class="row">
         <div class="col-lg-6">
       </div>
     </ng-template>
   </li>
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Terms</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Terms</a>
     <ng-template ngbNavContent>
       <eg-course-term-grid></eg-course-term-grid>
     </ng-template>
   </li>
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Course roles</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Course roles</a>
     <ng-template ngbNavContent>
       <eg-admin-page idlClass="acmr"></eg-admin-page>
     </ng-template>
index d8bae1b..0310f2c 100644 (file)
     </a>
   </div>
 </div>
-<ul ngbNav #coursePageNav="ngbNav" class="nav-tabs">
+<ul ngbNav #coursePageNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
 
   <!-- Edit Tab -->
-  <li [ngbNavItem]="'edit'">
-    <a ngbNavLink i18n>Edit course</a>
+  <li role="presentation" [ngbNavItem]="'edit'">
+    <a role="tab" ngbNavLink i18n>Edit course</a>
     <ng-template ngbNavContent>
       <div class="row">
         <div class="col-lg-3 mt-3">
@@ -45,8 +45,8 @@
   </li>
 
   <!-- Materials Tab -->
-  <li [ngbNavItem]="'courseMaterials'">
-    <a ngbNavLink i18n>Course materials</a>
+  <li role="presentation" [ngbNavItem]="'courseMaterials'">
+    <a role="tab" ngbNavLink i18n>Course materials</a>
     <ng-template ngbNavContent>
       <eg-course-associate-material-dialog [courseId]="courseId"
         [currentCourse]="currentCourse" displayMode="inline"
@@ -56,8 +56,8 @@
   </li>
 
   <!-- Users Tab -->
-  <li [ngbNavItem]="'courseUsers'">
-    <a ngbNavLink i18n>Course users</a>
+  <li role="presentation" [ngbNavItem]="'courseUsers'">
+    <a role="tab" ngbNavLink i18n>Course users</a>
     <ng-template ngbNavContent>
       <eg-course-associate-users-dialog [courseId]="courseId"
         [currentCourse]="currentCourse" displayMode="inline"
@@ -67,8 +67,8 @@
   </li>
 
   <!-- Terms Tab -->
-  <li [ngbNavItem]="'courseTerms'">
-    <a ngbNavLink i18n>Course terms</a>
+  <li role="presentation" [ngbNavItem]="'courseTerms'">
+    <a role="tab" ngbNavLink i18n>Course terms</a>
     <ng-template ngbNavContent>
       <eg-course-term-map-grid [courseId]="courseId"></eg-course-term-map-grid>
     </ng-template>
index 2317ab9..822f1f5 100644 (file)
@@ -2,7 +2,7 @@ import {Component, Input, ViewChild, OnInit} from '@angular/core';
 import {EMPTY} from 'rxjs';
 import {map, tap, concatMap} from 'rxjs/operators';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {OrgService} from '@eg/core/org.service';
 import {AuthService} from '@eg/core/auth.service';
 import {NetService} from '@eg/core/net.service';
index f5d1c2c..b3d5895 100644 (file)
@@ -1,8 +1,9 @@
 <eg-staff-banner bannerText="Survey ID # {{surveyId}}" i18n-bannerText
                 class="mb-3"></eg-staff-banner>
-<ngb-tabset #surveyTabs [activeId]="surveyTab" (tabChange)="onTabChange($event)" class="mb-3">
-    <ngb-tab title="Edit Survey" i18n-title id="edit">
-        <ng-template ngbTabContent>
+<ul ngbNav #surveyTabs="ngbNav" [(activeId)]="surveyTab" (navChange)="onNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="mb-3 nav-tabs">
+    <li role="presentation" [ngbNavItem]="'edit'">
+        <a i18n ngbNavLink role="tab">Edit Survey</a>
+        <ng-template ngbNavContent>
             <div class="col-lg-6 offset-lg-3 mt-3">
                 <div style="text-align: center;">
                     <button class="p-2 mb-3 btn btn-danger btn-lg" 
                 </eg-fm-record-editor>
             </div>
         </ng-template>
-    </ngb-tab>
-    <ngb-tab title="Questions and Answers" i18n-title id="qanda">
-        <ng-template ngbTabContent>
+    </li>
+    <li role="presentation" [ngbNavItem]="'qanda'">
+        <a i18n ngbNavLink role="tab">Questions and Answers</a>
+        <ng-template ngbNavContent>
             <div class="col-lg-8 offset-lg-2 mt-3">
                 <eg-staff-banner bannerText="Questions & Answers" i18n-bannerText>
                     </eg-staff-banner>
                 </div>
             </div>
         </ng-template>
-    </ngb-tab>
-</ngb-tabset>
+    </li>
+</ul>
+
+<div [ngbNavOutlet]="surveyTabs" class="mt-2"></div>
 
 <eg-string #createAnswerString i18n-text text="New Answer Added"></eg-string>
 <eg-string #createAnswerErrString i18n-text text="Failed to Create New Answer">
index 73b3a7b..550b52c 100644 (file)
@@ -6,7 +6,7 @@ import {ToastService} from '@eg/share/toast/toast.service';
 import {NetService} from '@eg/core/net.service';
 import {AuthService} from '@eg/core/auth.service';
 import {IdlObject, IdlService } from '@eg/core/idl.service';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 
 @Component({
     templateUrl: './survey-edit.component.html'
@@ -83,7 +83,7 @@ export class SurveyEditComponent implements OnInit {
         });
     }
 
-    onTabChange(event: NgbTabChangeEvent) {
+    onNavChange(event: NgbNavChangeEvent) {
         this.surveyTab = event.nextId;
     }
 
index 34a66a8..6084e2c 100644 (file)
@@ -3,10 +3,10 @@
 <div class="text-center">
     <button class="btn btn-outline-dark" (click)="back()">&#8592; Back to Notifications/Action Triggers</button>
 </div>
-<ul ngbNav #editNav="ngbNav" class="nav-tabs mb-3"
+<ul ngbNav #editNav="ngbNav" class="nav-tabs mb-3"  [keyboard]="true" [roles]="false" role="tablist"
     [activeId]="editTab" (navChange)="onTabChange($event)">
-    <li [ngbNavItem]="'def'">
-        <a ngbNavLink i18n>Edit Definition</a>
+    <li role="presentation" [ngbNavItem]="'def'">
+        <a role="tab" ngbNavLink i18n>Edit Definition</a>
         <ng-template ngbNavContent>
             <ng-template #textAreaTemplate let-field="field" let-record="record">
                 <textarea class="form-control" name="{{field.name}}"
@@ -25,8 +25,8 @@
             </div>
     </ng-template>
     </li>
-    <li ngbNavItem="'alt'" *ngIf=this.evtAltEligible>
-        <a ngbNavLink i18n>Edit Alternate Template</a>
+    <li role="presentation" ngbNavItem="'alt'" *ngIf=this.evtAltEligible>
+        <a role="tab" ngbNavLink i18n>Edit Alternate Template</a>
         <ng-template ngbNavContent>
             <ng-template #textAreaTemplate let-field="field" let-record="record">
                 <textarea class="form-control" name="{{field.name}}"
@@ -53,8 +53,8 @@
                  hiddenFields="event_def,id"></eg-fm-record-editor>
         </ng-template>
     </li>
-    <li ngbNavItem="'env'">
-        <a ngbNavLink i18n>Edit Environment</a>
+    <li role="presentation" ngbNavItem="'env'">
+        <a role="tab" ngbNavLink i18n>Edit Environment</a>
         <ng-template ngbNavContent>
             <h3 class="mb-3">Trigger Event Environment</h3>
             <eg-grid #envGrid idlClass="atenv" [dataSource]="envDataSource"
@@ -71,8 +71,8 @@
                 hiddenFields="event_def,id"></eg-fm-record-editor>
         </ng-template>
     </li>
-    <li ngbNavItem="'param'">
-        <a ngbNavLink i18n>Edit Parameters</a>
+    <li role="presentation" ngbNavItem="'param'">
+        <a role="tab" ngbNavLink i18n>Edit Parameters</a>
         <ng-template ngbNavContent>
             <h3 class="mb-3">Trigger Event Parameters</h3>
             <eg-grid #paramGrid idlClass="atevparam" [dataSource]="paramDataSource"
@@ -89,8 +89,8 @@
                 hiddenFields="event_def,id"></eg-fm-record-editor>
         </ng-template>
     </li>
-    <li ngbNavItem="'test'">
-        <a ngbNavLink i18n>Run Tests</a>
+    <li role="presentation" ngbNavItem="'test'">
+        <a role="tab" ngbNavLink i18n>Run Tests</a>
         <ng-template ngbNavContent>
             <h3 class="mb-3">Run Tests</h3>
             <label id="barcode">Barcode of Circulating Copy </label>
index 07e7901..4d6bd7b 100644 (file)
 <eg-fm-record-editor #reactorDialog idlClass="atreact"></eg-fm-record-editor>
 <eg-fm-record-editor #validatorDialog idlClass="atval"></eg-fm-record-editor>
 
-<ul ngbNav #triggerNav="ngbNav" [activeId]="triggerTab" class="nav-tabs"
+<ul ngbNav #triggerNav="ngbNav" [activeId]="triggerTab" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist"
     (navChange)="onTabChange($event)">
-    <li [ngbNavItem]="'eventDefinitions'">
-      <a ngbNavLink i18n>Event Definitions</a>
+    <li role="presentation" [ngbNavItem]="'eventDefinitions'">
+      <a role="tab" ngbNavLink i18n>Event Definitions</a>
       <ng-template ngbNavContent>
         <h4 class="mb-3 mt-3">Trigger Event Definitions</h4>
         <eg-grid #eventsGrid idlClass="atevdef" [dataSource]="eventsDataSource"
@@ -63,8 +63,8 @@
         </eg-grid>
       </ng-template>
     </li>
-    <li [ngbNavItem]="'hooks'">
-      <a ngbNavLink i18n>Hooks</a>
+    <li role="presentation" [ngbNavItem]="'hooks'">
+      <a role="tab" ngbNavLink i18n>Hooks</a>
       <ng-template ngbNavContent>
         <h4 class="mb-3 mt-3">Trigger Hooks</h4>
             <eg-grid #hooksGrid idlClass="ath" [dataSource]="hooksDataSource"
@@ -78,8 +78,8 @@
             </eg-grid>
       </ng-template>
     </li>
-    <li [ngbNavItem]="'reactors'">
-      <a ngbNavLink i18n>Reactors</a>
+    <li role="presentation" [ngbNavItem]="'reactors'">
+      <a role="tab" ngbNavLink i18n>Reactors</a>
       <ng-template ngbNavContent>
         <h4 class="mb-3 mt-3">Trigger Reactors</h4>
             <eg-grid #reactorsGrid idlClass="atreact" [dataSource]="reactorsDataSource"
@@ -93,8 +93,8 @@
             </eg-grid>
       </ng-template>
     </li>
-    <li [ngbNavItem]="'validators'">
-        <a ngbNavLink i18n>Validators</a>
+    <li role="presentation" [ngbNavItem]="'validators'">
+        <a role="tab" ngbNavLink i18n>Validators</a>
         <ng-template ngbNavContent>
             <h4 class="mb-3 mt-3">Trigger Validators</h4>
             <eg-grid #validatorsGrid idlClass="atval" [dataSource]="validatorsDataSource"
index ab8b534..9a0ceac 100644 (file)
@@ -1,29 +1,25 @@
-
-<ngb-tabset #addressTabs *ngIf="orgUnit" (tabChange)="tabChanged($event)">
+<ul ngbNav #addressTabs="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist" [(activeId)]="tabName">
   <ng-container *ngFor="let type of addrTypes()">
-    <b>type = {{type}}</b>
 
-    <ngb-tab *ngIf="addr(type)"
-      i18n-title id="{{type}}"
-      title="{{type === 'billing_address' ? 'Physical Address' : 
+    <li *ngIf="addr(type)" role="presentation" id="{{type}}" ngbNavItem="{{type}}">
+      <a role="tab" ngbNavLink i18n>{{type === 'billing_address' ? 'Physical Address' : 
         (type === 'holds_address' ? 'Holds Address' : 
-        (type === 'mailing_address' ? 'Mailing Address' : 'ILL Address'))}}">
-
-      <ng-template ngbTabContent>
+        (type === 'mailing_address' ? 'Mailing Address' : 'ILL Address'))}}</a>
+      <ng-template ngbNavContent>
         <eg-fm-record-editor idlClass="aoa" readonlyFields="org_unit" 
-          [mode]="addr(type).isnew() ? 'create': 'update'" 
-          [hideBanner]="true" displayMode="inline" hiddenFields="id"
-          (recordSaved)="addrSaved($event)" 
-          [record]="addr(type)"
-          fieldOrder="address_type,street1,street2,city,county,state,country,post_code,san,valid"
-          >
-          <eg-fm-record-editor-action i18n-label label="Get Coordinates"
-            (actionClick)="getCoordinates($event)">
-          </eg-fm-record-editor-action>
-          <eg-fm-record-editor-action i18n-label label="Delete" *ngIf="!addr(type).isnew()"
-            (actionClick)="deleteAddress($event)" buttonCss="btn-warning">
-          </eg-fm-record-editor-action>
-        </eg-fm-record-editor>
+            [mode]="addr(type).isnew() ? 'create': 'update'" 
+            [hideBanner]="true" displayMode="inline" hiddenFields="id"
+            (recordSaved)="addrSaved($event)" 
+            [record]="addr(type)"
+            fieldOrder="address_type,street1,street2,city,county,state,country,post_code,san,valid"
+            >
+            <eg-fm-record-editor-action i18n-label label="Get Coordinates"
+              (actionClick)="getCoordinates($event)">
+            </eg-fm-record-editor-action>
+            <eg-fm-record-editor-action i18n-label label="Delete" *ngIf="!addr(type).isnew()"
+              (actionClick)="deleteAddress($event)" buttonCss="btn-warning">
+            </eg-fm-record-editor-action>
+          </eg-fm-record-editor>
 
         <ng-container *ngIf="sharedAddress(addr(type).id())">
           <div class="alert alert-info">
               class="btn btn-light ml-3" i18n>Clone As New Address</button>
           </div>
         </ng-container>
+
       </ng-template>
-    </ngb-tab>
+    </li>
+
   </ng-container>
-</ngb-tabset>
+</ul>
 
+<div [ngbNavOutlet]="addressTabs" class="mt-2"></div>
\ No newline at end of file
index 766a0b7..7d63cac 100644 (file)
@@ -4,7 +4,7 @@ import {OrgService} from '@eg/core/org.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {NetService} from '@eg/core/net.service';
 import {AuthService} from '@eg/core/auth.service';
-import {NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {ToastService} from '@eg/share/toast/toast.service';
 
 const ADDR_TYPES =
@@ -17,7 +17,7 @@ const ADDR_TYPES =
 export class OrgAddressComponent {
 
     orgUnit: IdlObject = null;
-    private tabName: string;
+    tabName: string;
 
     private _orgId: number;
 
@@ -45,12 +45,13 @@ export class OrgAddressComponent {
         private toast: ToastService
     ) {
         this.addrChange = new EventEmitter<IdlObject>();
-        this.tabName = 'billing_address';
     }
 
     init() {
         if (!this.orgId) { return; }
 
+        this.tabName = 'billing_address';
+
         return this.pcrud.retrieve('aou', this.orgId,
             {flesh : 1, flesh_fields : {aou : ADDR_TYPES}},
             {authoritative: true}
@@ -64,10 +65,6 @@ export class OrgAddressComponent {
         });
     }
 
-    tabChanged($event: NgbTabChangeEvent) {
-        this.tabName = $event.nextId;
-    }
-
     addrTypes(): string[] { // for UI
         return ADDR_TYPES;
     }
index e8e07c7..7ee805d 100644 (file)
 >
 </eg-fm-record-editor>
 
-<div class="row">
-  <div class="col-lg-4">
+<div class="row org-unit-types-row">
+  <div class="col-lg-4 org-unit-types-col-aside">
     <h3 i18n>Org Unit Types</h3>
     <eg-tree [tree]="tree" (nodeClicked)="nodeClicked($event)"></eg-tree>
   </div>
-  <div class="col-lg-8">
+  <div class="col-lg-8 org-unit-types-col-main">
     <h3 i18n class="mb-3">Selected Org Unit Type</h3>
     <ng-container *ngIf="!selected">
       <div class="alert alert-info font-italic" i18n>
index f73557d..b7111eb 100644 (file)
@@ -10,7 +10,8 @@ import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
 
 @Component({
-    templateUrl: './org-unit-type.component.html'
+    templateUrl: './org-unit-type.component.html',
+    styleUrls: [ './org-unit.component.css' ],
 })
 
 export class OrgUnitTypeComponent implements OnInit {
diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit.component.css b/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit.component.css
new file mode 100644 (file)
index 0000000..7b27960
--- /dev/null
@@ -0,0 +1,14 @@
+.org-unit-types-row {
+    align-items: stretch;
+}
+
+.org-unit-types-col-aside {
+    height: 100%;
+}
+
+eg-tree { 
+    display: block;
+    height: 100%; 
+    overflow-y: auto;
+    width: 100%;
+}
\ No newline at end of file
index 19b803a..4a0f24f 100644 (file)
 <eg-string #treeNodeLabel key='admin.server.org_unit.treenode' 
   [template]="treeNodeLabelTmpl"></eg-string>
 
-<div class="row">
-  <div class="col-lg-4">
+<div class="row org-unit-types-row">
+  <div class="col-lg-4 org-unit-types-col-aside">
     <h3 i18n>Org Units</h3>
-    <div class="border rounded p-1" style="height:{{winHeight}}px;overflow-y:auto">
+    <div class="border rounded p-1" >
       <eg-tree [tree]="tree" (nodeClicked)="nodeClicked($event)"></eg-tree>
     </div>
   </div>
-  <div class="col-lg-8">
+  <div class="col-lg-8 org-unit-types-col-main">
     <div class="alert alert-info">
       <div *ngIf="currentOrg()">
         <span *ngIf="currentOrg().name()" i18n>
         </span>
       </div>
     </div>
-    <ngb-tabset #rootTabs (tabChange)="tabChanged($event)" *ngIf="currentOrg()">
-      <ngb-tab title="Main Settings" i18n-title id="main">
-        <ng-template ngbTabContent>
+
+    <div class="ngbNav-wrapper" *ngIf="currentOrg()"> 
+    <ul ngbNav #rootTabs="ngbNav" [(activeId)]="orgUnitTab" (navChange)="navChanged($event)" [disabled]="currentOrg().isnew()" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+      <li role="presentation" [ngbNavItem]="'main'">
+        <a i18n ngbNavLink role="tab">Main Settings</a>
+        <ng-template ngbNavContent>
           <div class="mt-2">
             <eg-fm-record-editor *ngIf="currentOrg()" #editDialog idlClass="aou" 
               [mode]="currentOrg().isnew() ? 'create': 'update'" [hideBanner]="true" 
             </eg-fm-record-editor>
           </div>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Hours of Operation" i18n-title id="hours" 
-        [disabled]="currentOrg().isnew()">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'hours'">
+        <a i18n ngbNavLink role="tab">Hours of Operation</a>
+        <ng-template ngbNavContent>
           <div class="mt-2 common-form striped-even">
             <div class="row font-weight-bold mb-2">
               <div class="col-lg-3 offset-lg-2" i18n>Open Time</div>
             </div>
           </div>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Addresses" i18n-title id="addresses" 
-        [disabled]="currentOrg().isnew()">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'addresses'" [disabled]="currentOrg().isnew()">
+        <a i18n ngbNavLink role="tab">Addresses</a>
+        <ng-template ngbNavContent>
           <div class="mt-2">
             <eg-admin-org-address [orgId]="currentOrg().id()" (addrChange)="addressChanged($event)">
             </eg-admin-org-address>
           </div>
         </ng-template>
-      </ngb-tab>
-    </ngb-tabset>
+      </li>
+    </ul>
+
+    <div [ngbNavOutlet]="rootTabs" class="mt-2"></div>
+    </div>
+
   </div>
 </div>
index 7b34df0..65ab138 100644 (file)
@@ -1,7 +1,7 @@
 import {Component, Input, ViewChild, OnInit} from '@angular/core';
 import {Tree, TreeNode} from '@eg/share/tree/tree';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {OrgService} from '@eg/core/org.service';
 import {AuthService} from '@eg/core/auth.service';
 import {PcrudService} from '@eg/core/pcrud.service';
@@ -13,13 +13,14 @@ import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
 
 @Component({
-    templateUrl: './org-unit.component.html'
+    templateUrl: './org-unit.component.html',
+    styleUrls: [ './org-unit.component.css' ],
 })
 export class OrgUnitComponent implements OnInit {
 
     tree: Tree;
     selected: TreeNode;
-    winHeight = 500;
+    orgUnitTab: string;
 
     @ViewChild('editString', { static: true }) editString: StringComponent;
     @ViewChild('errorString', { static: true }) errorString: StringComponent;
@@ -39,7 +40,7 @@ export class OrgUnitComponent implements OnInit {
         this.loadAouTree(this.org.root().id());
     }
 
-    tabChanged(evt: NgbTabChangeEvent) {
+    navChanged(evt: NgbNavChangeEvent) {
         const tab = evt.nextId;
         // stubbing out in case we need it.
     }
@@ -74,9 +75,6 @@ export class OrgUnitComponent implements OnInit {
             const node = this.tree.findNode(selectNodeId);
             this.selected = node;
             this.tree.selectNode(node);
-
-            // Subtract out the menu bar plus a bit more.
-            this.winHeight = window.innerHeight * 0.8;
         });
     }
 
index fa9fc42..02d045f 100644 (file)
         </ng-container>
     </ng-container>
     <div *ngIf="selected" class="common-form striped-even">
-      <ngb-tabset>
-        <ngb-tab title="Group Details" i18n-title id="detail">
-          <ng-template ngbTabContent>
+      <ul ngbNav #PermTabs="ngbNav" [(activeId)]="permTab" (navChange)="onNavChange($event)" 
+        [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+        <li role="presentation" [ngbNavItem]="'detail'">
+          <a i18n ngbNavLink role="tab">Group Details</a>
+          <ng-template ngbNavContent>
             <div class="row">
               <div class="col-lg-3">
                 <label i18n>Actions for Selected: </label>
               </div>
             </div>
           </ng-template>
-        </ngb-tab>
-        <ngb-tab title="Group Permissions" i18n-title id="perm">
-          <ng-template ngbTabContent>
+        </li>
+        <li role="presentation" [ngbNavItem]="'perm'">
+          <a i18n ngbNavLink role="tab">Group Permissions</a>
+          <ng-template ngbNavContent>
 
             <div class="row d-flex m-2 mb-3">
               <button class="btn btn-success" (click)="applyChanges()" i18n
               </button>
             </div>
           </ng-template>
-        </ngb-tab>
-      </ngb-tabset>
+        </li>
+      </ul>
+
+      <div [ngbNavOutlet]="PermTabs" class="mt-2"></div>
     </div>
   </div>
 </div>
index 5c8b083..9e6438c 100644 (file)
@@ -12,6 +12,7 @@ import {FmRecordEditorComponent, FmFieldOptions} from '@eg/share/fm-editor/fm-ed
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
 import {PermGroupMapDialogComponent} from './perm-group-map-dialog.component';
 import {ProgressInlineComponent} from '@eg/share/dialog/progress-inline.component';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 
 /** Manage permission groups and group permissions */
 
@@ -32,6 +33,7 @@ export class PermGroupTreeComponent implements OnInit {
 
     // Have to fetch quite a bit of data for this UI.
     loading: boolean;
+    permTab: string;
 
     @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
     @ViewChild('delConfirm', { static: true }) delConfirm: ConfirmDialogComponent;
@@ -72,6 +74,10 @@ export class PermGroupTreeComponent implements OnInit {
         return Promise.resolve();
     }
 
+    onNavChange(evt: NgbNavChangeEvent) {
+        this.permTab = evt.nextId;
+    }
+
     setOrgDepths() {
         const depths = this.org.typeList().map(t => Number(t.depth()));
         const depths2 = [];
index 6d426ef..81a8879 100644 (file)
   </div>
 </div>
 
-<ngb-tabset *ngIf="template" #tabs (tabChange)="onTabChange($event)">
-  <ngb-tab title="Template" i18n-title id='template'>
-    <ng-template ngbTabContent>
+<ul ngbNav #tabs="ngbNav" *ngIf="template" [(activeId)]="template"
+      (navChange)="onNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+
+  <li role="presentation" [ngbNavItem]="'template'">
+    <a i18n ngbNavLink role="tab">Template</a>
+    <ng-template ngbNavContent>
       <div class="row">
         <div class="col-lg-12 mt-3 d-flex">
           <button class="btn btn-info" (click)="openEditDialog()" i18n>
         </div>
       </div>
     </ng-template>
-  </ngb-tab>
-  <ngb-tab title="Sample Data" i18n-title id='data'>
-    <ng-template ngbTabContent>
+  </li>
+  <li role="presentation" [ngbNavItem]="'data'">
+    <a i18n ngbNavLink role="tab">Sample Data</a>
+    <ng-template ngbNavContent>
       <textarea rows="20" [(ngModel)]="sampleJson" 
         spellcheck="false" class="form-control">
       </textarea>
     </ng-template>
-  </ngb-tab>
-</ngb-tabset>
+  </li>
+</ul>
 
+<div [ngbNavOutlet]="tabs" class="mt-2"></div>
\ No newline at end of file
index 0b27fd7..dd3be36 100644 (file)
@@ -11,7 +11,7 @@ import {ComboboxComponent, ComboboxEntry
     } from '@eg/share/combobox/combobox.component';
 import {PrintService} from '@eg/share/print/print.service';
 import {LocaleService} from '@eg/core/locale.service';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
 import {SampleDataService} from '@eg/share/util/sample-data.service';
 import {OrgFamily} from '@eg/share/org-family-select/org-family-select.component';
@@ -39,7 +39,7 @@ export class PrintTemplateComponent implements OnInit {
     selectedOrgs: number[];
 
     @ViewChild('templateSelector', { static: true }) templateSelector: ComboboxComponent;
-    @ViewChild('tabs', { static: false }) tabs: NgbTabset;
+    @ViewChild('tabs', { static: false }) tabs: NgbNav;
     @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
     @ViewChild('confirmDelete', { static: true }) confirmDelete: ConfirmDialogComponent;
     @ViewChild('printContextCbox', {static: false}) printContextCbox: ComboboxComponent;
@@ -170,7 +170,7 @@ export class PrintTemplateComponent implements OnInit {
             this.org.list()[0];
     }
 
-    onTabChange(evt: NgbTabChangeEvent) {
+    onTabChange(evt: NgbNavChangeEvent) {
         if (evt.nextId === 'template') {
             this.refreshPreview();
         }
index 4dc4d89..c881afd 100644 (file)
   </div>
   <div class="card col-sm-6">
     <h2 class="card-header" i18n>Reservation details</h2>
-    <ngb-tabset #details="ngbTabset">
-      <ngb-tab id="select-resource-type">
-        <ng-template ngbTabTitle>
+    <ul ngbNav #details="ngbNav" [(activeId)]="detailsTab" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+      <li role="presentation" [ngbNavItem]="'select-resource-type'">
+        <a ngbNavLink role="tab">
           <span class="material-icons">dns</span>
           <ng-container i18n>Choose resource by type</ng-container>
-        </ng-template>
-        <ng-template ngbTabContent>
+        </a>
+        <ng-template ngbNavContent>
           <div ngbPanelContent class="row">
             <div class="col">
               <div class="input-group">
             </div>
           </div>
         </ng-template>
-      </ngb-tab>
+      </li>
 
-      <ngb-tab id="select-resource">
-        <ng-template ngbTabTitle>
+      <li role="presentation" [ngbNavItem]="'select-resource'">
+        <a ngbNavLink role="tab">
           <span class="material-icons">assignment</span>
           <ng-container i18n>Choose resource by barcode</ng-container>
-        </ng-template>
-        <ng-template ngbTabContent>
+        </a>
+        <ng-template ngbNavContent>
           <div ngbPanelContent class="row">
             <div class="col">
               <div class="input-group">
             </div>
           </div>
         </ng-template>
-      </ngb-tab>
+      </li>
 
-      <ngb-tab id="attributes" [disabled]="0 === attributes.length">
-        <ng-template ngbTabTitle>
+      <li role="presentation" [ngbNavItem]="'attributes'" [disabled]="0 === attributes.length">
+        <a ngbNavLink role="tab">
           <span class="material-icons">filter_list</span>
           <ng-container i18n>Limit by attributes</ng-container>
-        </ng-template>
-        <ng-template ngbTabContent>
+        </a>
+        <ng-template ngbNavContent>
           <ul class="list-group list-group-flush" formArrayName="selectedAttributes">
             <li *ngFor="let attribute of attributes; let i = index" class="list-group-item">
               <span class="input-group">
             </li>
           </ul>
         </ng-template>
-      </ngb-tab>
+      </li>
 
-      <ngb-tab id="display-settings">
-        <ng-template ngbTabTitle>
+      <li role="presentation" [ngbNavItem]="'display-settings'">
+        <a ngbNavLink role="tab">
           <span class="material-icons">settings</span>
           <ng-container i18n>Schedule settings</ng-container>
-        </ng-template>
-        <ng-template ngbTabContent>
+        </a>
+        <ng-template ngbNavContent>
           <ul class="list-group list-group-flush">
             <li class="list-group-item">
               <span class="input-group">
             </li>
           </ul>
         </ng-template>
-      </ngb-tab>
-    </ngb-tabset>
+      </li>
+    </ul>
+
+    <div [ngbNavOutlet]="details" class="mt-2"></div>
   </div>
 </form>
 
index 6e3ae35..ad83b6b 100644 (file)
@@ -3,7 +3,7 @@ import {FormGroup, FormControl, ValidationErrors, ValidatorFn, FormArray} from '
 import {Router, ActivatedRoute} from '@angular/router';
 import {from, iif, Observable, of, throwError, timer, Subscription} from 'rxjs';
 import {catchError, debounceTime, takeLast, mapTo, single, switchMap, tap} from 'rxjs/operators';
-import {NgbCalendar, NgbTabset} from '@ng-bootstrap/ng-bootstrap';
+import {NgbCalendar, NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {AuthService} from '@eg/core/auth.service';
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
 import {FormatService} from '@eg/core/format.service';
@@ -68,9 +68,10 @@ export class CreateReservationComponent implements OnInit, AfterViewInit, OnDest
     changeGranularity: ($event: ComboboxEntry) => void;
 
     dateRange: DateRange;
+    detailsTab: string = '';
 
     @ViewChild('createDialog', { static: true }) createDialog: CreateReservationDialogComponent;
-    @ViewChild('details', { static: true }) details: NgbTabset;
+    @ViewChild('details', { static: true }) details: NgbNav;
     @ViewChild('noTimezoneSetDialog', { static: true }) noTimezoneSetDialog: NoTimezoneSetComponent;
     @ViewChild('viewReservation', { static: true }) viewReservation: FmRecordEditorComponent;
     @ViewChildren('scheduleGrid') scheduleGrids: QueryList<GridComponent>;
index 1a7e94b..fab4245 100644 (file)
   <div class="col-sm-6 offset-sm-3">
     <div class="card">
       <h2 class="card-header" i18n>Filter reservations</h2>
-      <ngb-tabset #filterTabs [activeId]="startingTab" class="mt-1">
-        <ngb-tab id="patron">
-          <ng-template ngbTabTitle>
+      <ul ngbNav #filterTabs="ngbNav" [(activeId)]="startingTab" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+        <li role="presentation" [ngbNavItem]="'patron'">
+          <a ngbNavLink role="tab">
             <span class="material-icons" *ngIf="patronId">filter_list</span> <span i18n>Filter by patron</span>
-          </ng-template>
-          <ng-template ngbTabContent>
+          </a>
+          <ng-template ngbNavContent>
             <div class="m-2">
               <div class="input-group m-2">
                 <div class="input-group-prepend">
               </div>
             </div>
           </ng-template>
-        </ngb-tab>
-        <ngb-tab id="resource">
-          <ng-template ngbTabTitle>
+        </li>
+        <li role="presentation" [ngbNavItem]="'resource'">
+          <a ngbNavLink role="tab">
             <span class="material-icons" *ngIf="resourceBarcode.value">filter_list</span> <span i18n>Filter by resource</span>
-          </ng-template>
-          <ng-template ngbTabContent>
+          </a>
+          <ng-template ngbNavContent>
             <div class="m-2">
               <div class="input-group m-2">
                 <div class="input-group-prepend">
               </div>
             </div>
           </ng-template>
-        </ngb-tab>
-        <ngb-tab id="type">
-          <ng-template ngbTabTitle>
+        </li>
+        <li role="presentation" [ngbNavItem]="'type'">
+          <a ngbNavLink role="tab">
             <span class="material-icons" *ngIf="resourceTypeForGrid">filter_list</span> <span i18n>Filter by resource type</span>
-          </ng-template>
-          <ng-template ngbTabContent>
+          </a>
+          <ng-template ngbNavContent>
             <div class="m-2">
               <div class="input-group m-2">
                 <div class="input-group-prepend">
               </div>
             </div>
           </ng-template>
-        </ngb-tab>
-      </ngb-tabset>
+        </li>
+      </ul>
+
+      <div [ngbNavOutlet]="filterTabs" class="mt-2"></div>
     </div>
   </div>
 </form>
index 25ef296..5d4cea9 100644 (file)
@@ -3,7 +3,7 @@ import {FormGroup, FormControl} from '@angular/forms';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
 import {Subscription, of} from 'rxjs';
 import {debounceTime, single, tap, switchMap} from 'rxjs/operators';
-import {NgbTabset} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {AuthService} from '@eg/core/auth.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {ReservationsGridComponent} from './reservations-grid.component';
@@ -27,7 +27,7 @@ export class ManageReservationsComponent implements OnInit, OnDestroy {
     startingTab: 'patron' | 'resource' | 'type' = 'patron';
     startingPickupOrgs: OrgFamily = {primaryOrgId: this.auth.user().ws_ou(), includeDescendants: true};
 
-    @ViewChild('filterTabs', { static: true }) filterTabs: NgbTabset;
+    @ViewChild('filterTabs', { static: true }) filterTabs: NgbNav;
     @ViewChild('reservationsGrid', { static: true }) reservationsGrid: ReservationsGridComponent;
 
     removeFilters: () => void;
index 82758dd..ca6c8a4 100644 (file)
@@ -3,9 +3,11 @@
 <eg-title i18n-prefix i18n-suffix prefix="Booking" suffix="Return"></eg-title>
 
 <form [formGroup]="findPatron">
-  <ngb-tabset (tabChange)="handleTabChange($event)" activeId="patron" #tabs>
-    <ngb-tab title="By patron" i18n-title id="patron">
-      <ng-template ngbTabContent>
+  <ul ngbNav #tabs="ngbNav" [(activeId)]="patronTab"
+      (navChange)="handleNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+    <li role="presentation" [ngbNavItem]="'patron_tab'">
+      <a i18n ngbNavLink role="tab">By patron</a>
+      <ng-template ngbNavContent>
         <div class="row">
           <div class="col-md-4">
             <div class="input-group flex-nowrap">
           <eg-reservations-grid #returnedGrid [patron]="patronId" status="returnedToday" persistSuffix="return.patron.returned"></eg-reservations-grid>
         </div>
       </ng-template>
-    </ngb-tab>
-    <ngb-tab title="By resource" i18n-title id="resource">
-      <ng-template ngbTabContent>
+    </li>
+    <li role="presentation" [ngbNavItem]="'resource'">
+      <a i18n ngbNavLink role="tab">By resource</a>
+      <ng-template ngbNavContent>
         <div class="input-group flex-nowrap">
           <div class="input-group-prepend">
             <label class="input-group-text" for="resource-barcode" i18n>Resource barcode</label>
@@ -41,6 +44,8 @@
           <eg-reservations-grid #returnedGrid [patron]="patronId" status="returnedToday" persistSuffix="return.resource.returned"></eg-reservations-grid>
         </div>
       </ng-template>
-    </ngb-tab>
-  </ngb-tabset>
+    </li>
+  </ul>
+
+  <div [ngbNavOutlet]="tabs" class="mt-2"></div>
 </form>
index f37e10e..fad7764 100644 (file)
@@ -1,7 +1,7 @@
 import {Component, OnInit, OnDestroy, QueryList, ViewChildren, ViewChild} from '@angular/core';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
 import {FormGroup, FormControl, Validators} from '@angular/forms';
-import {NgbTabChangeEvent, NgbTabset} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {Observable, from, of, Subscription} from 'rxjs';
 import { single, switchMap, tap, debounceTime } from 'rxjs/operators';
 import {PatronService} from '@eg/staff/share/patron/patron.service';
@@ -21,10 +21,11 @@ export class ReturnComponent implements OnInit, OnDestroy {
     patronId: number;
     findPatron: FormGroup;
     subscriptions: Subscription[] = [];
+    patronTab: any;
 
     noSelectedRows: (rows: IdlObject[]) => boolean;
-    handleTabChange: ($event: NgbTabChangeEvent) => void;
-    @ViewChild('tabs', { static: true }) tabs: NgbTabset;
+    handleNavChange: ($event: NgbNavChangeEvent) => void;
+    @ViewChild('tabs', { static: true }) tabs: NgbNav;
     @ViewChildren(ReservationsGridComponent) grids: QueryList<ReservationsGridComponent>;
 
     constructor(
@@ -44,6 +45,10 @@ export class ReturnComponent implements OnInit, OnDestroy {
             return this.handleParams$(params);
         })).subscribe();
 
+        this.patronTab =
+            this.store.getItem('eg.booking.return.tab')
+            || 'patron_tab';
+
         this.findPatron = new FormGroup({
             'patronBarcode': new FormControl(null,
                 [Validators.required],
@@ -95,7 +100,7 @@ export class ReturnComponent implements OnInit, OnDestroy {
         );
         this.noSelectedRows = (rows: IdlObject[]) => (rows.length === 0);
 
-        this.handleTabChange = ($event) => {
+        this.handleNavChange = ($event) => {
             this.store.setItem('eg.booking.return.tab', $event.nextId)
             .then(() => {
                 this.router.navigate(['/staff', 'booking', 'return']);
index c1951fe..2d77dd4 100644 (file)
   </div>
 </div>
 
-<ngb-tabset #authTabs [activeId]="authTab" 
-  (tabChange)="beforeTabChange($event)">
-  <ngb-tab title="Linked Bibs" i18n-title id="bibs">
-    <ng-template ngbTabContent>
+<ul ngbNav #authTabs="ngbNav" [(activeId)]="authTab" 
+  (navChange)="beforeNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+  <li role="presentation" [ngbNavItem]="'bibs'">
+    <a i18n ngbNavLink role="tab">Linked Bibs</a>
+    <ng-template ngbNavContent>
       <div class="mt-3" *ngIf="authMeta">
         <eg-bib-list #bibList [bibIdSource]="linkedBibIdSource"
           gridPersistKey="cat.authority.manage.bibs"></eg-bib-list>
       </div>
     </ng-template>
-  </ngb-tab>
-  <ngb-tab title="Edit" i18n-title id="edit">
-    <ng-template ngbTabContent>
+  </li>
+  <li role="presentation" [ngbNavItem]="'edit'">
+    <a i18n ngbNavLink role="tab">Edit</a>
+    <ng-template ngbNavContent>
       <div class="mt-3">
         <eg-marc-editor #marcEditor recordType="authority" [recordId]="authId">
         </eg-marc-editor>
       </div>
     </ng-template>
-  </ngb-tab>
-</ngb-tabset>
-
+  </li>
+</ul>
 
+<div [ngbNavOutlet]="authTabs" class="mt-2"></div>
index 95c0193..5e70b63 100644 (file)
@@ -2,7 +2,7 @@ import {Component, OnInit, ViewChild} from '@angular/core';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
 import {Observable} from 'rxjs';
 import {map, switchMap} from 'rxjs/operators';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {IdlObject} from '@eg/core/idl.service';
 import {Pager} from '@eg/share/util/pager';
 import {NetService} from '@eg/core/net.service';
@@ -66,7 +66,7 @@ export class ManageAuthorityComponent implements OnInit {
 
     // Changing a tab in the UI means changing the route.
     // Changing the route ultimately results in changing the tab.
-    beforeTabChange(evt: NgbTabChangeEvent) {
+    beforeNavChange(evt: NgbNavChangeEvent) {
 
         // prevent tab changing until after route navigation
         evt.preventDefault();
index 78a86ed..4249fe0 100644 (file)
@@ -1,17 +1,21 @@
 
-<ngb-tabset #tabs [activeId]="attrType" (tabChange)="onTabChange($event)">
-       <ngb-tab title="Bibliographic Attributes" i18n-title id="bib">
-               <ng-template ngbTabContent>
+<ul ngbNav #tabs="ngbNav" [(activeId)]="attrType" (navChange)="onNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+       <li role="presentation" [ngbNavItem]="'bib'">
+               <a i18n ngbNavLink role="tab">Bibliographic Attributes</a>
+               <ng-template ngbNavContent>
       <div class="mt-3">
         <eg-admin-page idlClass="vqbrad"></eg-admin-page>
       </div>
                </ng-template>
-       </ngb-tab>
-       <ngb-tab title="Authority Attributes" i18n-title id="authority">
-               <ng-template ngbTabContent>
+       </li>
+       <li role="presentation" [ngbNavItem]="'authority'">
+               <a i18n ngbNavLink role="tab">Authority Attributes</a>
+               <ng-template ngbNavContent>
       <div class="mt-3">
         <eg-admin-page idlClass="vqarad"></eg-admin-page>
       </div>
                </ng-template>
-       </ngb-tab>
-</ngb-tabset>
+       </li>
+</ul>
+
+<div [ngbNavOutlet]="tabs" class="mt-2"></div>
index 7d1eceb..86c60c7 100644 (file)
@@ -1,6 +1,6 @@
 import {Component} from '@angular/core';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 
 @Component({
   templateUrl: 'display-attrs.component.html'
@@ -20,7 +20,7 @@ export class DisplayAttrsComponent {
 
     // Changing a tab in the UI means changing the route.
     // Changing the route ultimately results in changing the tab.
-    onTabChange(evt: NgbTabChangeEvent) {
+    onNavChange(evt: NgbNavChangeEvent) {
         this.attrType = evt.nextId;
 
         // prevent tab changing until after route navigation
index fd69cf9..b12f7da 100644 (file)
   </div>
 </div>
 
-<ngb-tabset [activeId]="matchSetTab" (tabChange)="onTabChange($event)">
-       <ngb-tab title="Match Set Editor" i18n-title id="editor">
-               <ng-template ngbTabContent>
+<ul ngbNav #matchSetTabs="ngbNav" [(activeId)]="matchSetTab" 
+      (navChange)="onNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+       <li role="presentation" [ngbNavItem]="'editor'">
+               <a i18n ngbNavLink role="tab">Match Set Editor</a>
+    <ng-template ngbNavContent>
       <eg-match-set-expression [matchSet]="matchSet">
       </eg-match-set-expression>
                </ng-template>
-       </ngb-tab>
-       <ngb-tab title="Match Set Quality Metrics" i18n-title id="quality">
-               <ng-template ngbTabContent>
+       </li>
+       <li role="presentation" [ngbNavItem]="'quality'">
+               <a i18n ngbNavLink role="tab">Match Set Quality Metrics</a>
+    <ng-template ngbNavContent>
       <eg-match-set-quality [matchSet]="matchSet">
       </eg-match-set-quality>
                </ng-template>
-       </ngb-tab>
-</ngb-tabset>
+       </li>
+</ul>
+
+<div [ngbNavOutlet]="matchSetTabs" class="mt-2"></div>
\ No newline at end of file
index 64a4b35..34a2f41 100644 (file)
@@ -1,6 +1,6 @@
 import {Component, OnInit} from '@angular/core';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {IdlObject} from '@eg/core/idl.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {OrgService} from '@eg/core/org.service';
@@ -36,7 +36,7 @@ export class MatchSetComponent implements OnInit {
 
     // Changing a tab in the UI means changing the route.
     // Changing the route ultimately results in changing the tab.
-    onTabChange(evt: NgbTabChangeEvent) {
+    onNavChange(evt: NgbNavChangeEvent) {
         this.matchSetTab = evt.nextId;
 
         // prevent tab changing until after route navigation
index ed643d9..21fb720 100644 (file)
@@ -9,15 +9,18 @@
   </div>
 </div>
 
-<ngb-tabset #recordTabs [activeId]="recordTab" (tabChange)="onTabChange($event)">
-  <ngb-tab title="Queued Record MARC" i18n-title id="marc">
-    <ng-template ngbTabContent>
+<ul ngbNav #recordTabs="ngbNav" [(activeId)]="recordTab" 
+      (navChange)="onNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+  <li role="presentation" [ngbNavItem]="'marc'">
+    <a i18n ngbNavLink role="tab">Queued Record MARC</a>
+    <ng-template ngbNavContent>
       <eg-marc-html [recordId]="recordId" [recordType]="'vandelay-'+queueType">
       </eg-marc-html>
     </ng-template>
-  </ngb-tab>
-  <ngb-tab title="Edit Record" i18n-title id="edit">
-    <ng-template ngbTabContent>
+  </li>
+  <li role="presentation" [ngbNavItem]="'edit'">
+    <a i18n ngbNavLink role="tab">Edit Record</a>
+    <ng-template ngbNavContent>
       <ng-container *ngIf="queuedRecord">
         <eg-marc-editor [inPlaceMode]="true" [recordXml]="queuedRecord.marc()"
           [recordSource]="queuedRecord.bib_source()"
           *ngIf="queueType !== 'bib'"></eg-marc-editor>
       </ng-container>
     </ng-template>
-  </ngb-tab>
-  <ngb-tab title="Record Matches" i18n-title id="matches">
-    <ng-template ngbTabContent>
+  </li>
+  <li role="presentation" [ngbNavItem]="'matches'">
+    <a i18n ngbNavLink role="tab">Record Matches</a>
+    <ng-template ngbNavContent>
       <eg-queued-record-matches [recordId]="recordId" [queueType]="queueType">
       </eg-queued-record-matches>
     </ng-template>
-  </ngb-tab>
-  <ngb-tab title="Import Items" i18n-title id="items">
-    <ng-template ngbTabContent>
+  </li>
+  <li role="presentation" [ngbNavItem]="'items'">
+    <a i18n ngbNavLink role="tab">Import Items</a>
+    <ng-template ngbNavContent>
       <eg-queued-record-items [recordId]="recordId">
       </eg-queued-record-items>
     </ng-template>
-  </ngb-tab>
-</ngb-tabset>
+  </li>
+</ul>
+
+<div [ngbNavOutlet]="recordTabs" class="mt-2"></div>
\ No newline at end of file
index 872f0e5..120f84a 100644 (file)
@@ -1,6 +1,6 @@
 import {Component} from '@angular/core';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {IdlObject} from '@eg/core/idl.service';
 
@@ -33,7 +33,7 @@ export class QueuedRecordComponent {
 
     // Changing a tab in the UI means changing the route.
     // Changing the route ultimately results in changing the tab.
-    onTabChange(evt: NgbTabChangeEvent) {
+    onNavChange(evt: NgbNavChangeEvent) {
         this.recordTab = evt.nextId;
 
         // prevent tab changing until after route navigation
index bfa9217..5715df4 100644 (file)
 
   <div class="mt-3"> </div>
 
-  <ul ngbNav #holdingsNav="ngbNav" class="nav-tabs"
+  <ul ngbNav #holdingsNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist"
     [activeId]="tab" (navChange)="beforeTabChange($event)">
-    <li ngbNavItem="holdings">
-      <a ngbNavLink i18n>Holdings</a>
+    <li role="presentation" ngbNavItem="holdings">
+      <a role="tab" ngbNavLink i18n>Holdings</a>
       <ng-template ngbNavContent>
         <div class="mt-2">
           <eg-vol-edit [context]="context"
@@ -35,8 +35,8 @@
       </ng-template>
     </li>
     <ng-container *ngIf="!volcopy.defaults.values.unified_display">
-      <li ngbNavItem="attrs">
-        <a ngbNavLink i18n>Item Attributes</a>
+      <li role="presentation" ngbNavItem="attrs">
+        <a role="tab" ngbNavLink i18n>Item Attributes</a>
         <ng-template ngbNavContent>
           <div class="mt-2">
             <eg-copy-attrs [context]="context" #copyAttrs
@@ -45,8 +45,8 @@
         </ng-template>
       </li>
     </ng-container>
-    <li ngbNavItem="config">
-      <a ngbNavLink i18n>Preferences</a>
+    <li role="presentation" ngbNavItem="config">
+      <a role="tab" ngbNavLink i18n>Preferences</a>
       <ng-template ngbNavContent>
         <div class="mt-2">
           <eg-volcopy-config [context]="context"></eg-volcopy-config>
index d4f711e..f0428fa 100644 (file)
             (click)="setDefaultTab()" i18n>Set Default View</button>
       </div>
     </div>
-    <ngb-tabset #recordTabs [activeId]="recordTab" 
-      (tabChange)="beforeTabChange($event)">
-      <ngb-tab title="Item Table" i18n-title id="item_table">
-        <ng-template ngbTabContent>
+    <ul ngbNav #recordTabs="ngbNav" [(activeId)]="recordTab"
+      (navChange)="beforeNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+      <li role="presentation" [ngbNavItem]="'item_table'">
+        <a i18n ngbNavLink role="tab">Item Table</a>
+        <ng-template ngbNavContent>
           <eg-catalog-copies [recordId]="recordId"></eg-catalog-copies>
         </ng-template>
-      </ngb-tab>
+      </li>
       <!-- NOTE some tabs send the user over to the AngJS app -->
-      <ngb-tab title="MARC Edit" i18n-title id="marc_edit">
-        <ng-template ngbTabContent>
+      <li role="presentation" [ngbNavItem]="'marc_edit'">
+        <a i18n ngbNavLink role="tab">MARC Edit</a>
+        <ng-template ngbNavContent>
           <div class="mt-3">
             <eg-marc-editor #marcEditor (recordSaved)="handleMarcRecordSaved()" 
               [recordId]="recordId"></eg-marc-editor>
           </div>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="MARC View" i18n-title id="marc_html">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'marc_html'">
+        <a i18n ngbNavLink role="tab">MARC View</a>
+        <ng-template ngbNavContent>
           <eg-marc-html [recordId]="recordId" recordType="bib"></eg-marc-html>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Record Notes" i18n-title id="bibnotes">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'bibnotes'">
+        <a i18n ngbNavLink role="tab">Record Notes</a>
+        <ng-template ngbNavContent>
           <eg-catalog-record-notes [recordId]="recordId">
           </eg-catalog-record-notes>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="View Holds" i18n-title id="holds">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'holds'">
+        <a i18n ngbNavLink role="tab">View Holds</a>
+        <ng-template ngbNavContent>
           <eg-holds-grid [recordId]="recordId"
             preFetchSetting="catalog.record.holds.prefetch"
             printTemplate="holds_for_bib"
             [defaultSort]="[{name:'request_time',dir:'asc'}]"
             [initialPickupLib]="currentSearchOrg()"></eg-holds-grid>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Monograph Parts" i18n-title id="monoparts">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'monoparts'">
+        <a i18n ngbNavLink role="tab">Monograph Parts</a>
+        <ng-template ngbNavContent>
           <eg-catalog-record-parts [recordId]="recordId">
           </eg-catalog-record-parts>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Holdings View" i18n-title id="holdings">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'holdings'">
+        <a i18n ngbNavLink role="tab">Holdings View</a>
+        <ng-template ngbNavContent>
           <eg-holdings-maintenance #holdingsMaint [recordId]="recordId">
           </eg-holdings-maintenance>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Conjoined Items" i18n-title id="conjoined">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'conjoined'">
+        <a i18n ngbNavLink role="tab">Conjoined Items</a>
+        <ng-template ngbNavContent>
           <eg-catalog-record-conjoined [recordId]="recordId">
           </eg-catalog-record-conjoined>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Shelf Browse" i18n-title id="cnbrowse">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'cnbrowse'">
+        <a i18n ngbNavLink role="tab">Shelf Browse</a>
+        <ng-template ngbNavContent>
           <ng-container *ngIf="summary">
             <div class="mt-2">
               <eg-catalog-cn-browse-results [bibSummary]="summary">
             </div>
           </ng-container>
         </ng-template>
-      </ngb-tab>
-    </ngb-tabset>
+      </li>
+    </ul>
+
+    <div [ngbNavOutlet]="recordTabs" class="mt-2"></div>
   </div>
 </div>
 
index 80e6e19..619a5a0 100644 (file)
@@ -1,5 +1,5 @@
 import {Component, OnInit, Input, ViewChild, HostListener} from '@angular/core';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {IdlObject} from '@eg/core/idl.service';
@@ -25,7 +25,7 @@ export class RecordComponent implements OnInit {
     recordTab: string;
     summary: BibRecordSummary;
     searchContext: CatalogSearchContext;
-    @ViewChild('recordTabs', { static: true }) recordTabs: NgbTabset;
+    @ViewChild('recordTabs', { static: true }) recordTabs: NgbNav;
     @ViewChild('marcEditor', {static: false}) marcEditor: MarcEditorComponent;
 
     @ViewChild('holdingsMaint', {static: false})
@@ -83,7 +83,7 @@ export class RecordComponent implements OnInit {
 
     // Changing a tab in the UI means changing the route.
     // Changing the route ultimately results in changing the tab.
-    beforeTabChange(evt: NgbTabChangeEvent) {
+    beforeNavChange(evt: NgbNavChangeEvent) {
 
         // prevent tab changing until after route navigation
         evt.preventDefault();
index 4d2842e..100da1b 100644 (file)
@@ -23,6 +23,4 @@ select.form-control:not([size]):not([multiple]) {
 
 .tab-content {
   padding: 5px;
-  margin-top: 25px;
-  font-weight: bold;
 }
index e75ef48..9db594a 100644 (file)
   
   <div *ngIf="!hideForm()" class="row pt-3 pb-1 mb-1">
   <div class="col-lg-8">
-    <ngb-tabset #searchTabs [activeId]="searchTab" (tabChange)="onTabChange($event)">
-      <ngb-tab title="Keyword Search" i18n-title id="term">
-        <ng-template ngbTabContent>
+    <ul ngbNav #searchTabs="ngbNav" [(activeId)]="searchTab" (navChange)="onNavChange($event)" [keyboard]="true" [roles]="false" role="tablist" class="nav-tabs">
+      <li role="presentation" [ngbNavItem]="'term'">
+        <a i18n ngbNavLink role="tab">Keyword Search</a>
+        <ng-template ngbNavContent>
           <div class="row"
             [ngClass]="{'mt-4': idx === 0, 'mt-1': idx > 0}"
             *ngFor="let q of context.termSearch.query; let idx = index; trackBy:trackByIdx">
             </div>
           </div>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Numeric Search" i18n-title id="ident">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'ident'">
+        <a i18n ngbNavLink role="tab">Numeric Search</a>
+        <ng-template ngbNavContent>
           <div class="row mt-4">
             <div class="col-lg-12">
               <div class="form-inline">
             </div>
           </div>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="MARC Search" i18n-title id="marc">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'marc'">
+        <a i18n ngbNavLink role="tab">MARC Search</a>
+        <ng-template ngbNavContent>
           <div class="row mt-4">
             <div class="col-lg-12">
               <div class="form-inline mt-2" 
             </div>
           </div>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Browse" i18n-title id="browse">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'browse'">
+        <a i18n ngbNavLink role="tab">Browse</a>
+        <ng-template ngbNavContent>
           <div class="row mt-4">
             <div class="col-lg-12 form-inline">
               <label for="field-class" i18n>Browse for</label>
             </div>
           </div>
         </ng-template>
-      </ngb-tab>
-      <ngb-tab title="Shelf Browse" i18n-title id="cnbrowse">
-        <ng-template ngbTabContent>
+      </li>
+      <li role="presentation" [ngbNavItem]="'cnbrowse'">
+        <a i18n ngbNavLink role="tab">Shelf Browse</a>
+        <ng-template ngbNavContent>
           <div class="row mt-4">
             <div class="col-lg-12 form-inline">
               <label for="cnbrowse-term-input" i18n>
             </div>
           </div>
         </ng-template>
-      </ngb-tab>      
-    </ngb-tabset>
+      </li>      
+    </ul>
+
+    <div [ngbNavOutlet]="searchTabs" class="mt-2"></div>
+
   </div>
   <div class="col-lg-4">
     <div class="row">
index c7d9898..60c92e5 100644 (file)
@@ -6,7 +6,7 @@ import {ServerStoreService} from '@eg/core/server-store.service';
 import {CatalogService} from '@eg/share/catalog/catalog.service';
 import {CatalogSearchContext, CatalogSearchState} from '@eg/share/catalog/search-context';
 import {StaffCatalogService} from './catalog.service';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 
 // Maps opac-style default tab names to local tab names.
 const LEGACY_TAB_NAME_MAP = {
@@ -144,7 +144,7 @@ export class SearchFormComponent implements OnInit, AfterViewInit {
         });
     }
 
-    onTabChange(evt: NgbTabChangeEvent) {
+    onNavChange(evt: NgbNavChangeEvent) {
         this.searchTab = evt.nextId;
 
         // Focus after tab-change event has a chance to complete
index 298325b..70470a7 100644 (file)
@@ -1,5 +1,5 @@
 import {Component} from '@angular/core';
-import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {AuthService} from '@eg/core/auth.service';
index 8b3c707..51338a6 100644 (file)
@@ -2,15 +2,15 @@
 <eg-staff-banner bannerText="Triggered Event Log (Item Specific)" i18n-bannerText>
 </eg-staff-banner>
 
-<ul ngbNav #nav="ngbNav" class="nav-tabs">
-  <li [ngbNavItem]="1">
-    <a ngbNavLink i18n>Circulations</a>
+<ul ngbNav #nav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+  <li role="presentation" [ngbNavItem]="1">
+    <a role="tab" ngbNavLink i18n>Circulations</a>
     <ng-template ngbNavContent>
       <eg-item-event-grid #itemEventGrid [item]="itemId" event_type="circ"></eg-item-event-grid>
     </ng-template>
   </li>
-  <li [ngbNavItem]="2">
-    <a ngbNavLink i18n>Holds</a>
+  <li role="presentation" [ngbNavItem]="2">
+    <a role="tab" ngbNavLink i18n>Holds</a>
     <ng-template ngbNavContent>
       <eg-item-event-grid #itemEventGrid [item]="itemId" event_type="hold"></eg-item-event-grid>
     </ng-template>
index 46158a7..bbaa34c 100644 (file)
 
 <hr class="p-2 m-2"/>
 
-<ul ngbNav #statementNav="ngbNav" class="nav-tabs" [activeId]="statementTab">
-  <li ngbNavItem="statement">
-    <a ngbNavLink i18n>Statement</a>
+<ul ngbNav #statementNav="ngbNav" class="nav-tabs" [activeId]="statementTab" [keyboard]="true" [roles]="false" role="tablist">
+  <li role="presentation" ngbNavItem="statement">
+    <a role="tab" ngbNavLink i18n>Statement</a>
     <ng-template ngbNavContent>
       <h4 i18n>Billing Statement</h4>
       <div class="card tight-card">
       </div>
     </ng-template>
   </li>
-  <li ngbNavItem="details">
-    <a ngbNavLink i18n>Details</a>
+  <li role="presentation" ngbNavItem="details">
+    <a role="tab" ngbNavLink i18n>Details</a>
     <ng-template ngbNavContent>
       <div class="mt-3">
         <eg-grid idlClass="mb" #billingGrid toolbarLabel="Bills" 
index 2485775..761c6c5 100644 (file)
 </ng-template>
 
 
-<ul ngbNav #nav="ngbNav" class="nav-tabs" 
+<ul ngbNav #nav="ngbNav" class="nav-tabs"  [keyboard]="true" [roles]="false" role="tablist"
   [activeId]="tab" (navChange)="beforeTabChange($event)">
-  <li ngbNavItem="transactions">
-    <a ngbNavLink i18n>Transactions</a>
+  <li role="presentation" ngbNavItem="transactions">
+    <a role="tab" ngbNavLink i18n>Transactions</a>
     <ng-template ngbNavContent>
 
       <div class="row mt-3 mb-3 pt-2 pb-2 border rounded">
       </eg-grid>
     </ng-template>
   </li>
-  <li ngbNavItem="payments">
-    <a ngbNavLink i18n>Payments</a>
+  <li role="presentation" ngbNavItem="payments">
+    <a role="tab" ngbNavLink i18n>Payments</a>
     <ng-template ngbNavContent>
       <div class="row mt-3 mb-3 pt-2 pb-2 border rounded">
         <div class="col-lg-4">
index 95f9246..255f463 100644 (file)
   </div>
 
   <!-- Name / Preferred Name Tabs -->
-  <ul ngbNav #nameNav="ngbNav" class="nav-tabs" [(activeId)]="nameTab">
-    <li ngbNavItem="primary">
-      <a ngbNavLink i18n>Primary Name</a>
+  <ul ngbNav #nameNav="ngbNav" class="nav-tabs" [(activeId)]="nameTab" [keyboard]="true" [roles]="false" role="tablist">
+    <li role="presentation" ngbNavItem="primary">
+      <a role="tab" ngbNavLink i18n>Primary Name</a>
       <ng-template ngbNavContent>
         <ng-container *ngTemplateOutlet="fieldRow; context: 
           {args: {template: fieldInput, field: 'prefix'}}">
         </ng-container>
       </ng-template>
     </li>
-    <li ngbNavItem="preferred">
-      <a ngbNavLink i18n>Preferred Name</a>
+    <li role="presentation" ngbNavItem="preferred">
+      <a role="tab" ngbNavLink i18n>Preferred Name</a>
       <ng-template ngbNavContent>
         <ng-container *ngTemplateOutlet="fieldRow; context: 
           {args: {template: fieldInput, field: 'pref_prefix'}}">
index f16f69f..83ea3b9 100644 (file)
@@ -2,15 +2,15 @@
 <eg-staff-banner bannerText="Triggered Event Log (Patron Specific)" i18n-bannerText>
 </eg-staff-banner>
 
-<ul ngbNav #nav="ngbNav" class="nav-tabs">
-  <li [ngbNavItem]="1">
-    <a ngbNavLink i18n>Circulations</a>
+<ul ngbNav #nav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+  <li role="presentation" [ngbNavItem]="1">
+    <a role="tab" ngbNavLink i18n>Circulations</a>
     <ng-template ngbNavContent>
       <eg-event-grid #eventGrid [patron]="patronId" event_type="circ"></eg-event-grid>
     </ng-template>
   </li>
-  <li [ngbNavItem]="2">
-    <a ngbNavLink i18n>Holds</a>
+  <li role="presentation" [ngbNavItem]="2">
+    <a role="tab" ngbNavLink i18n>Holds</a>
     <ng-template ngbNavContent>
       <eg-event-grid #eventGrid [patron]="patronId" event_type="hold"></eg-event-grid>
     </ng-template>
index da0fcb0..0bf13f6 100644 (file)
@@ -1,9 +1,9 @@
 
 
-<ul ngbNav #holdsNav="ngbNav" class="nav-tabs">
+<ul ngbNav #holdsNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
 
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Open Hold Requests</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Open Hold Requests</a>
     <ng-template ngbNavContent>
       <eg-holds-grid 
         printTemplate="holds_for_patron"
@@ -19,8 +19,8 @@
     </ng-template>
   </li>
 
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Recently Canceled Holds</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Recently Canceled Holds</a>
     <ng-template ngbNavContent>
       <eg-holds-grid 
         printTemplate="holds_for_patron"
index 58a5e3f..83c5fa5 100644 (file)
@@ -7,10 +7,10 @@
 </ng-template>
 
 <div>
-  <ul ngbNav #itemsNav="ngbNav" class="nav-tabs"
+  <ul ngbNav #itemsNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist"
     [activeId]="itemsTab" (navChange)="tabChange($event)">
-    <li ngbNavItem="checkouts">
-      <a ngbNavLink i18n>Items Checked Out ({{mainList.length}})</a>
+    <li role="presentation" ngbNavItem="checkouts">
+      <a role="tab" ngbNavLink i18n>Items Checked Out ({{mainList.length}})</a>
       <ng-template ngbNavContent>
         <ng-container *ngIf="loading">
           <ng-container *ngTemplateOutlet="progress"></ng-container>
@@ -21,8 +21,8 @@
       </ng-template>
     </li>
     <ng-container *ngIf="displayAltList">
-      <li ngbNavItem="other">
-        <a ngbNavLink i18n>Other/Special Circulations ({{altList.length}})</a>
+      <li role="presentation" ngbNavItem="other">
+        <a role="tab" ngbNavLink i18n>Other/Special Circulations ({{altList.length}})</a>
         <ng-template ngbNavContent>
           <ng-container>
             <ng-container *ngIf="loading">
@@ -35,8 +35,8 @@
         </ng-template>
       </li>
     </ng-container>
-    <li ngbNavItem="noncat">
-      <a ngbNavLink i18n>
+    <li role="presentation" ngbNavItem="noncat">
+      <a role="tab" ngbNavLink i18n>
         <ng-container *ngIf="context.summary && context.summary.stats">
           Non-Cataloged Circulations ({{context.summary.stats.checkouts.noncat}})
         </ng-container>
index 9518163..7cd1d61 100644 (file)
@@ -67,7 +67,7 @@
   <div [ngClass]="{'col-lg-9': showSummaryPane(), 'col-lg-12': !showSummaryPane()}">
 
     <div class="sticky-top-with-nav bg-white">
-      <ul ngbNav #patronNav="ngbNav" class="nav-tabs" [keyboard]="false"
+      <ul ngbNav #patronNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist"
         [activeId]="patronTab" (navChange)="beforeTabChange($event)">
 
         <ng-container *ngIf="patronTab !== 'search'">
@@ -84,8 +84,8 @@
           </li>
         </ng-container>
 
-        <li ngbNavItem="checkout" [disabled]="!context.summary">
-          <a ngbNavLink (click)="navItemClick('checkout', $event)"
+        <li role="presentation" ngbNavItem="checkout" [disabled]="!context.summary">
+          <a role="tab" ngbNavLink (click)="navItemClick('checkout', $event)"
             routerLink="/staff/circ/patron/{{patronId}}/checkout" i18n>Check Out</a>
           <ng-template ngbNavContent>
             <div class="">
@@ -94,8 +94,8 @@
           </ng-template>
         </li>
 
-        <li ngbNavItem="items_out" [disabled]="!context.summary">
-          <a ngbNavLink (click)="navItemClick('items_out', $event)"
+        <li role="presentation" ngbNavItem="items_out" [disabled]="!context.summary">
+          <a role="tab" ngbNavLink (click)="navItemClick('items_out', $event)"
             routerLink="/staff/circ/patron/{{patronId}}/items_out" i18n>
             Items Out ({{counts('checkouts', 'total_out')}})
           </a>
           </ng-template>
         </li>
 
-        <li ngbNavItem="holds" [disabled]="!context.summary">
-          <a ngbNavLink (click)="navItemClick('holds', $event)"
+        <li role="presentation" ngbNavItem="holds" [disabled]="!context.summary">
+          <a role="tab" ngbNavLink (click)="navItemClick('holds', $event)"
             routerLink="/staff/circ/patron/{{patronId}}/holds" i18n>
             Holds ({{counts('holds', 'ready')}} / {{counts('holds', 'total')}})
           </a>
           </ng-template>
         </li>
 
-        <li ngbNavItem="bills" [disabled]="!context.summary">
-          <a ngbNavLink (click)="navItemClick('bills', $event)"
+        <li role="presentation" ngbNavItem="bills" [disabled]="!context.summary">
+          <a role="tab" ngbNavLink (click)="navItemClick('bills', $event)"
             routerLink="/staff/circ/patron/{{patronId}}/bills" i18n>
             Bills 
             <span [ngClass]="{'text-danger': counts('fines', 'balance_owed') > 0}">
           </ng-template>
         </li>
 
-        <li ngbNavItem="messages" [disabled]="!context.summary">
-          <a ngbNavLink (click)="navItemClick('messages', $event)"
+        <li role="presentation" ngbNavItem="messages" [disabled]="!context.summary">
+          <a role="tab" ngbNavLink (click)="navItemClick('messages', $event)"
             routerLink="/staff/circ/patron/{{patronId}}/messages" i18n>Messages</a>
           <ng-template ngbNavContent>
             <div class="">
           </ng-template>
         </li>
 
-        <li ngbNavItem="edit" [disabled]="!context.summary">
-          <a ngbNavLink (click)="navItemClick('edit', $event)"
+        <li role="presentation" ngbNavItem="edit" [disabled]="!context.summary">
+          <a role="tab" ngbNavLink (click)="navItemClick('edit', $event)"
             routerLink="/staff/circ/patron/{{patronId}}/edit" i18n>Edit</a>
           <ng-template ngbNavContent>
             <eg-patron-edit #patronEditor [patronId]="patronId" [toolbar]="editorToolbar">
           </ng-template>
         </li>
 
-        <li ngbNavItem="search" class="ml-auto">
-          <a ngbNavLink (click)="navItemClick('search', $event)"
+        <li role="presentation" ngbNavItem="search" class="ml-auto">
+          <a role="tab" ngbNavLink (click)="navItemClick('search', $event)"
             routerLink="/staff/circ/patron/search" i18n>Patron Search</a>
           <ng-template ngbNavContent>
             <div class="">
index ae759fb..0bee2c4 100644 (file)
@@ -5,10 +5,10 @@
   </div>
 </div>
 
-<ul ngbNav #permsNav="ngbNav" class="nav-tabs">
+<ul ngbNav #permsNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
 
-  <li ngbNavItem>
-    <a ngbNavLink i18n>Working Location(s)</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>Working Location(s)</a>
     <ng-template ngbNavContent>
 
       <div class="striped-rows-odd mt-3 mb-3">
@@ -28,8 +28,8 @@
       </div>
     </ng-template>
   </li>
-  <li ngbNavItem>
-    <a ngbNavLink i18n>User Permissions</a>
+  <li role="presentation" ngbNavItem>
+    <a role="tab" ngbNavLink i18n>User Permissions</a>
     <ng-template ngbNavContent>
 
       <div class="striped-rows-odd mt-3">
index 4723a14..32bb62b 100644 (file)
@@ -3,13 +3,13 @@
 
 <div class="row" id="simple-reporter-main">
   <div class="col-lg-12">
-    <ul ngbNav #simpleRptTabs="ngbNav" class="nav-tabs">
-      <li [ngbNavItem]="'myreports'">
-        <a ngbNavLink i18n>My Reports</a>
+    <ul ngbNav #simpleRptTabs="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+      <li role="presentation" [ngbNavItem]="'myreports'">
+        <a role="tab" ngbNavLink i18n>My Reports</a>
            <ng-template ngbNavContent><eg-sr-reports></eg-sr-reports></ng-template>
       </li>
-      <li [ngbNavItem]="'outputs'">
-        <a ngbNavLink i18n>My Outputs</a>
+      <li role="presentation" [ngbNavItem]="'outputs'">
+        <a role="tab" ngbNavLink i18n>My Outputs</a>
            <ng-template ngbNavContent><eg-sr-outputs></eg-sr-outputs></ng-template>
       </li>
     </ul>
index 353830a..5a0faff 100644 (file)
 </div>
 <div *ngIf="rptType !== ''" class="row mt-2" id="sr-editor-main">
   <div class="col-lg-12">
-    <ul ngbNav #srEditorTabs="ngbNav" class="nav-tabs">
+    <ul ngbNav #srEditorTabs="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
 
-      <li [ngbNavItem]="'rptFields'">
-        <a ngbNavLink i18n>Display Fields</a>
+      <li role="presentation" [ngbNavItem]="'rptFields'">
+        <a role="tab" ngbNavLink i18n>Display Fields</a>
        <ng-template ngbNavContent>
           <eg-sr-field-chooser
             [fieldType]="'display'"
         </ng-template>
       </li>
 
-      <li [ngbNavItem]="'rptSortFields'">
-        <a ngbNavLink i18n>Output Order</a>
+      <li role="presentation" [ngbNavItem]="'rptSortFields'">
+        <a role="tab" ngbNavLink i18n>Output Order</a>
        <ng-template ngbNavContent><eg-sr-sort-order [(fields)]="templ.displayFields" [(orderByNames)]="templ.orderByNames" (orderByNamesChange)="dirty()"></eg-sr-sort-order></ng-template>
       </li>
 
-      <li [ngbNavItem]="'rptFilterFields'">
-        <a ngbNavLink i18n>Filters</a>
+      <li role="presentation" [ngbNavItem]="'rptFilterFields'">
+        <a role="tab" ngbNavLink i18n>Filters</a>
        <ng-template ngbNavContent>
           <eg-sr-field-chooser
             [fieldType]="'filter'"
@@ -86,8 +86,8 @@
         </ng-template>
       </li>
 
-      <li [ngbNavItem]="'rptOutputOptions'">
-        <a ngbNavLink i18n>Output Options</a>
+      <li role="presentation" [ngbNavItem]="'rptOutputOptions'">
+        <a role="tab" ngbNavLink i18n>Output Options</a>
         <ng-template ngbNavContent>
           <eg-sr-output-options
             [readyToSchedule]="readyToSchedule"
index 402f217..be33f11 100644 (file)
@@ -18,9 +18,9 @@
     </button>
   </div>
   <div class="modal-body">
-    <ul ngbNav #bucketDialogTabs="ngbNav" class="nav-tabs">
-      <li [ngbNavItem]="1">
-        <a ngbNavLink i18n>Existing bucket</a>
+    <ul ngbNav #bucketDialogTabs="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist">
+      <li role="presentation" [ngbNavItem]="1">
+        <a role="tab" ngbNavLink i18n>Existing bucket</a>
         <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-3 font-weight-bold"><label for="existing-bucket-name">Name of existing bucket</label></div>
@@ -40,8 +40,8 @@
           </div>
         </ng-template>
       </li>
-      <li [ngbNavItem]="2">
-        <a ngbNavLink i18n>New bucket</a>
+      <li role="presentation" [ngbNavItem]="2">
+        <a role="tab" ngbNavLink i18n>New bucket</a>
         <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-3 font-weight-bold" i18n>Name of new bucket</div>
@@ -70,8 +70,8 @@
           </div>
         </ng-template>
       </li>
-      <li [ngbNavItem]="3">
-        <a ngbNavLink i18n>Shared bucket</a>
+      <li role="presentation" [ngbNavItem]="3">
+        <a role="tab" ngbNavLink i18n>Shared bucket</a>
         <ng-template ngbNavContent>
           <div class="row mt-3">
             <div class="col-lg-3 font-weight-bold" i18n>ID of shared bucket</div>
index 4315e28..ea01690 100644 (file)
 
 <div class="row mt-2">
   <div class="col-lg-12">
-    <ul ngbNav #detailNav="ngbNav" class="nav-tabs" [activeId]="detailTab">
-      <li ngbNavItem="notes">
-        <a ngbNavLink i18n>Notes</a>
+    <ul ngbNav #detailNav="ngbNav" class="nav-tabs" [activeId]="detailTab" [keyboard]="true" [roles]="false" role="tablist">
+      <li role="presentation" ngbNavItem="notes">
+        <a role="tab" ngbNavLink i18n>Notes</a>
         <ng-template ngbNavContent>
           <button class="btn btn-outline-dark mt-3" (click)="newNote()" i18n>New Note</button>
           <div class="mt-3" *ngFor="let note of notes">
           </div>
         </ng-template>
       </li>
-      <li ngbNavItem="notifications">
-        <a ngbNavLink i18n>Staff Notifications</a>
+      <li role="presentation" ngbNavItem="notifications">
+        <a role="tab" ngbNavLink i18n>Staff Notifications</a>
         <ng-template ngbNavContent>
           <button class="btn btn-outline-dark mt-3" 
             (click)="newNotify()" i18n>Add Record of Notification</button>
index e92e9bc..62b84a9 100644 (file)
 
 <div *ngIf="!dataSaving" class="row">
   <div class="col-lg-12">
-    <ul ngbNav #editorNav="ngbNav" class="nav-tabs"
+    <ul ngbNav #editorNav="ngbNav" class="nav-tabs" [keyboard]="true" [roles]="false" role="tablist"
       [activeId]="editorTab" (navChange)="tabChange($event)">
-      <li [ngbNavItem]="'rich'">
-        <a ngbNavLink i18n>Enhanced MARC Editor</a>
+      <li role="presentation" [ngbNavItem]="'rich'">
+        <a role="tab" ngbNavLink i18n>Enhanced MARC Editor</a>
         <ng-template ngbNavContent>
           <ng-container *ngIf="context && context.record">
             <eg-marc-rich-editor [context]="context"></eg-marc-rich-editor>
           </ng-container>
         </ng-template>
       </li>
-      <li ngbNavItem="flat">
-        <a ngbNavLink i18n>Flat Text Editor</a>
+      <li role="presentation" ngbNavItem="flat">
+        <a role="tab" ngbNavLink i18n>Flat Text Editor</a>
         <ng-template ngbNavContent>
           <ng-container *ngIf="context && context.record">
             <eg-marc-flat-editor [context]="context"></eg-marc-flat-editor>
index b239168..af633e7 100644 (file)
@@ -306,7 +306,7 @@ body>.dropdown-menu {z-index: 2100;}
  * 5. Turning off view encapsulation for the acq search component
  *    breaks a lot of styles.
  */
-#acq-search-page ngb-tabset .nav.nav-tabs {
+#acq-search-page ngbNav .nav.nav-tabs {
   background-color: rgb(247, 247, 247);
 }