Compare commits

...

15 Commits

Author SHA1 Message Date
shamoon
6c230f098a Bump version to 2.13.5 2024-11-10 08:25:10 -08:00
shamoon
da40d03be6 Merge branch 'dev' 2024-11-10 08:24:31 -08:00
shamoon
a6f4c75a72 Fix: handle page count exception for pw-protected files (#8240) 2024-11-10 03:33:47 -08:00
shamoon
c22a80abd3 Fix: correctly track task id in list for change detection (#8230) 2024-11-08 00:19:05 -08:00
Trenton H
2806b1820e Updates all runner images to use Ubuntu Noble (#8213) 2024-11-08 02:14:47 +00:00
Trenton H
177cc9d985 Fixes admin pages to show trashed documents too (#8068) 2024-11-07 23:04:29 +00:00
shamoon
da85b05ea4 Fix: tag colors stay fixed in list when selected (#8225) 2024-11-07 11:59:03 -08:00
shamoon
82fd706dca Fix: another Firefox plaintext popup fix 2024-11-06 08:58:15 -08:00
shamoon
2f06680f76 Fix: fix re-activation of save button when adding / removing array items (#8208) 2024-11-05 20:01:36 -08:00
shamoon
64095a710a Fix: Dont check empty ASNs 2024-11-05 20:01:36 -08:00
shamoon
005150c84f Fix: fix thumbnail clipping, select inverted color in safari (#8193) 2024-11-04 13:44:35 -08:00
shamoon
c57cd7e298 Fix: select checkbox should remain visible (#8185) 2024-11-04 04:32:57 -08:00
shamoon
ef329fc687 Fix: warn with proper error on ASN exists in trash (#8176) 2024-11-03 17:52:59 -08:00
dependabot[bot]
695967cbb2 Chore(deps): Bump stumpylog/image-cleaner-action in the actions group (#8142)
Bumps the actions group with 1 update: [stumpylog/image-cleaner-action](https://github.com/stumpylog/image-cleaner-action).


Updates `stumpylog/image-cleaner-action` from 0.8.0 to 0.9.0
- [Release notes](https://github.com/stumpylog/image-cleaner-action/releases)
- [Changelog](https://github.com/stumpylog/image-cleaner-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stumpylog/image-cleaner-action/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: stumpylog/image-cleaner-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-03 15:33:12 +00:00
github-actions[bot]
c028910cdd Changelog v2.13.4 - GHA (#8170)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-03 06:27:10 -08:00
20 changed files with 145 additions and 33 deletions

View File

@@ -30,7 +30,7 @@ jobs:
github.repository
name: Linting Checks
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
-
name: Checkout repository
@@ -46,7 +46,7 @@ jobs:
documentation:
name: "Build & Deploy Documentation"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- pre-commit
steps:
@@ -95,7 +95,7 @@ jobs:
tests-backend:
name: "Backend Tests (Python ${{ matrix.python-version }})"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- pre-commit
strategy:
@@ -170,7 +170,7 @@ jobs:
install-frontend-depedendencies:
name: "Install Frontend Dependencies"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- pre-commit
steps:
@@ -201,7 +201,7 @@ jobs:
tests-frontend:
name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- install-frontend-depedendencies
strategy:
@@ -261,7 +261,7 @@ jobs:
tests-coverage-upload:
name: "Upload to Codecov"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- tests-backend
- tests-frontend
@@ -333,7 +333,7 @@ jobs:
build-docker-image:
name: Build Docker image for ${{ github.ref_name }}
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || startsWith(github.ref, 'refs/heads/fix-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v'))
concurrency:
group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }}
@@ -461,7 +461,7 @@ jobs:
needs:
- build-docker-image
- documentation
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
-
name: Checkout
@@ -569,7 +569,7 @@ jobs:
publish-release:
name: "Publish Release"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
outputs:
prerelease: ${{ steps.get_version.outputs.prerelease }}
changelog: ${{ steps.create-release.outputs.body }}
@@ -619,7 +619,7 @@ jobs:
append-changelog:
name: "Append Changelog"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- publish-release
if: needs.publish-release.outputs.prerelease == 'false'

View File

@@ -21,7 +21,7 @@ jobs:
cleanup-images:
name: Cleanup Image Tags for ${{ matrix.primary-name }}
if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
@@ -33,7 +33,7 @@ jobs:
-
name: Clean temporary images
if: "${{ env.TOKEN != '' }}"
uses: stumpylog/image-cleaner-action/ephemeral@v0.8.0
uses: stumpylog/image-cleaner-action/ephemeral@v0.9.0
with:
token: "${{ env.TOKEN }}"
owner: "${{ github.repository_owner }}"
@@ -47,7 +47,7 @@ jobs:
cleanup-untagged-images:
name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }}
if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs:
- cleanup-images
strategy:
@@ -61,7 +61,7 @@ jobs:
-
name: Clean untagged images
if: "${{ env.TOKEN != '' }}"
uses: stumpylog/image-cleaner-action/untagged@v0.8.0
uses: stumpylog/image-cleaner-action/untagged@v0.9.0
with:
token: "${{ env.TOKEN }}"
owner: "${{ github.repository_owner }}"

View File

@@ -23,7 +23,7 @@ on:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read

View File

@@ -16,7 +16,7 @@ jobs:
synchronize-with-crowdin:
name: Crowdin Sync
if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Checkout

View File

@@ -15,7 +15,7 @@ permissions:
jobs:
pr_opened_or_reopened:
name: pr_opened_or_reopened
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
permissions:
# write permission is required for autolabeler
pull-requests: write

View File

@@ -17,7 +17,7 @@ jobs:
stale:
name: 'Stale'
if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/stale@v9
with:
@@ -33,7 +33,7 @@ jobs:
lock-threads:
name: 'Lock Old Threads'
if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: dessant/lock-threads@v5
with:
@@ -59,7 +59,7 @@ jobs:
close-answered-discussions:
name: 'Close Answered Discussions'
if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/github-script@v7
with:
@@ -116,7 +116,7 @@ jobs:
close-outdated-discussions:
name: 'Close Outdated Discussions'
if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/github-script@v7
with:
@@ -208,7 +208,7 @@ jobs:
close-unsupported-feature-requests:
name: 'Close Unsupported Feature Requests'
if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/github-script@v7
with:

View File

@@ -1,5 +1,21 @@
# Changelog
## paperless-ngx 2.13.4
### Bug Fixes
- Fix: fix dark mode icon blend mode in 2.13.3 [@shamoon](https://github.com/shamoon) ([#8166](https://github.com/paperless-ngx/paperless-ngx/pull/8166))
- Fix: fix clipped popup preview in 2.13.3 [@shamoon](https://github.com/shamoon) ([#8165](https://github.com/paperless-ngx/paperless-ngx/pull/8165))
### All App Changes
<details>
<summary>2 changes</summary>
- Fix: fix dark mode icon blend mode in 2.13.3 [@shamoon](https://github.com/shamoon) ([#8166](https://github.com/paperless-ngx/paperless-ngx/pull/8166))
- Fix: fix clipped popup preview in 2.13.3 [@shamoon](https://github.com/shamoon) ([#8165](https://github.com/paperless-ngx/paperless-ngx/pull/8165))
</details>
## paperless-ngx 2.13.3
### Bug Fixes

View File

@@ -43,7 +43,7 @@
</tr>
</thead>
<tbody>
@for (task of tasks | slice: (page-1) * pageSize : page * pageSize; track task) {
@for (task of tasks | slice: (page-1) * pageSize : page * pageSize; track task.id) {
<tr (click)="toggleSelected(task, $event); $event.stopPropagation();">
<td>
<div class="form-check">

View File

@@ -19,6 +19,7 @@
object:not(.pdf) {
mix-blend-mode: difference;
background: white !important;
&.p-2 {
padding: 0 !important;
}

View File

@@ -710,7 +710,10 @@ export class DocumentDetailComponent
next: (docValues) => {
// in case data changed while saving eg removing inbox_tags
this.documentForm.patchValue(docValues)
this.store.next(this.documentForm.value)
const newValues = Object.assign({}, this.documentForm.value)
newValues.tags = [...docValues.tags]
newValues.custom_fields = [...docValues.custom_fields]
this.store.next(newValues)
this.openDocumentService.setDirty(this.document, false)
this.openDocumentService.save()
this.toastService.showInfo($localize`Document saved successfully.`)

View File

@@ -1,6 +1,6 @@
<div class="col p-2 h-100">
<div class="card h-100 shadow-sm document-card" [class.card-selected]="selected" [class.popover-hidden]="popoverHidden" (mouseleave)="mouseLeaveCard()">
<div class="border-bottom doc-img-container" (click)="this.toggleSelected.emit($event)" (dblclick)="dblClickDocument.emit(this)">
<div class="border-bottom doc-img-container rounded-top" (click)="this.toggleSelected.emit($event)" (dblclick)="dblClickDocument.emit(this)">
<img class="card-img doc-img" [class.inverted]="getIsThumbInverted()" [src]="getThumbUrl()">
<div class="border-end border-bottom bg-light py-1 px-2 document-card-check">

View File

@@ -5,7 +5,7 @@ export const environment = {
apiBaseUrl: document.baseURI + 'api/',
apiVersion: '5',
appTitle: 'Paperless-ngx',
version: '2.13.4',
version: '2.13.5',
webSocketHost: window.location.host,
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
webSocketBaseUrl: base_url.pathname + 'ws/',

View File

@@ -501,7 +501,7 @@ ul.pagination {
border-color:var(--bs-primary);
.document-card-check {
display: block;
display: block !important;
}
.doc-img-container {

View File

@@ -204,7 +204,7 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt
@supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none) {
// Safari does not like the filters on the image, see https://github.com/paperless-ngx/paperless-ngx/pull/8121
.doc-img-container {
background-color: #ffffff;
background-color: #ffffff !important;
}
.doc-img {
@@ -252,7 +252,7 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt
}
.table-row-selected {
td, a {
td, a:not(.badge) {
color: var(--pngx-primary-text-contrast) !important;
}
}

View File

@@ -51,6 +51,7 @@ class DocumentAdmin(GuardedModelAdmin):
"archive_filename",
"archive_checksum",
"original_filename",
"deleted_at",
)
list_display_links = ("title",)
@@ -77,6 +78,12 @@ class DocumentAdmin(GuardedModelAdmin):
created_.short_description = "Created"
def get_queryset(self, request): # pragma: no cover
"""
Include trashed documents
"""
return Document.global_objects.all()
def delete_queryset(self, request, queryset):
from documents import index

View File

@@ -805,6 +805,24 @@ class DocumentSerializer(
doc["content"] = doc.get("content")[0:550]
return doc
def validate(self, attrs):
if (
"archive_serial_number" in attrs
and attrs["archive_serial_number"] is not None
and len(str(attrs["archive_serial_number"])) > 0
and Document.deleted_objects.filter(
archive_serial_number=attrs["archive_serial_number"],
).exists()
):
raise serializers.ValidationError(
{
"archive_serial_number": [
"Document with this Archive Serial Number already exists in the trash.",
],
},
)
return super().validate(attrs)
def update(self, instance: Document, validated_data):
if "created_date" in validated_data and "created" not in validated_data:
new_datetime = datetime.datetime.combine(

View File

@@ -2540,6 +2540,50 @@ class TestDocumentApi(DirectoriesMixin, DocumentConsumeDelayMixin, APITestCase):
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.content, b"1")
def test_asn_not_unique_with_trashed_doc(self):
"""
GIVEN:
- Existing document with ASN that is trashed
WHEN:
- API request to update document with same ASN
THEN:
- Explicit error is returned
"""
user1 = User.objects.create_superuser(username="test1")
self.client.force_authenticate(user1)
doc1 = Document.objects.create(
title="test",
mime_type="application/pdf",
content="this is a document 1",
checksum="1",
archive_serial_number=1,
)
doc1.delete()
doc2 = Document.objects.create(
title="test2",
mime_type="application/pdf",
content="this is a document 2",
checksum="2",
)
result = self.client.patch(
f"/api/documents/{doc2.pk}/",
{
"archive_serial_number": 1,
},
)
self.assertEqual(result.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
result.json(),
{
"archive_serial_number": [
"Document with this Archive Serial Number already exists in the trash.",
],
},
)
def test_remove_inbox_tags(self):
"""
GIVEN:

View File

@@ -1,6 +1,6 @@
from typing import Final
__version__: Final[tuple[int, int, int]] = (2, 13, 4)
__version__: Final[tuple[int, int, int]] = (2, 13, 5)
# Version string like X.Y.Z
__full_version_str__: Final[str] = ".".join(map(str, __version__))
# Version string like X.Y

View File

@@ -43,10 +43,15 @@ class RasterisedDocumentParser(DocumentParser):
def get_page_count(self, document_path, mime_type):
page_count = None
if mime_type == "application/pdf":
import pikepdf
try:
import pikepdf
with pikepdf.Pdf.open(document_path) as pdf:
page_count = len(pdf.pages)
with pikepdf.Pdf.open(document_path) as pdf:
page_count = len(pdf.pages)
except Exception as e:
self.log.warning(
f"Unable to determine PDF page count {document_path}: {e}",
)
return page_count
def extract_metadata(self, document_path, mime_type):

View File

@@ -81,6 +81,24 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
)
self.assertEqual(page_count, 6)
def test_get_page_count_password_protected(self):
"""
GIVEN:
- Password protected PDF file
WHEN:
- The number of pages is requested
THEN:
- The method returns None
"""
parser = RasterisedDocumentParser(uuid.uuid4())
with self.assertLogs("paperless.parsing.tesseract", level="WARNING") as cm:
page_count = parser.get_page_count(
os.path.join(self.SAMPLE_FILES, "password-protected.pdf"),
"application/pdf",
)
self.assertEqual(page_count, None)
self.assertIn("Unable to determine PDF page count", cm.output[0])
def test_thumbnail(self):
parser = RasterisedDocumentParser(uuid.uuid4())
thumb = parser.get_thumbnail(