diff --git a/src-ui/angular.json b/src-ui/angular.json
index 633be88c5f..c3faf73f26 100644
--- a/src-ui/angular.json
+++ b/src-ui/angular.json
@@ -69,6 +69,9 @@
"src/polyfills.ts"
],
"tsConfig": "tsconfig.app.json",
+ "loader": {
+ ".svg": "text"
+ },
"localize": true,
"assets": [
"src/apple-touch-icon.png",
diff --git a/src-ui/e2e/document-list/document-list.spec.ts b/src-ui/e2e/document-list/document-list.spec.ts
index 5365b48268..b86ffa873f 100644
--- a/src-ui/e2e/document-list/document-list.spec.ts
+++ b/src-ui/e2e/document-list/document-list.spec.ts
@@ -123,7 +123,7 @@ test('sorting', async ({ page }) => {
await page.getByRole('button', { name: 'Notes' }).click()
await expect(page).toHaveURL(/sort=num_notes/)
await page.getByRole('button', { name: 'Sort' }).click()
- await page.locator('.w-100 > label > i-bs').first().click()
+ await page.locator('.w-100 > label > pngx-bs-icon').first().click()
await expect(page).not.toHaveURL(/reverse=1/)
})
diff --git a/src-ui/jest.config.js b/src-ui/jest.config.js
index 89a3341307..ffea6ccc21 100644
--- a/src-ui/jest.config.js
+++ b/src-ui/jest.config.js
@@ -28,7 +28,7 @@ module.exports = {
'abstract-paperless-service',
],
transformIgnorePatterns: [
- 'node_modules/(?!.*(\\.mjs$|tslib|lodash-es|normalize-diacritics|marked|@angular/common/locales/.*\\.js$))',
+ 'node_modules/(?!.*(\\.mjs$|tslib|lodash-es|normalize-diacritics|marked|@angular/common/locales/.*\\.js$|bootstrap-icons/icons/.*\\.svg$))',
],
moduleNameMapper: {
...esmPreset.moduleNameMapper,
diff --git a/src-ui/package.json b/src-ui/package.json
index a1ce49eed4..9255ff139e 100644
--- a/src-ui/package.json
+++ b/src-ui/package.json
@@ -28,11 +28,11 @@
"@ngneat/dirty-check-forms": "^3.0.3",
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.8",
+ "bootstrap-icons": "^1.13.2",
"file-saver": "^2.0.5",
"lodash-es": "^4.18.1",
"marked": "~18.1.1",
"mime-names": "^1.0.0",
- "ngx-bootstrap-icons": "^1.9.3",
"ngx-color": "^10.1.0",
"ngx-cookie-service": "^22.0.0",
"ngx-device-detector": "^12.0.0",
diff --git a/src-ui/pnpm-lock.yaml b/src-ui/pnpm-lock.yaml
index bcbc11d953..3e743b69ef 100644
--- a/src-ui/pnpm-lock.yaml
+++ b/src-ui/pnpm-lock.yaml
@@ -51,6 +51,9 @@ importers:
bootstrap:
specifier: ^5.3.8
version: 5.3.8(@popperjs/core@2.11.8)
+ bootstrap-icons:
+ specifier: ^1.13.2
+ version: 1.13.2
file-saver:
specifier: ^2.0.5
version: 2.0.5
@@ -63,9 +66,6 @@ importers:
mime-names:
specifier: ^1.0.0
version: 1.0.0
- ngx-bootstrap-icons:
- specifier: ^1.9.3
- version: 1.9.3(@angular/common@22.2.3(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2))
ngx-color:
specifier: ^10.1.0
version: 10.1.0(@angular/common@22.2.3(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2))
@@ -2391,6 +2391,9 @@ packages:
resolution: {integrity: sha512-DkVaaQHymRhpYEYo9x1oo7Q7B0Y6KJUsjm3c9eTyFDby4MHLBTwZ6ZDWBel5zrYxj1WsZgC5oLpiz+93MluXeA==}
engines: {node: '>=20.19.0'}
+ bootstrap-icons@1.13.2:
+ resolution: {integrity: sha512-fAU1Ly3dH7hwRg+CB8EZ0Vl0fF80zgXHeUVJyfUOKzoURr+TbwISbCW5tKUoQLERaWYG2emTCybcPbD96hdD1A==}
+
bootstrap@5.3.8:
resolution: {integrity: sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==}
peerDependencies:
@@ -3421,13 +3424,6 @@ packages:
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
- ngx-bootstrap-icons@1.9.3:
- resolution: {integrity: sha512-UsFqJ/cn0u5W39hVMIDbm+ze1dCF9fDV839scqeimi70Efcmg41zOx6GgR6i2gWAVFR0OBso1cdqb4E75XhTSw==}
- engines: {node: '>= 16.18.1', npm: '>= 8.11.0'}
- peerDependencies:
- '@angular/common': '>= 13.3.8'
- '@angular/core': '>= 13.3.8'
-
ngx-color@10.1.0:
resolution: {integrity: sha512-yuxlE1LfN+PABIO4hv0Gw5ksq8g9XkMJKrGPn2SWbrre/gsH+kkyyn3rwSCurinnLCnw7czqenwQUtnBJm8yww==}
peerDependencies:
@@ -6411,6 +6407,8 @@ snapshots:
boolbase@2.0.0: {}
+ bootstrap-icons@1.13.2: {}
+
bootstrap@5.3.8(@popperjs/core@2.11.8):
dependencies:
'@popperjs/core': 2.11.8
@@ -7648,12 +7646,6 @@ snapshots:
neo-async@2.6.2: {}
- ngx-bootstrap-icons@1.9.3(@angular/common@22.2.3(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2)):
- dependencies:
- '@angular/common': 22.2.3(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2))(rxjs@7.8.2)
- '@angular/core': 22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2)
- tslib: 2.8.1
-
ngx-color@10.1.0(@angular/common@22.2.3(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2)):
dependencies:
'@angular/common': 22.2.3(@angular/core@22.2.3(@angular/compiler@22.2.3)(rxjs@7.8.2))(rxjs@7.8.2)
diff --git a/src-ui/src/app/app.component.spec.ts b/src-ui/src/app/app.component.spec.ts
index d93534d80f..bd81eebaeb 100644
--- a/src-ui/src/app/app.component.spec.ts
+++ b/src-ui/src/app/app.component.spec.ts
@@ -3,7 +3,6 @@ import { provideHttpClientTesting } from '@angular/common/http/testing'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { Router, RouterModule } from '@angular/router'
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap'
-import { allIcons, NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import {
provideUiTour,
TourNgBootstrap,
@@ -47,7 +46,6 @@ describe('AppComponent', () => {
ToastsComponent,
FileDropComponent,
TourNgBootstrap,
- NgxBootstrapIconsModule.pick(allIcons),
],
providers: [
PermissionsGuard,
diff --git a/src-ui/src/app/components/admin/config/config.component.html b/src-ui/src/app/components/admin/config/config.component.html
index 31e9aecfa6..50ecb8ef03 100644
--- a/src-ui/src/app/components/admin/config/config.component.html
+++ b/src-ui/src/app/components/admin/config/config.component.html
@@ -28,7 +28,7 @@
{{option.title}}
-
+
@if (isExternallyConfigured(option.config_key)) {
@if (isSet(option.key)) {
@@ -40,11 +40,11 @@
@if (isSet(option.key)) {
@if (isExternallyConfigured(option.config_key)) {
} @else {
}
}
diff --git a/src-ui/src/app/components/admin/config/config.component.spec.ts b/src-ui/src/app/components/admin/config/config.component.spec.ts
index 650761c7dd..0da90f7da7 100644
--- a/src-ui/src/app/components/admin/config/config.component.spec.ts
+++ b/src-ui/src/app/components/admin/config/config.component.spec.ts
@@ -6,7 +6,6 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { NgSelectModule } from '@ng-select/ng-select'
-import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { of, throwError } from 'rxjs'
import {
ConfigCategory,
@@ -39,7 +38,6 @@ describe('ConfigComponent', () => {
NgSelectModule,
FormsModule,
ReactiveFormsModule,
- NgxBootstrapIconsModule.pick(allIcons),
ConfigComponent,
TextComponent,
SelectComponent,
diff --git a/src-ui/src/app/components/admin/config/config.component.ts b/src-ui/src/app/components/admin/config/config.component.ts
index 6894a50be3..1923677c64 100644
--- a/src-ui/src/app/components/admin/config/config.component.ts
+++ b/src-ui/src/app/components/admin/config/config.component.ts
@@ -9,7 +9,6 @@ import {
} from '@angular/forms'
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'
import { DirtyComponent, dirtyCheck } from '@ngneat/dirty-check-forms'
-import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import {
BehaviorSubject,
Observable,
@@ -17,6 +16,7 @@ import {
first,
takeUntil,
} from 'rxjs'
+import { BootstrapIconComponent } from 'src/app/components/common/bootstrap-icon/bootstrap-icon.component'
import {
ConfigCategory,
ConfigOption,
@@ -52,7 +52,7 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading
NgbNavModule,
FormsModule,
ReactiveFormsModule,
- NgxBootstrapIconsModule,
+ BootstrapIconComponent,
],
})
export class ConfigComponent
diff --git a/src-ui/src/app/components/admin/logs/logs.component.spec.ts b/src-ui/src/app/components/admin/logs/logs.component.spec.ts
index c458804ce8..9f525a1735 100644
--- a/src-ui/src/app/components/admin/logs/logs.component.spec.ts
+++ b/src-ui/src/app/components/admin/logs/logs.component.spec.ts
@@ -8,7 +8,6 @@ import { provideHttpClientTesting } from '@angular/common/http/testing'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { BrowserModule, By } from '@angular/platform-browser'
import { NgbModule, NgbNavLink } from '@ng-bootstrap/ng-bootstrap'
-import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { of, throwError } from 'rxjs'
import { LogService } from 'src/app/services/rest/log.service'
import { PageHeaderComponent } from '../../common/page-header/page-header.component'
@@ -40,7 +39,6 @@ describe('LogsComponent', () => {
imports: [
BrowserModule,
NgbModule,
- NgxBootstrapIconsModule.pick(allIcons),
LogsComponent,
PageHeaderComponent,
CommonModule,
diff --git a/src-ui/src/app/components/admin/settings/settings.component.html b/src-ui/src/app/components/admin/settings/settings.component.html
index 89ea62c3e1..c314f1afcc 100644
--- a/src-ui/src/app/components/admin/settings/settings.component.html
+++ b/src-ui/src/app/components/admin/settings/settings.component.html
@@ -5,7 +5,7 @@
i18n-info
>
@if (canViewSystemStatus) {
}
@@ -207,7 +207,7 @@
[routerLinkActiveOptions]="{ exact: !(slimSidebarEnabled || attributesSectionsCollapsed) }" (click)="closeMenu()"
ngbPopover="Attributes" i18n-ngbPopover [disablePopover]="!slimSidebarPopoversEnabled" placement="end"
container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim">
- Attributes
+ Attributes
@if (!slimSidebarEnabled && canSaveSettings) {
-
+
}
@@ -228,27 +228,27 @@
@@ -259,7 +259,7 @@
- Saved Views
+ Saved Views
@if (settingsService.organizingSidebarItems()) {
@@ -270,7 +270,7 @@
- Share links
+ Share links
@if (settingsService.organizingSidebarItems()) {
@@ -283,7 +283,7 @@
- Workflows
+ Workflows
@if (settingsService.organizingSidebarItems()) {
@@ -294,7 +294,7 @@
- Mail
+ Mail
@if (settingsService.organizingSidebarItems()) {
@@ -304,7 +304,7 @@
- Trash
+ Trash
@@ -320,21 +320,21 @@
- Settings
+ Settings
- Configuration
+ Configuration
- Users & Groups
+ Users & Groups
- Tasks
+ Tasks
@if (tasksService.needsAttentionTasksCount > 0 && !slimSidebarEnabled) {
{{tasksService.needsAttentionTasksCount}}
}
@@ -357,7 +357,7 @@
- Logs
+ Logs
}
@@ -366,7 +366,7 @@
target="_blank" rel="noopener noreferrer" href="https://docs.paperless-ngx.com" ngbPopover="Documentation"
i18n-ngbPopover [disablePopover]="!slimSidebarPopoversEnabled" placement="end" container="body"
triggers="mouseenter:mouseleave" popoverClass="popover-slim">
- Documentation
+ Documentation
@if (settingsService.organizingSidebarItems()) {
@@ -408,7 +408,7 @@
href="https://github.com/paperless-ngx/paperless-ngx/releases"
[ngbPopover]="updateAvailablePopContent" popoverClass="shadow" triggers="mouseenter:mouseleave"
container="body">
-
+
@if (appRemoteVersion()?.update_available) {
Update available
}
@@ -418,7 +418,7 @@
-
+
}
diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss
index 933dd93743..57e605eae1 100644
--- a/src-ui/src/app/components/app-frame/app-frame.component.scss
+++ b/src-ui/src/app/components/app-frame/app-frame.component.scss
@@ -142,7 +142,7 @@ main {
padding-left: 0;
padding-right: 0;
- i-bs {
+ pngx-bs-icon {
margin-right: 0 !important;
}
}
@@ -268,7 +268,7 @@ main {
}
}
- i-bs {
+ pngx-bs-icon {
position: relative;
top: -1px;
}
@@ -279,7 +279,7 @@ main {
align-items: center;
min-width: 0;
- > i-bs {
+ > pngx-bs-icon {
flex: 0 0 auto;
}
@@ -373,11 +373,11 @@ main {
width: 1.8rem;
height: 100%;
- i-bs {
+ pngx-bs-icon {
opacity: 0.5;
}
- &:hover i-bs {
+ &:hover pngx-bs-icon {
opacity: 1;
}
}
@@ -392,7 +392,7 @@ main {
text-decoration: underline;
}
- i-bs {
+ pngx-bs-icon {
margin-bottom: 2px;
}
}
@@ -665,7 +665,7 @@ main {
.navbar .dropdown-menu {
font-size: 0.875rem; // body size
- a i-bs, button i-bs {
+ a pngx-bs-icon, button pngx-bs-icon {
opacity: 0.6;
}
}
@@ -693,7 +693,7 @@ main {
cursor: move;
}
-::ng-deep .navItemDrag .position-absolute i-bs {
+::ng-deep .navItemDrag .position-absolute pngx-bs-icon {
display: none;
}
diff --git a/src-ui/src/app/components/app-frame/app-frame.component.spec.ts b/src-ui/src/app/components/app-frame/app-frame.component.spec.ts
index 83cebd8890..2b4c3d63a7 100644
--- a/src-ui/src/app/components/app-frame/app-frame.component.spec.ts
+++ b/src-ui/src/app/components/app-frame/app-frame.component.spec.ts
@@ -10,7 +10,6 @@ import { BrowserModule, By } from '@angular/platform-browser'
import { ActivatedRoute, Router } from '@angular/router'
import { RouterTestingModule } from '@angular/router/testing'
import { NgbModal, NgbModalModule, NgbModule } from '@ng-bootstrap/ng-bootstrap'
-import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { provideUiTour } from 'ngx-ui-tour-ng-bootstrap'
import { of, throwError } from 'rxjs'
import { routes } from 'src/app/app-routing.module'
@@ -108,7 +107,6 @@ describe('AppFrameComponent', () => {
ReactiveFormsModule,
DragDropModule,
NgbModalModule,
- NgxBootstrapIconsModule.pick(allIcons),
AppFrameComponent,
IfPermissionsDirective,
GlobalSearchComponent,
diff --git a/src-ui/src/app/components/app-frame/app-frame.component.ts b/src-ui/src/app/components/app-frame/app-frame.component.ts
index 4f9a02f6ec..54caff0582 100644
--- a/src-ui/src/app/components/app-frame/app-frame.component.ts
+++ b/src-ui/src/app/components/app-frame/app-frame.component.ts
@@ -23,10 +23,10 @@ import {
NgbNavModule,
NgbPopoverModule,
} from '@ng-bootstrap/ng-bootstrap'
-import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { TourNgBootstrap } from 'ngx-ui-tour-ng-bootstrap'
import { Observable } from 'rxjs'
import { first } from 'rxjs/operators'
+import { BootstrapIconComponent } from 'src/app/components/common/bootstrap-icon/bootstrap-icon.component'
import { Document } from 'src/app/data/document'
import { SavedView } from 'src/app/data/saved-view'
import {
@@ -89,7 +89,7 @@ const SCROLL_THRESHOLD = 16
NgbPopoverModule,
NgbCollapseModule,
NgbNavModule,
- NgxBootstrapIconsModule,
+ BootstrapIconComponent,
DragDropModule,
TourNgBootstrap,
FormsModule,
diff --git a/src-ui/src/app/components/app-frame/global-search/global-search.component.html b/src-ui/src/app/components/app-frame/global-search/global-search.component.html
index e2748709e0..8b8a4b7f42 100644
--- a/src-ui/src/app/components/app-frame/global-search/global-search.component.html
+++ b/src-ui/src/app/components/app-frame/global-search/global-search.component.html
@@ -1,7 +1,7 @@