Chore: ditch the abandoned ngx-bootstrap-icons, roll our own (#14665)

This commit is contained in:
shamoon authored and GitHub committed 2026-11-02 21:25:35 -08:00
1 parent 786eac0b22
commit 7cdf8ec3c2
249 files changed
+1092 -1216

No files matched your search

@@ -33,9 +33,9 @@
i18n-title
>
@if (copiedIndex() === $index) {
<i-bs name="clipboard-check"></i-bs>
<pngx-bs-icon name="clipboard-check"></pngx-bs-icon>
} @else {
<i-bs name="clipboard"></i-bs>
<pngx-bs-icon name="clipboard"></pngx-bs-icon>
}
<span class="visually-hidden" i18n>Copy content</span>
</button>
@@ -1,6 +1,5 @@
import { Clipboard } from '@angular/cdk/clipboard'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { DocumentBarcodesComponent } from './document-barcodes.component'
const barcodes = [
@@ -16,10 +15,7 @@ describe('DocumentBarcodesComponent', () => {
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [
DocumentBarcodesComponent,
NgxBootstrapIconsModule.pick(allIcons),
],
imports: [DocumentBarcodesComponent],
}).compileComponents()
fixture = TestBed.createComponent(DocumentBarcodesComponent)
@@ -53,15 +49,15 @@ describe('DocumentBarcodesComponent', () => {
fixture.detectChanges()
expect(copySpy).toHaveBeenCalledWith('ASN00123')
expect(component.copiedIndex()).toEqual(0)
expect(buttons[0].querySelector('i-bs').getAttribute('name')).toEqual(
'clipboard-check'
)
expect(
buttons[0].querySelector('pngx-bs-icon').getAttribute('name')
).toEqual('clipboard-check')
jest.advanceTimersByTime(3000)
fixture.detectChanges()
expect(component.copiedIndex()).toBeNull()
expect(buttons[0].querySelector('i-bs').getAttribute('name')).toEqual(
'clipboard'
)
expect(
buttons[0].querySelector('pngx-bs-icon').getAttribute('name')
).toEqual('clipboard')
jest.useRealTimers()
})
@@ -1,12 +1,12 @@
import { Clipboard } from '@angular/cdk/clipboard'
import { Component, inject, input, OnDestroy, signal } from '@angular/core'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { BootstrapIconComponent } from 'src/app/components/common/bootstrap-icon/bootstrap-icon.component'
import { DocumentBarcode } from 'src/app/data/document-barcode'
@Component({
selector: 'pngx-document-barcodes',
templateUrl: './document-barcodes.component.html',
imports: [NgxBootstrapIconsModule],
imports: [BootstrapIconComponent],
})
export class DocumentBarcodesComponent implements OnDestroy {
private readonly clipboard = inject(Clipboard)
@@ -1,6 +1,6 @@
<pngx-page-header [title]="title()" [id]="documentId()">
<button type="button" class="btn btn-sm btn-outline-danger me-md-4" (click)="delete()" [disabled]="!userIsOwner" *pngxIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.Document }" aria-label="Delete" i18n-aria-label>
<i-bs width="1.2em" height="1.2em" name="trash"></i-bs><span class="d-none d-lg-inline ps-1" i18n>Delete</span>
<pngx-bs-icon width="1.2em" height="1.2em" name="trash"></pngx-bs-icon><span class="d-none d-lg-inline ps-1" i18n>Delete</span>
</button>
<pngx-document-version-dropdown
@@ -18,7 +18,7 @@
@if (downloading()) {
<div class="spinner-border spinner-border-sm" role="status"></div>
} @else {
<i-bs width="1.2em" height="1.2em" name="download"></i-bs>
<pngx-bs-icon width="1.2em" height="1.2em" name="download"></pngx-bs-icon>
}
<span class="d-none d-lg-inline ps-1" i18n>Download</span>
</button>
@@ -42,28 +42,28 @@
<div class="ms-md-auto" ngbDropdown>
<button class="btn btn-sm btn-outline-primary" id="actionsDropdown" ngbDropdownToggle aria-label="Actions" i18n-aria-label>
<i-bs name="three-dots"></i-bs><div class="d-none d-sm-inline ms-1"><ng-container i18n>Actions</ng-container></div>
<pngx-bs-icon name="three-dots"></pngx-bs-icon><div class="d-none d-sm-inline ms-1"><ng-container i18n>Actions</ng-container></div>
</button>
<div ngbDropdownMenu aria-labelledby="actionsDropdown" class="shadow">
<button ngbDropdownItem (click)="reprocess()" [disabled]="!userCanEdit || !userIsOwner">
<i-bs width="1em" height="1em" name="arrow-counterclockwise" class="me-2"></i-bs><span i18n>Reprocess</span>
<pngx-bs-icon width="1em" height="1em" name="arrow-counterclockwise" class="me-2"></pngx-bs-icon><span i18n>Reprocess</span>
</button>
<button ngbDropdownItem (click)="printDocument()" [hidden]="useNativePdfViewer || isMobile">
<i-bs width="1em" height="1em" name="printer" class="me-2"></i-bs><span i18n>Print</span>
<pngx-bs-icon width="1em" height="1em" name="printer" class="me-2"></pngx-bs-icon><span i18n>Print</span>
</button>
<button ngbDropdownItem (click)="moreLike()">
<i-bs width="1em" height="1em" name="diagram-3" class="me-2"></i-bs><span i18n>More like this</span>
<pngx-bs-icon width="1em" height="1em" name="diagram-3" class="me-2"></pngx-bs-icon><span i18n>More like this</span>
</button>
<button ngbDropdownItem (click)="editPdf()" [disabled]="!userIsOwner || !userCanEdit || originalContentRenderType !== ContentRenderType.PDF">
<i-bs name="pencil" class="me-2"></i-bs><ng-container i18n>PDF Editor</ng-container>
<pngx-bs-icon name="pencil" class="me-2"></pngx-bs-icon><ng-container i18n>PDF Editor</ng-container>
</button>
@if (userIsOwner && (requiresPassword || password)) {
<button ngbDropdownItem (click)="removePassword()" [disabled]="!password">
<i-bs name="unlock" class="me-2"></i-bs><ng-container i18n>Remove Password</ng-container>
<pngx-bs-icon name="unlock" class="me-2"></pngx-bs-icon><ng-container i18n>Remove Password</ng-container>
</button>
}
</div>
@@ -71,15 +71,15 @@
<div class="ms-md-auto" ngbDropdown>
<button class="btn btn-sm btn-outline-primary" id="sendDropdown" ngbDropdownToggle aria-label="Send" i18n-aria-label>
<i-bs name="send"></i-bs><div class="d-none d-sm-inline ms-1"><ng-container i18n>Send</ng-container></div>
<pngx-bs-icon name="send"></pngx-bs-icon><div class="d-none d-sm-inline ms-1"><ng-container i18n>Send</ng-container></div>
</button>
<div ngbDropdownMenu aria-labelledby="sendDropdown" class="shadow">
<button ngbDropdownItem (click)="openShareLinks()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.ShareLink }">
<i-bs name="link" class="me-2"></i-bs><span i18n>Share Links</span>
<pngx-bs-icon name="link" class="me-2"></pngx-bs-icon><span i18n>Share Links</span>
</button>
@if (emailEnabled) {
<button ngbDropdownItem (click)="openEmailDocument()">
<i-bs name="envelope" class="me-2"></i-bs><span i18n>Email</span>
<pngx-bs-icon name="envelope" class="me-2"></pngx-bs-icon><span i18n>Email</span>
</button>
}
</div>
@@ -95,13 +95,13 @@
<div class="btn-toolbar mb-1 pb-3 gap-2 row-gap-2 border-bottom">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary" i18n-title title="Close" (click)="close()">
<i-bs width="1.2em" height="1.2em" name="x"></i-bs>
<pngx-bs-icon width="1.2em" height="1.2em" name="x"></pngx-bs-icon>
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" i18n-title title="Previous" (click)="previousDoc()" [disabled]="!hasPrevious()">
<i-bs width="1.2em" height="1.2em" name="arrow-left"></i-bs>
<pngx-bs-icon width="1.2em" height="1.2em" name="arrow-left"></pngx-bs-icon>
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" i18n-title title="Next" (click)="nextDoc()" [disabled]="!hasNext()">
<i-bs width="1.2em" height="1.2em" name="arrow-right"></i-bs>
<pngx-bs-icon width="1.2em" height="1.2em" name="arrow-right"></pngx-bs-icon>
</button>
</div>
@@ -439,7 +439,7 @@
<div class="btn-group">
<ng-container *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.Document }">
<button type="submit" class="order-3 btn btn-sm btn-primary" title="Save" i18n-title [disabled]="!userCanEdit || networkActive() || (isDirty$ | async) !== true">
<i-bs class="d-md-none" width="1.2em" height="1.2em" name="check-lg"></i-bs><span class="d-none d-md-inline" i18n>Save</span>
<pngx-bs-icon class="d-md-none" width="1.2em" height="1.2em" name="floppy"></pngx-bs-icon><span class="d-none d-md-inline" i18n>Save</span>
</button>
@if (hasNext()) {
<button type="button" class="order-1 btn btn-sm btn-outline-primary d-none d-md-inline-block" (click)="saveEditNext()" i18n [disabled]="!userCanEdit || networkActive() || (isDirty$ | async) !== true">Save &amp; next</button>
@@ -447,7 +447,7 @@
<button type="button" class="order-2 btn btn-sm btn-outline-primary d-none d-md-inline-block" (click)="save(true)" i18n [disabled]="!userCanEdit || networkActive() || (isDirty$ | async) !== true">Save &amp; close</button>
}
<button type="button" class="order-0 btn btn-sm btn-outline-secondary" (click)="discard()" title="Discard" i18n-title [disabled]="!userCanEdit || networkActive() || (isDirty$ | async) !== true">
<i-bs class="d-md-none" width="1.2em" height="1.2em" name="arrow-counterclockwise"></i-bs><span class="d-none d-md-inline" i18n>Discard</span>
<pngx-bs-icon class="d-md-none" width="1.2em" height="1.2em" name="arrow-counterclockwise"></pngx-bs-icon><span class="d-none d-md-inline" i18n>Discard</span>
</button>
<div class="btn-group order-4 d-md-none" ngbDropdown placement="bottom-end top-end" role="group">
<button type="button" class="btn btn-sm btn-outline-primary dropdown-toggle dropdown-toggle-split" ngbDropdownToggle aria-label="More save options" i18n-aria-label [disabled]="!userCanEdit || networkActive() || (isDirty$ | async) !== true"></button>
@@ -499,7 +499,7 @@
}
<div class="input-group input-group-sm w-auto flex-nowrap">
<button class="btn btn-outline-secondary" type="button" (click)="decreaseZoom()" aria-label="Zoom out" i18n-aria-label>
<i-bs width="1em" height="1em" name="dash"></i-bs>
<pngx-bs-icon width="1em" height="1em" name="dash"></pngx-bs-icon>
</button>
<select class="form-select" (change)="setZoom($event.target.value)" [ngModelOptions]="{standalone: true}" [ngModel]="currentZoom" aria-label="Zoom" i18n-aria-label>
@for (setting of zoomSettings; track setting) {
@@ -509,7 +509,7 @@
}
</select>
<button class="btn btn-outline-secondary" type="button" (click)="increaseZoom()" aria-label="Zoom in" i18n-aria-label>
<i-bs width="1em" height="1em" name="plus"></i-bs>
<pngx-bs-icon width="1em" height="1em" name="plus"></pngx-bs-icon>
</button>
</div>
</div>
@@ -22,7 +22,6 @@ import {
NgbModal,
NgbModalRef,
} from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { DeviceDetectorService } from 'ngx-device-detector'
import { Subject, of, throwError } from 'rxjs'
import { routes } from 'src/app/app-routing.module'
@@ -152,11 +151,7 @@ describe('DocumentDetailComponent', () => {
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [
DocumentDetailComponent,
RouterModule.forRoot(routes),
NgxBootstrapIconsModule.pick(allIcons),
],
imports: [DocumentDetailComponent, RouterModule.forRoot(routes)],
providers: [
DocumentTitlePipe,
{
@@ -26,7 +26,6 @@ import {
NgbNavModule,
} from '@ng-bootstrap/ng-bootstrap'
import { dirtyCheck, DirtyComponent } from '@ngneat/dirty-check-forms'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { DeviceDetectorService } from 'ngx-device-detector'
import { BehaviorSubject, merge, Observable, of, Subject, timer } from 'rxjs'
import {
@@ -41,6 +40,7 @@ import {
takeUntil,
tap,
} from 'rxjs/operators'
import { BootstrapIconComponent } from 'src/app/components/common/bootstrap-icon/bootstrap-icon.component'
import { Correspondent } from 'src/app/data/correspondent'
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
import { CustomFieldInstance } from 'src/app/data/custom-field-instance'
@@ -198,7 +198,7 @@ interface IncomingDocumentUpdate {
SafeUrlPipe,
NgbNavModule,
NgbDropdownModule,
NgxBootstrapIconsModule,
BootstrapIconComponent,
TextAreaComponent,
RouterModule,
PngxPdfViewerComponent,
@@ -4,7 +4,6 @@ import { DatePipe } from '@angular/common'
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
import { provideHttpClientTesting } from '@angular/common/http/testing'
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { of } from 'rxjs'
import { AuditLogAction } from 'src/app/data/auditlog-entry'
import { DataType } from 'src/app/data/datatype'
@@ -27,11 +26,7 @@ describe('DocumentHistoryComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
DocumentHistoryComponent,
NgbCollapseModule,
NgxBootstrapIconsModule.pick(allIcons),
],
imports: [DocumentHistoryComponent, NgbCollapseModule],
providers: [
DatePipe,
provideHttpClient(withInterceptorsFromDi()),
@@ -1,7 +1,6 @@
import { AsyncPipe, KeyValuePipe, TitleCasePipe } from '@angular/common'
import { Component, Input, OnInit, inject, signal } from '@angular/core'
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { Observable, first, forkJoin, map, of, shareReplay } from 'rxjs'
import { AuditLogAction, AuditLogEntry } from 'src/app/data/auditlog-entry'
import { DataType } from 'src/app/data/datatype'
@@ -23,7 +22,6 @@ import { UserService } from 'src/app/services/rest/user.service'
AsyncPipe,
KeyValuePipe,
TitleCasePipe,
NgxBootstrapIconsModule,
],
})
export class DocumentHistoryComponent implements OnInit {
@@ -1,6 +1,6 @@
<div class="btn-group" ngbDropdown autoClose="outside">
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" ngbDropdownToggle aria-label="Versions" i18n-aria-label>
<i-bs name="file-earmark-diff"></i-bs>
<pngx-bs-icon name="file-earmark-diff"></pngx-bs-icon>
<span class="d-none d-lg-inline ps-1" i18n>Versions</span>
@if (versions.length > 1) {
<span class="badge text-bg-secondary ms-1">{{ versions.length }}</span>
@@ -35,7 +35,7 @@
title="Upload a new version"
i18n-title
>
<i-bs name="file-earmark-plus"></i-bs><span class="ps-1" i18n>Upload</span>
<pngx-bs-icon name="file-earmark-plus"></pngx-bs-icon><span class="ps-1" i18n>Upload</span>
</button>
<button
class="btn btn-sm btn-outline-secondary w-100"
@@ -44,7 +44,7 @@
title="Use an existing document"
i18n-title
>
<i-bs name="file-earmark"></i-bs><span class="ps-1" i18n>Existing</span>
<pngx-bs-icon name="file-earmark"></pngx-bs-icon><span class="ps-1" i18n>Existing</span>
</button>
</div>
} @else {
@@ -81,9 +81,9 @@
>
<div class="check mx-3">
@if (selectedVersionId === version.id) {
<i-bs name="check-circle"></i-bs>
<pngx-bs-icon name="check-circle"></pngx-bs-icon>
} @else {
<i-bs class="text-muted" name="circle"></i-bs>
<pngx-bs-icon class="text-muted" name="circle"></pngx-bs-icon>
}
</div>
<div class="d-flex flex-column">
@@ -121,9 +121,9 @@
(click)="isEditingVersion(version.id) ? submitEditedVersionLabel(version, $event) : beginEditingVersion(version, $event)"
>
@if (isEditingVersion(version.id)) {
<i-bs width=".8rem" height=".8rem" name="check-lg"></i-bs>
<pngx-bs-icon width=".8rem" height=".8rem" name="check-lg"></pngx-bs-icon>
} @else {
<i-bs width=".8rem" height=".8rem" name="pencil"></i-bs>
<pngx-bs-icon width=".8rem" height=".8rem" name="pencil"></pngx-bs-icon>
}
</button>
}
@@ -3,13 +3,12 @@ import { SimpleChange, signal } from '@angular/core'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { By } from '@angular/platform-browser'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { Subject, of, throwError } from 'rxjs'
import { DocumentVersionInfo } from 'src/app/data/document'
import {
PermissionAction,
PermissionsService,
PermissionType,
PermissionsService,
} from 'src/app/services/permissions.service'
import { DocumentService } from 'src/app/services/rest/document.service'
import { SettingsService } from 'src/app/services/settings.service'
@@ -64,10 +63,7 @@ describe('DocumentVersionDropdownComponent', () => {
}
await TestBed.configureTestingModule({
imports: [
DocumentVersionDropdownComponent,
NgxBootstrapIconsModule.pick(allIcons),
],
imports: [DocumentVersionDropdownComponent],
providers: [
DatePipe,
{
@@ -12,7 +12,6 @@ import {
} from '@angular/core'
import { FormsModule } from '@angular/forms'
import { NgbDropdownModule, NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { merge, of, Subject } from 'rxjs'
import {
filter,
@@ -24,6 +23,7 @@ import {
takeUntil,
tap,
} from 'rxjs/operators'
import { BootstrapIconComponent } from 'src/app/components/common/bootstrap-icon/bootstrap-icon.component'
import { DocumentVersionInfo } from 'src/app/data/document'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
@@ -44,7 +44,7 @@ import { AddExistingDocumentVersionDialogComponent } from './add-existing-docume
imports: [
FormsModule,
NgbDropdownModule,
NgxBootstrapIconsModule,
BootstrapIconComponent,
ConfirmButtonComponent,
IfPermissionsDirective,
SlicePipe,
@@ -2,10 +2,10 @@
<button type="button" class="btn btn-outline-secondary btn-sm me-2"
(click)="expand = !expand" aria-label="Toggle document metadata" i18n-aria-label>
@if (!expand) {
<i-bs width="1.2em" height="1.2em" name="caret-down"></i-bs>
<pngx-bs-icon width="1.2em" height="1.2em" name="caret-down"></pngx-bs-icon>
}
@if (expand) {
<i-bs width="1.2em" height="1.2em" name="caret-up"></i-bs>
<pngx-bs-icon width="1.2em" height="1.2em" name="caret-up"></pngx-bs-icon>
}
</button>
{{title}}
@@ -1,5 +1,4 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { MetadataCollapseComponent } from './metadata-collapse.component'
const metadata = [
@@ -24,10 +23,7 @@ describe('MetadataCollapseComponent', () => {
beforeEach(async () => {
TestBed.configureTestingModule({
providers: [],
imports: [
MetadataCollapseComponent,
NgxBootstrapIconsModule.pick(allIcons),
],
imports: [MetadataCollapseComponent],
}).compileComponents()
fixture = TestBed.createComponent(MetadataCollapseComponent)
@@ -1,12 +1,12 @@
import { Component, Input } from '@angular/core'
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { BootstrapIconComponent } from 'src/app/components/common/bootstrap-icon/bootstrap-icon.component'
@Component({
selector: 'pngx-metadata-collapse',
templateUrl: './metadata-collapse.component.html',
styleUrls: ['./metadata-collapse.component.scss'],
imports: [NgbCollapseModule, NgxBootstrapIconsModule],
imports: [NgbCollapseModule, BootstrapIconComponent],
})
export class MetadataCollapseComponent {
constructor() {}