diff --git a/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.html b/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.html index 62a680964..2ac67b6d9 100644 --- a/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.html +++ b/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.html @@ -13,10 +13,10 @@ - - + + - + diff --git a/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.spec.ts b/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.spec.ts index 362d99e0a..085ece5c8 100644 --- a/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.spec.ts +++ b/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.spec.ts @@ -123,6 +123,16 @@ describe('ShareLinkBundleListComponent', () => { expect(service.list).toHaveBeenLastCalledWith(2, 25, 'created', true) }) + it('sorts bundles and returns to the first page', () => { + fixture.detectChanges() + component.page.set(2) + + component.onSort({ column: 'status', reverse: false }) + + expect(component.page()).toBe(1) + expect(service.list).toHaveBeenLastCalledWith(1, 25, 'status', false) + }) + it('marks expired share link bundles', () => { service.list.mockReturnValue( of({ diff --git a/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.ts b/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.ts index a8dc8ed4d..00d04a77e 100644 --- a/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.ts +++ b/src-ui/src/app/components/manage/share-links/share-link-bundle-list/share-link-bundle-list.component.ts @@ -16,6 +16,10 @@ import { ShareLinkBundleSummary, } from 'src/app/data/share-link-bundle' import { SETTINGS_KEYS } from 'src/app/data/ui-settings' +import { + SortEvent, + SortableDirective, +} from 'src/app/directives/sortable.directive' import { FileSizePipe } from 'src/app/pipes/file-size.pipe' import { ShareLinkBundleService } from 'src/app/services/rest/share-link-bundle.service' import { SettingsService } from 'src/app/services/settings.service' @@ -35,6 +39,7 @@ import { LoadingComponentWithPermissions } from 'src/app/components/loading-comp NgbPaginationModule, NgbPopoverModule, NgxBootstrapIconsModule, + SortableDirective, FileSizePipe, ], }) @@ -52,6 +57,8 @@ export class ShareLinkBundleListComponent readonly copiedSlug = signal(null) readonly total = signal(0) readonly page = signal(1) + readonly sortField = signal('created') + readonly sortReverse = signal(true) readonly statuses = ShareLinkBundleStatus readonly fileVersions = FileVersion @@ -90,7 +97,12 @@ export class ShareLinkBundleListComponent } this.error.set(null) return this.shareLinkBundleService - .list(this.page(), this.pageSize, 'created', true) + .list( + this.page(), + this.pageSize, + this.sortField(), + this.sortReverse() + ) .pipe( catchError((error) => { if (!silent) { @@ -138,6 +150,13 @@ export class ShareLinkBundleListComponent this.triggerRefresh(false) } + onSort(event: SortEvent): void { + this.sortField.set(event.column || 'created') + this.sortReverse.set(event.column ? event.reverse : true) + this.page.set(1) + this.triggerRefresh(false) + } + copy(bundle: ShareLinkBundleSummary): void { if (bundle.status !== ShareLinkBundleStatus.Ready) { return diff --git a/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.html b/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.html index 25c90f64c..710db7dc3 100644 --- a/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.html +++ b/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.html @@ -12,9 +12,9 @@
CreatedStatusCreatedStatus SizeExpiresExpires Documents File version Actions
- - - + + + diff --git a/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.spec.ts b/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.spec.ts index 43a6f7cc0..1946b7e78 100644 --- a/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.spec.ts +++ b/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.spec.ts @@ -75,6 +75,16 @@ describe('ShareLinkListComponent', () => { expect(service.list).toHaveBeenLastCalledWith(2, 25, 'created', true) }) + it('sorts links and returns to the first page', () => { + fixture.detectChanges() + component.page.set(2) + + component.onSort({ column: 'expiration', reverse: false }) + + expect(component.page()).toBe(1) + expect(service.list).toHaveBeenLastCalledWith(1, 25, 'expiration', false) + }) + it('marks expired share links', () => { service.list.mockReturnValue( of({ diff --git a/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.ts b/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.ts index 8c4239256..6f30366f4 100644 --- a/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.ts +++ b/src-ui/src/app/components/manage/share-links/share-link-list/share-link-list.component.ts @@ -12,6 +12,10 @@ import { FileVersion, ShareLink } from 'src/app/data/share-link' import { SHARE_LINK_BUNDLE_FILE_VERSION_LABELS } from 'src/app/data/share-link-bundle' import { SETTINGS_KEYS } from 'src/app/data/ui-settings' import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive' +import { + SortEvent, + SortableDirective, +} from 'src/app/directives/sortable.directive' import { DocumentTitlePipe } from 'src/app/pipes/document-title.pipe' import { PermissionAction, @@ -34,6 +38,7 @@ import { environment } from 'src/environments/environment' NgbPaginationModule, NgxBootstrapIconsModule, RouterModule, + SortableDirective, ], }) export class ShareLinkListComponent @@ -48,6 +53,8 @@ export class ShareLinkListComponent readonly links = signal([]) readonly total = signal(0) readonly page = signal(1) + readonly sortField = signal('created') + readonly sortReverse = signal(true) readonly copiedID = signal(null) readonly copiedDocumentID = signal(null) readonly error = signal(null) @@ -85,7 +92,7 @@ export class ShareLinkListComponent this.loading.set(true) this.error.set(null) this.shareLinkService - .list(this.page(), this.pageSize, 'created', true) + .list(this.page(), this.pageSize, this.sortField(), this.sortReverse()) .pipe(takeUntil(this.unsubscribeNotifier)) .subscribe({ next: (results) => { @@ -109,6 +116,13 @@ export class ShareLinkListComponent this.reload() } + onSort(event: SortEvent): void { + this.sortField.set(event.column || 'created') + this.sortReverse.set(event.column ? event.reverse : true) + this.page.set(1) + this.reload() + } + getShareUrl(link: ShareLink): string { const apiURL = new URL(environment.apiBaseUrl) return `${apiURL.origin}${apiURL.pathname.replace(/\/api\/$/, '/share/')}${ diff --git a/src/documents/tests/test_api_documents.py b/src/documents/tests/test_api_documents.py index 30ddb4af0..aee461d0f 100644 --- a/src/documents/tests/test_api_documents.py +++ b/src/documents/tests/test_api_documents.py @@ -3796,6 +3796,23 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase): self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + def test_order_share_links_by_document_title(self) -> None: + document_zulu = Document.objects.create(title="Zulu") + document_alpha = Document.objects.create(title="Alpha") + ShareLink.objects.create(document=document_zulu, slug="zulu-link") + ShareLink.objects.create(document=document_alpha, slug="alpha-link") + + response = self.client.get( + "/api/share_links/?ordering=document__title", + format="json", + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + [link["document_title"] for link in response.data["results"]], + ["Alpha", "Zulu"], + ) + def test_share_links_permissions_aware(self) -> None: """ GIVEN: diff --git a/src/documents/views.py b/src/documents/views.py index 5f1debbb1..9ae2a4a48 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -4571,7 +4571,7 @@ class ShareLinkViewSet( PermittedObjectsFilter, ) filterset_class = ShareLinkFilterSet - ordering_fields = ("created", "expiration", "document") + ordering_fields = ("created", "expiration", "document__title") @extend_schema_view(
DocumentCreatedExpiresDocumentCreatedExpires File version Actions