mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
Compare commits
6 Commits
ab07b40fa5
...
18709f5fe8
Author | SHA1 | Date | |
---|---|---|---|
![]() |
18709f5fe8 | ||
![]() |
955ff32dcd | ||
![]() |
b746b6f2d6 | ||
![]() |
b4b0f802e1 | ||
![]() |
5f16d5f5f1 | ||
![]() |
8db04398c7 |
16
.codecov.yml
16
.codecov.yml
@ -1,18 +1,18 @@
|
||||
codecov:
|
||||
require_ci_to_pass: true
|
||||
# https://docs.codecov.com/docs/flags#recommended-automatic-flag-management
|
||||
# Require each flag to have 1 upload before notification
|
||||
flag_management:
|
||||
individual_flags:
|
||||
- name: backend
|
||||
# https://docs.codecov.com/docs/components
|
||||
component_management:
|
||||
individual_components:
|
||||
- component_id: backend
|
||||
paths:
|
||||
- src/
|
||||
- name: frontend
|
||||
- src/**
|
||||
- component_id: frontend
|
||||
paths:
|
||||
- src-ui/
|
||||
- src-ui/**
|
||||
# https://docs.codecov.com/docs/pull-request-comments
|
||||
# codecov will only comment if coverage changes
|
||||
comment:
|
||||
layout: "header, diff, components, flags, files"
|
||||
require_changes: true
|
||||
# https://docs.codecov.com/docs/javascript-bundle-analysis
|
||||
require_bundle_changes: true
|
||||
|
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
github: [shamoon, stumpylog]
|
132
.github/workflows/ci.yml
vendored
132
.github/workflows/ci.yml
vendored
@ -162,16 +162,20 @@ jobs:
|
||||
--frozen \
|
||||
pytest
|
||||
-
|
||||
name: Upload coverage
|
||||
if: ${{ matrix.python-version == env.DEFAULT_PYTHON_VERSION }}
|
||||
uses: actions/upload-artifact@v4
|
||||
name: Upload backend test results to Codecov
|
||||
if: always()
|
||||
uses: codecov/test-results-action@v1
|
||||
with:
|
||||
name: backend-coverage-report
|
||||
path: |
|
||||
coverage.xml
|
||||
junit.xml
|
||||
retention-days: 7
|
||||
if-no-files-found: error
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: backend-python-${{ matrix.python-version }}
|
||||
files: junit.xml
|
||||
-
|
||||
name: Upload backend coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: backend-python-${{ matrix.python-version }}
|
||||
files: coverage.xml
|
||||
-
|
||||
name: Stop containers
|
||||
if: always()
|
||||
@ -179,7 +183,7 @@ jobs:
|
||||
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml logs
|
||||
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml down
|
||||
|
||||
install-frontend-depedendencies:
|
||||
install-frontend-dependencies:
|
||||
name: "Install Frontend Dependencies"
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
@ -214,7 +218,7 @@ jobs:
|
||||
name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- install-frontend-depedendencies
|
||||
- install-frontend-dependencies
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@ -245,111 +249,33 @@ jobs:
|
||||
run: cd src-ui && npm run lint
|
||||
-
|
||||
name: Run Jest unit tests
|
||||
env:
|
||||
JEST_JUNIT_OUTPUT_FILE: junit-report-${{ matrix.shard-index }}.xml
|
||||
run: cd src-ui && npm run test -- --max-workers=2 --shard=${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
||||
-
|
||||
name: Upload Jest coverage
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: jest-coverage-report-${{ matrix.shard-index }}
|
||||
path: |
|
||||
src-ui/coverage/coverage-final.json
|
||||
src-ui/coverage/lcov.info
|
||||
src-ui/coverage/clover.xml
|
||||
retention-days: 7
|
||||
if-no-files-found: error
|
||||
-
|
||||
name: Run Playwright e2e tests
|
||||
run: cd src-ui && npx playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
||||
-
|
||||
name: Upload Playwright test results
|
||||
name: Upload frontend test results to Codecov
|
||||
uses: codecov/test-results-action@v1
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-report-${{ matrix.shard-index }}
|
||||
path: src-ui/playwright-report
|
||||
retention-days: 7
|
||||
-
|
||||
name: Upload frontend test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: junit-report-${{ matrix.shard-index }}
|
||||
path: src-ui/junit-report-${{ matrix.shard-index }}.xml
|
||||
retention-days: 7
|
||||
|
||||
tests-coverage-upload:
|
||||
name: "Upload to Codecov"
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- tests-backend
|
||||
- tests-frontend
|
||||
steps:
|
||||
-
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Download frontend jest coverage
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: src-ui/coverage/
|
||||
pattern: jest-coverage-report-*
|
||||
-
|
||||
name: Download frontend playwright coverage
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: src-ui/coverage/
|
||||
pattern: playwright-report-*
|
||||
merge-multiple: true
|
||||
-
|
||||
name: Download frontend test results
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: src-ui/junit/
|
||||
pattern: junit-report-*
|
||||
merge-multiple: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: frontend-node-${{ matrix.node-version }}
|
||||
directory: src-ui/
|
||||
-
|
||||
name: Upload frontend coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
# not required for public repos, but intermittently fails otherwise
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: frontend
|
||||
flags: frontend-node-${{ matrix.node-version }}
|
||||
directory: src-ui/coverage/
|
||||
# dont include backend coverage files here
|
||||
files: '!coverage.xml'
|
||||
-
|
||||
name: Upload frontend test results to Codecov
|
||||
if: ${{ !cancelled() }}
|
||||
uses: codecov/test-results-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: frontend
|
||||
directory: src-ui/junit/
|
||||
-
|
||||
name: Download backend coverage
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: backend-coverage-report
|
||||
path: src/
|
||||
-
|
||||
name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
# not required for public repos, but intermittently fails otherwise
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
# future expansion
|
||||
flags: backend
|
||||
directory: src/
|
||||
-
|
||||
name: Upload backend test results to Codecov
|
||||
if: ${{ !cancelled() }}
|
||||
uses: codecov/test-results-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: backend
|
||||
directory: src/
|
||||
|
||||
frontend-bundle-analysis:
|
||||
name: "Frontend Bundle Analysis"
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- tests-frontend
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
-
|
||||
name: Use Node.js 20
|
||||
uses: actions/setup-node@v4
|
||||
|
@ -36,7 +36,13 @@ export const routes: Routes = [
|
||||
component: AppFrameComponent,
|
||||
canDeactivate: [DirtyDocGuard],
|
||||
children: [
|
||||
{ path: 'dashboard', component: DashboardComponent },
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: DashboardComponent,
|
||||
data: {
|
||||
componentName: 'AppFrameComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'documents',
|
||||
component: DocumentListComponent,
|
||||
@ -47,6 +53,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.Document,
|
||||
},
|
||||
componentName: 'DocumentListComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -59,6 +66,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.SavedView,
|
||||
},
|
||||
componentName: 'DocumentListComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -70,6 +78,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.Document,
|
||||
},
|
||||
componentName: 'DocumentDetailComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -81,6 +90,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.Document,
|
||||
},
|
||||
componentName: 'DocumentDetailComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -92,6 +102,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.Document,
|
||||
},
|
||||
componentName: 'DocumentAsnComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -103,6 +114,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.Tag,
|
||||
},
|
||||
componentName: 'TagListComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -114,6 +126,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.DocumentType,
|
||||
},
|
||||
componentName: 'DocumentTypeListComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -125,6 +138,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.Correspondent,
|
||||
},
|
||||
componentName: 'CorrespondentListComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -136,6 +150,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.StoragePath,
|
||||
},
|
||||
componentName: 'StoragePathListComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -144,6 +159,7 @@ export const routes: Routes = [
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
requireAdmin: true,
|
||||
componentName: 'LogsComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -155,6 +171,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.Delete,
|
||||
type: PermissionType.Document,
|
||||
},
|
||||
componentName: 'TrashComponent',
|
||||
},
|
||||
},
|
||||
// redirect old paths
|
||||
@ -180,6 +197,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.Change,
|
||||
type: PermissionType.UISettings,
|
||||
},
|
||||
componentName: 'SettingsComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -192,6 +210,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.UISettings,
|
||||
},
|
||||
componentName: 'SettingsComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -203,6 +222,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.Change,
|
||||
type: PermissionType.AppConfig,
|
||||
},
|
||||
componentName: 'ConfigComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -214,6 +234,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.PaperlessTask,
|
||||
},
|
||||
componentName: 'TasksComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -225,6 +246,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.CustomField,
|
||||
},
|
||||
componentName: 'CustomFieldsComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -236,6 +258,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.Workflow,
|
||||
},
|
||||
componentName: 'WorkflowsComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -247,6 +270,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.MailAccount,
|
||||
},
|
||||
componentName: 'MailComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -258,6 +282,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.User,
|
||||
},
|
||||
componentName: 'UsersAndGroupsComponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -269,6 +294,7 @@ export const routes: Routes = [
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.SavedView,
|
||||
},
|
||||
componentName: 'SavedViewsComponent',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -29,7 +29,7 @@ describe('ComponentRouterService', () => {
|
||||
eventsSubject.next(
|
||||
new ActivationStart({
|
||||
url: 'test-url',
|
||||
component: { name: 'TestComponent' },
|
||||
data: { componentName: 'TestComponent' },
|
||||
} as any)
|
||||
)
|
||||
|
||||
@ -41,13 +41,13 @@ describe('ComponentRouterService', () => {
|
||||
eventsSubject.next(
|
||||
new ActivationStart({
|
||||
url: 'test-url-1',
|
||||
component: { name: 'TestComponent' },
|
||||
data: { componentName: 'TestComponent' },
|
||||
} as any)
|
||||
)
|
||||
eventsSubject.next(
|
||||
new ActivationStart({
|
||||
url: 'test-url-2',
|
||||
component: { name: 'TestComponent' },
|
||||
data: { componentName: 'TestComponent' },
|
||||
} as any)
|
||||
)
|
||||
|
||||
@ -59,13 +59,13 @@ describe('ComponentRouterService', () => {
|
||||
eventsSubject.next(
|
||||
new ActivationStart({
|
||||
url: 'test-url-1',
|
||||
component: { name: 'TestComponent1' },
|
||||
data: { componentName: 'TestComponent1' },
|
||||
} as any)
|
||||
)
|
||||
eventsSubject.next(
|
||||
new ActivationStart({
|
||||
url: 'test-url-2',
|
||||
component: { name: 'TestComponent2' },
|
||||
data: { componentName: 'TestComponent2' },
|
||||
} as any)
|
||||
)
|
||||
|
||||
@ -76,13 +76,13 @@ describe('ComponentRouterService', () => {
|
||||
eventsSubject.next(
|
||||
new ActivationStart({
|
||||
url: 'test-url-1',
|
||||
component: { name: 'TestComponent' },
|
||||
data: { componentName: 'TestComponent' },
|
||||
} as any)
|
||||
)
|
||||
eventsSubject.next(
|
||||
new ActivationStart({
|
||||
url: 'test-url-2',
|
||||
component: { name: 'TestComponent' },
|
||||
data: { componentName: 'TestComponent' },
|
||||
} as any)
|
||||
)
|
||||
|
||||
@ -93,7 +93,7 @@ describe('ComponentRouterService', () => {
|
||||
eventsSubject.next(
|
||||
new ActivationStart({
|
||||
url: 'test-url',
|
||||
component: { name: 'TestComponent' },
|
||||
data: { componentName: 'TestComponent' },
|
||||
} as any)
|
||||
)
|
||||
|
||||
|
@ -17,11 +17,11 @@ export class ComponentRouterService {
|
||||
.subscribe((event: ActivationStart) => {
|
||||
if (
|
||||
this.componentHistory[this.componentHistory.length - 1] !==
|
||||
event.snapshot.component.name &&
|
||||
!EXCLUDE_COMPONENTS.includes(event.snapshot.component.name)
|
||||
event.snapshot.data.componentName &&
|
||||
!EXCLUDE_COMPONENTS.includes(event.snapshot.data.componentName)
|
||||
) {
|
||||
this.history.push(event.snapshot.url.toString())
|
||||
this.componentHistory.push(event.snapshot.component.name)
|
||||
this.componentHistory.push(event.snapshot.data.componentName)
|
||||
} else {
|
||||
// Update the URL of the current component in case the same component was loaded via a different URL
|
||||
this.history[this.history.length - 1] = event.snapshot.url.toString()
|
||||
|
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
11036
src-ui/src/locale/messages.et_EE.xlf
Normal file
11036
src-ui/src/locale/messages.et_EE.xlf
Normal file
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
2021
src/locale/et_EE/LC_MESSAGES/django.po
Normal file
2021
src/locale/et_EE/LC_MESSAGES/django.po
Normal file
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
@ -32,6 +32,7 @@ from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from documents.index import DelayedQuery
|
||||
from documents.permissions import PaperlessObjectPermissions
|
||||
from paperless.filters import GroupFilterSet
|
||||
from paperless.filters import UserFilterSet
|
||||
@ -66,17 +67,17 @@ class StandardPagination(PageNumberPagination):
|
||||
)
|
||||
|
||||
def get_all_result_ids(self):
|
||||
ids = []
|
||||
if hasattr(self.page.paginator.object_list, "saved_results"):
|
||||
results_page = self.page.paginator.object_list.saved_results[0]
|
||||
if results_page is not None:
|
||||
for i in range(len(results_page.results.docs())):
|
||||
try:
|
||||
fields = results_page.results.fields(i)
|
||||
if "id" in fields:
|
||||
ids.append(fields["id"])
|
||||
except Exception:
|
||||
pass
|
||||
query = self.page.paginator.object_list
|
||||
if isinstance(query, DelayedQuery):
|
||||
try:
|
||||
ids = [
|
||||
query.searcher.ixreader.stored_fields(
|
||||
doc_num,
|
||||
)["id"]
|
||||
for doc_num in query.saved_results.get(0).results.docs()
|
||||
]
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
ids = self.page.paginator.object_list.values_list("pk", flat=True)
|
||||
return ids
|
||||
|
Loading…
x
Reference in New Issue
Block a user