Compare commits

..
6 Commits
Author SHA1 Message Date
shamoon d48663e9eb Bump version to 3.1.3 2026-09-03 18:59:18 -07:00
github-actions[bot]andCrowdin Bot a28a6fe23b New Crowdin translations by GitHub Action (#13894)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2026-09-03 18:58:02 -07:00
Trenton H e75a9d8c55 Chore: Drops the LSIO option from bug report install types (#13961) 2026-09-03 14:32:40 -07:00
dependabot[bot] 93ec102156 Chore(deps): Bump the uv group across 1 directory with 2 updates (#13958)
Bumps the uv group with 2 updates in the / directory: [banks](https://github.com/masci/banks) and [tornado](https://github.com/tornadoweb/tornado).


Updates `banks` from 2.4.2 to 2.4.5
- [Release notes](https://github.com/masci/banks/releases)
- [Commits](https://github.com/masci/banks/compare/v2.4.2...v2.4.5)

Updates `tornado` from 6.5.7 to 6.5.8
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.5.7...v6.5.8)

---
updated-dependencies:
- dependency-name: banks
  dependency-version: 2.4.5
  dependency-type: indirect
  dependency-group: uv
- dependency-name: tornado
  dependency-version: 6.5.8
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-03 16:54:47 +00:00
dependabot[bot] 1806141983 docker-compose(deps): bump nginx in /docker/compose (#13909)
Bumps nginx from 1.31.3-alpine to 1.31.5-alpine.

---
updated-dependencies:
- dependency-name: nginx
  dependency-version: 1.31.4-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-03 16:07:06 +00:00
dependabot[bot] 593a65c157 docker-compose(deps): Bump greenmail/standalone in /docker/compose (#13907)
Bumps greenmail/standalone from 2.1.11 to 2.1.13.

---
updated-dependencies:
- dependency-name: greenmail/standalone
  dependency-version: 2.1.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-03 08:53:52 -07:00
118 changed files with 26541 additions and 26863 deletions
-1
View File
@@ -38,7 +38,6 @@ body:
label: Installation method
options:
- Docker - official image
- Docker - linuxserver.io image
- Bare metal
- Other (please describe above)
- type: textarea
-2
View File
@@ -87,10 +87,8 @@ body:
label: Installation method
options:
- Docker - official image
- Docker - linuxserver.io image
- Bare metal
- Other (please describe above)
description: Note there are significant differences from the official image and linuxserver.io, please check if your issue is specific to the third-party image.
validations:
required: true
- type: textarea
+2 -2
View File
@@ -24,7 +24,7 @@ services:
network_mode: host
restart: unless-stopped
greenmail:
image: docker.io/greenmail/standalone:2.1.11
image: docker.io/greenmail/standalone:2.1.13
hostname: greenmail
container_name: greenmail
environment:
@@ -35,7 +35,7 @@ services:
- "3143:3143" # IMAP
restart: unless-stopped
nginx:
image: docker.io/nginx:1.31.3-alpine
image: docker.io/nginx:1.31.5-alpine
hostname: nginx
container_name: nginx
ports:
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "paperless-ngx"
version = "3.1.2"
version = "3.1.3"
description = "A community-supported supercharged document management system: scan, index and archive all your physical documents"
readme = "README.md"
requires-python = ">=3.11"
-11
View File
@@ -48,7 +48,6 @@ def seed_database() -> None:
from django.utils import timezone
from documents.models import Correspondent
from documents.models import CustomField
from documents.models import Document
from documents.models import DocumentType
from documents.models import Note
@@ -82,16 +81,6 @@ def seed_database() -> None:
path="e2e/{created_year}/{title}",
owner=admin,
)
CustomField.objects.create(
name="Test Select Field",
data_type=CustomField.FieldDataType.SELECT,
extra_data={
"select_options": [
{"id": "abc123", "label": "Alpha"},
{"id": "def456", "label": "Beta"},
],
},
)
today = timezone.localdate()
documents = []
@@ -207,41 +207,3 @@ test('bulk edit', async ({ page }) => {
await page.getByRole('button', { name: 'Confirm' }).click()
await bulkEditPromise
})
test('permissions dropdown stays open when selecting a user', async ({
page,
}) => {
await page.goto('/documents')
await page.getByRole('button', { name: 'Permissions' }).click()
const dropdown = page.locator(
'pngx-permissions-filter-dropdown .dropdown-menu'
)
await expect(dropdown).toBeVisible()
await dropdown.locator('ng-select').click()
await page.getByRole('option', { name: 'playwright' }).click()
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.ng-value-label')).toHaveText('playwright')
})
test('custom fields query dropdown stays open when building a query', async ({
page,
}) => {
await page.goto('/documents')
await page.getByRole('button', { name: 'Custom fields' }).click()
const dropdown = page.locator(
'pngx-custom-fields-query-dropdown .dropdown-menu'
)
await expect(dropdown).toBeVisible()
// field picker
await dropdown.locator('ng-select').first().click()
await page.getByRole('option', { name: 'Test Select Field' }).click()
await expect(dropdown).toBeVisible()
// value picker, shown once the operator takes a list of options
await dropdown.locator('select').first().selectOption({ label: 'In' })
await dropdown.locator('ng-select').last().click()
await page.getByRole('option', { name: 'Alpha' }).click()
await expect(dropdown).toBeVisible()
await expect(dropdown.locator('.ng-value-label').last()).toHaveText('Alpha')
})
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "paperless-ngx-ui",
"version": "3.1.2",
"version": "3.1.3",
"scripts": {
"preinstall": "npx only-allow pnpm",
"ng": "ng",
@@ -24,7 +24,7 @@
"@angular/platform-browser": "~22.1.3",
"@angular/router": "~22.1.3",
"@ng-bootstrap/ng-bootstrap": "^21.0.0",
"@ng-select/ng-select": "~24.0.2",
"@ng-select/ng-select": "~23.6.0",
"@ngneat/dirty-check-forms": "^3.0.3",
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.8",
+5 -7
View File
@@ -36,8 +36,8 @@ importers:
specifier: ^21.0.0
version: 21.0.0(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/forms@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/localize@22.1.3(@angular/compiler-cli@22.1.3(@angular/compiler@22.1.3)(typescript@6.0.3))(@angular/compiler@22.1.3))(@popperjs/core@2.11.8)(rxjs@7.8.2)
'@ng-select/ng-select':
specifier: ~24.0.2
version: 24.0.2(@angular/cdk@22.1.4(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/forms@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))
specifier: ~23.6.0
version: 23.6.0(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/forms@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))
'@ngneat/dirty-check-forms':
specifier: ^3.0.3
version: 3.0.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/forms@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/router@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))(lodash-es@4.18.1)(rxjs@7.8.2)
@@ -1490,11 +1490,10 @@ packages:
'@popperjs/core': ^2.11.8
rxjs: ^6.5.3 || ^7.4.0
'@ng-select/ng-select@24.0.2':
resolution: {integrity: sha512-EcOQanLp5dNxkDOxK75z7+B3gZW8LvQofzwL5AgWUn04EkJOXRI7Wi6Ylp7+jIAi9yPsTwjznrRd+wSl9EZGAQ==}
'@ng-select/ng-select@23.6.0':
resolution: {integrity: sha512-0I84OZ9gncphNR26zuqOwpB/XWhPav+IP+EfJd9lDNeu3UT9Y0JhTBburCXEXcbltwQkiN6bMCKdRF93hrFHxw==}
engines: {node: ^22.12.0 || ^24.0.0 || ^26.0.0}
peerDependencies:
'@angular/cdk': ^22.0.0
'@angular/common': ^22.0.0
'@angular/core': ^22.0.0
'@angular/forms': ^22.0.0
@@ -5770,9 +5769,8 @@ snapshots:
rxjs: 7.8.2
tslib: 2.8.1
'@ng-select/ng-select@24.0.2(@angular/cdk@22.1.4(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/forms@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))':
'@ng-select/ng-select@23.6.0(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/forms@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2))':
dependencies:
'@angular/cdk': 22.1.4(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2)
'@angular/common': 22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2)
'@angular/core': 22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)
'@angular/forms': 22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(@angular/platform-browser@22.1.3(@angular/common@22.1.3(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.1.3(@angular/compiler@22.1.3)(rxjs@7.8.2)))(rxjs@7.8.2)
@@ -6,7 +6,7 @@
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge>
}
</button>
<div [id]="dropdownMenuId" class="px-3 shadow" ngbDropdownMenu attr.aria-labelledby="dropdown_{{name}}">
<div class="px-3 shadow" ngbDropdownMenu attr.aria-labelledby="dropdown_{{name}}">
<ng-container *ngTemplateOutlet="list; context: { queries: selectionModel.queries }"></ng-container>
</div>
</div>
@@ -64,11 +64,10 @@
[disabled]="disabled"
[virtualScroll]="getSelectOptionsForField(atom.field)?.length > 100"
[searchFn]="selectOptionSearchFn"
[appendTo]="selectAppendTo"
(mousedown)="$event.stopImmediatePropagation()"
></ng-select>
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.DocumentLink) {
<pngx-input-document-link [(ngModel)]="atom.value" class="w-25 form-select doc-link-select p-0" placeholder="Search docs..." i18n-placeholder [minimal]="true" [appendTo]="selectAppendTo"></pngx-input-document-link>
<pngx-input-document-link [(ngModel)]="atom.value" class="w-25 form-select doc-link-select p-0" placeholder="Search docs..." i18n-placeholder [minimal]="true"></pngx-input-document-link>
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Monetary) {
<input class="w-25 form-control rounded-end" type="text" inputmode="decimal"
[ngModel]="atom.value"
@@ -89,7 +88,6 @@
bindLabel="name"
bindValue="id"
[searchFn]="customFieldSearchFn"
[appendTo]="selectAppendTo"
(mousedown)="$event.stopImmediatePropagation()"
></ng-select>
<select class="w-25 form-select" [(ngModel)]="atom.operator" [disabled]="disabled">
@@ -123,7 +121,7 @@
<ng-container *ngTemplateOutlet="comparisonValueTemplate; context: { atom: atom }"></ng-container>
}
@case (CustomFieldQueryOperator.Contains) {
<pngx-input-document-link [(ngModel)]="atom.value" class="w-25 form-select doc-link-select p-0" placeholder="Search docs..." i18n-placeholder [minimal]="true" [appendTo]="selectAppendTo"></pngx-input-document-link>
<pngx-input-document-link [(ngModel)]="atom.value" class="w-25 form-select doc-link-select p-0" placeholder="Search docs..." i18n-placeholder [minimal]="true"></pngx-input-document-link>
}
@case (CustomFieldQueryOperator.In) {
<ng-select
@@ -135,7 +133,6 @@
[disabled]="disabled"
[multiple]="true"
[searchFn]="selectOptionSearchFn"
[appendTo]="selectAppendTo"
(mousedown)="$event.stopImmediatePropagation()"
></ng-select>
}
@@ -1,4 +1,3 @@
import { _IdGenerator } from '@angular/cdk/a11y'
import {
getLocaleNumberSymbol,
NgClass,
@@ -251,18 +250,6 @@ export class CustomFieldsQueryDropdownComponent extends LoadingComponentWithPerm
@Input()
useDropdown: boolean = true
private readonly idGenerator = inject(_IdGenerator)
public readonly dropdownMenuId = this.idGenerator.getId(
'pngx-custom-fields-query-dropdown-'
)
/**
* Keep ng-select dropdown panels inside the dropdown menu
*/
get selectAppendTo(): string {
return this.useDropdown ? `#${this.dropdownMenuId}` : null
}
get name(): string {
return this.title ? this.title.replace(/\s/g, '_').toLowerCase() : null
}
@@ -3,7 +3,7 @@
<i-bs width="1em" height="1em" name="calendar-event-fill"></i-bs><div class="d-none d-sm-inline ms-1">{{title}}</div>
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
</button>
<div [id]="dropdownMenuId" class="dropdown-menu date-dropdown shadow p-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
<div class="dropdown-menu date-dropdown shadow p-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
<h6 class="dropdown-header border-bottom" i18n>Created</h6>
<div class="list-group list-group-flush">
<div class="list-group-item d-flex p-2 select-item" role="menuitem">
@@ -21,7 +21,6 @@
bindValue="id"
bindLabel="name"
clearable="false"
[appendTo]="'#' + dropdownMenuId"
placeholder="Relative dates"
i18n-placeholder
(change)="onSetCreatedRelativeDate($event)">
@@ -98,7 +97,6 @@
bindValue="id"
bindLabel="name"
clearable="false"
[appendTo]="'#' + dropdownMenuId"
placeholder="Relative dates"
i18n-placeholder
(change)="onSetAddedRelativeDate($event)">
@@ -23,7 +23,6 @@ import { SettingsService } from 'src/app/services/settings.service'
import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter'
import { pngxPopperOptions } from 'src/app/utils/popper-options'
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
import { _IdGenerator } from '@angular/cdk/a11y'
export interface DateSelection {
createdTo?: string
@@ -69,10 +68,6 @@ export enum RelativeDate {
})
export class DatesDropdownComponent implements OnInit, OnDestroy {
public popperOptions = pngxPopperOptions
private readonly idGenerator = inject(_IdGenerator)
public readonly dropdownMenuId = this.idGenerator.getId(
'pngx-dates-dropdown-'
)
constructor() {
const settings = inject(SettingsService)
@@ -33,7 +33,6 @@
[compareWith]="compareDocuments"
[trackByFn]="trackByFn"
[minTermLength]="2"
[appendTo]="appendTo"
[loading]="loading()"
[typeahead]="documentsInput$"
(mousedown)="$event.stopImmediatePropagation()"
@@ -81,12 +81,6 @@ export class DocumentLinkComponent
@Input()
placeholder: string = $localize`Search for documents`
/**
* Parent for ng-select dropdown, needed to prevent close on click.
*/
@Input()
appendTo: string = null
get selectedDocumentIDs(): number[] {
return this.selectedDocuments.map((d) => d.id)
}
@@ -22,7 +22,7 @@
}
// Dropdown hierarchy reveal for ng-select options
::ng-deep .ng-dropdown-panel .ng-option {
:host ::ng-deep .ng-dropdown-panel .ng-option {
overflow-x: auto !important;
.tag-option-row {
@@ -41,12 +41,12 @@
}
}
::ng-deep .ng-dropdown-panel .ng-option:hover .hierarchy-reveal,
::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked .hierarchy-reveal {
:host ::ng-deep .ng-dropdown-panel .ng-option:hover .hierarchy-reveal,
:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked .hierarchy-reveal {
max-width: 1000px;
}
::ng-deep .ng-dropdown-panel .ng-option:hover .hierarchy-indicator,
::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked .hierarchy-indicator {
:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked .hierarchy-indicator {
background: transparent;
}
@@ -3,7 +3,7 @@
<i-bs name="person-fill-lock"></i-bs><div class="d-none d-sm-inline ms-1">{{title}}</div>
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
</button>
<div [id]="dropdownMenuId" class="dropdown-menu permission-filter-dropdown shadow py-0 w-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
<div class="dropdown-menu permission-filter-dropdown shadow py-0 w-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
<div class="list-group list-group-flush">
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.NONE)" [disabled]="disabled">
<div class="selected-icon me-1">
@@ -58,10 +58,7 @@
<button *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.User }" class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" [disabled]="disabled">
<div class="selected-icon me-1">
@if (selectionModel.ownerFilter() === OwnerFilterType.OTHERS) {
<a class="text-reset focus-variants" href="javascript:void(0)" (click)="clearIncludeUsers()" aria-label="Clear selected users" i18n-aria-label>
<i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
<i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
</a>
<i-bs width="1em" height="1em" name="check"></i-bs>
}
</div>
<div class="me-1 w-100">
@@ -72,7 +69,6 @@
(ngModelChange)="selectionModel.includeUsers.set($event)"
[disabled]="disabled"
[clearable]="false"
[appendTo]="'#' + dropdownMenuId"
[items]="users()"
bindLabel="username"
multiple="true"
@@ -6,18 +6,3 @@
min-width: 1em;
min-height: 1em;
}
.focus-variants {
.variant-focused {
display: none;
}
&:hover, &:focus {
.variant-unfocused {
display: none;
}
.variant-focused {
display: block;
}
}
}
@@ -171,21 +171,6 @@ describe('PermissionsFilterDropdownComponent', () => {
expect(component.selectionModel.ownerFilter()).toEqual(OwnerFilterType.NONE)
})
it('should clear selected users', () => {
component.selectionModel.includeUsers.set([12])
component.onUserSelect()
component.selectionModel.hideUnowned.set(true)
expect(component.selectionModel.ownerFilter()).toEqual(
OwnerFilterType.OTHERS
)
component.clearIncludeUsers()
expect(component.selectionModel.includeUsers()).toEqual([])
expect(component.selectionModel.ownerFilter()).toEqual(OwnerFilterType.NONE)
expect(component.selectionModel.hideUnowned()).toBeTruthy()
})
it('should emit a selection model depending on the type of owner filter set', () => {
const emitted = () => ({
excludeUsers: ownerFilterSetResult.excludeUsers(),
@@ -1,4 +1,3 @@
import { _IdGenerator } from '@angular/cdk/a11y'
import { NgClass } from '@angular/common'
import {
Component,
@@ -71,11 +70,6 @@ export class PermissionsFilterDropdownComponent extends ComponentWithPermissions
public OwnerFilterType = OwnerFilterType
private readonly idGenerator = inject(_IdGenerator)
public readonly dropdownMenuId = this.idGenerator.getId(
'pngx-permissions-filter-dropdown-'
)
@Input()
title: string
@@ -211,11 +205,6 @@ export class PermissionsFilterDropdownComponent extends ComponentWithPermissions
this.ownerFilterSet.emit(this.selectionModel)
}
clearIncludeUsers() {
this.selectionModel.includeUsers.set([])
this.onUserSelect()
}
onUserSelect() {
this.selectionModel.ownerFilter.set(
this.selectionModel.includeUsers()?.length
+1 -1
View File
@@ -8,7 +8,7 @@ export const environment = {
apiVersion: '10', // match src/paperless/settings.py
appTitle: DEFAULT_APP_TITLE,
tag: 'prod',
version: '3.1.2',
version: '3.1.3',
webSocketHost: window.location.host,
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
webSocketBaseUrl: base_url.pathname + 'ws/',
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+11 -16
View File
@@ -374,6 +374,17 @@ th[pngxSortable] {
}
}
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {
background-color: var(--pngx-bg-darker) !important;
color: var(--pngx-body-color-accent) !important;
}
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected,
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected.ng-option-marked {
font-weight: bold;
background-color: var(--pngx-bg-alt2) !important;
}
&.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder,
.ng-select-container .ng-value-container .ng-placeholder {
top: 7px;
@@ -391,22 +402,6 @@ th[pngxSortable] {
}
}
// ng-select renders the dropdown panel in a CDK overlay outside the component
.ng-dropdown-panel {
font-size: var(--pngx-body-font-size);
.ng-dropdown-panel-items .ng-option.ng-option-marked {
background-color: var(--pngx-bg-darker) !important;
color: var(--pngx-body-color-accent) !important;
}
.ng-dropdown-panel-items .ng-option.ng-option-selected,
.ng-dropdown-panel-items .ng-option.ng-option-selected.ng-option-marked {
font-weight: bold;
background-color: var(--pngx-bg-alt2) !important;
}
}
.paperless-input-tags {
.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value {
background-color: transparent;
+2 -2
View File
@@ -237,8 +237,8 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,%3csvg xmlns='h
mix-blend-mode: luminosity;
}
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option:not(.ng-option-selected):hover,
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {
.paperless-input-select .ng-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option:not(.ng-option-selected):hover,
.paperless-input-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {
background-color: var(--bs-light) !important;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More