diff --git a/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.html b/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.html new file mode 100644 index 000000000..297d4d0b5 --- /dev/null +++ b/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.html @@ -0,0 +1,86 @@ + + + + + diff --git a/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.spec.ts b/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.spec.ts new file mode 100644 index 000000000..3f39da1b5 --- /dev/null +++ b/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.spec.ts @@ -0,0 +1,7 @@ +describe('ShareBundleManageDialogComponent', () => { + it('is pending implementation', () => { + pending( + 'ShareBundleManageDialogComponent tests will be implemented once the dialog logic is finalized.' + ) + }) +}) diff --git a/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.ts b/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.ts new file mode 100644 index 000000000..e552ffeb6 --- /dev/null +++ b/src-ui/src/app/components/common/share-bundle-manage-dialog/share-bundle-manage-dialog.component.ts @@ -0,0 +1,95 @@ +import { Clipboard } from '@angular/cdk/clipboard' +import { CommonModule } from '@angular/common' +import { Component, OnInit, inject } from '@angular/core' +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' +import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' +import { first } from 'rxjs' +import { ShareBundleSummary } from 'src/app/data/share-bundle' +import { ShareBundleService } from 'src/app/services/rest/share-bundle.service' +import { ToastService } from 'src/app/services/toast.service' +import { environment } from 'src/environments/environment' +import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' + +@Component({ + selector: 'pngx-share-bundle-manage-dialog', + templateUrl: './share-bundle-manage-dialog.component.html', + standalone: true, + imports: [CommonModule, NgxBootstrapIconsModule], +}) +export class ShareBundleManageDialogComponent + extends LoadingComponentWithPermissions + implements OnInit +{ + private activeModal = inject(NgbActiveModal) + private shareBundleService = inject(ShareBundleService) + private toastService = inject(ToastService) + private clipboard = inject(Clipboard) + + title = $localize`Bulk Share Links` + + bundles: ShareBundleSummary[] = [] + error: string + copiedSlug: string + + ngOnInit(): void { + this.fetchBundles() + } + + fetchBundles(): void { + this.loading = true + this.error = null + this.shareBundleService + .listAllBundles() + .pipe(first()) + .subscribe({ + next: (results) => { + this.bundles = results + this.loading = false + }, + error: (e) => { + this.loading = false + this.error = $localize`Failed to load bulk share links.` + this.toastService.showError( + $localize`Error retrieving bulk share links.`, + e + ) + }, + }) + } + + getShareUrl(bundle: ShareBundleSummary): string { + const apiURL = new URL(environment.apiBaseUrl) + return `${apiURL.origin}${apiURL.pathname.replace(/\/api\/$/, '/share/')}${ + bundle.slug + }` + } + + copy(bundle: ShareBundleSummary): void { + const success = this.clipboard.copy(this.getShareUrl(bundle)) + if (success) { + this.copiedSlug = bundle.slug + setTimeout(() => { + this.copiedSlug = null + }, 3000) + } + } + + delete(bundle: ShareBundleSummary): void { + this.shareBundleService.delete(bundle).subscribe({ + next: () => { + this.toastService.showInfo($localize`Bulk share link deleted.`) + this.fetchBundles() + }, + error: (e) => { + this.toastService.showError( + $localize`Error deleting bulk share link.`, + e + ) + }, + }) + } + + close(): void { + this.activeModal.close() + } +} diff --git a/src-ui/src/app/components/document-list/bulk-editor/bulk-editor.component.ts b/src-ui/src/app/components/document-list/bulk-editor/bulk-editor.component.ts index 7748b7676..8f47ac020 100644 --- a/src-ui/src/app/components/document-list/bulk-editor/bulk-editor.component.ts +++ b/src-ui/src/app/components/document-list/bulk-editor/bulk-editor.component.ts @@ -56,6 +56,7 @@ import { import { ToggleableItemState } from '../../common/filterable-dropdown/toggleable-dropdown-button/toggleable-dropdown-button.component' import { PermissionsDialogComponent } from '../../common/permissions-dialog/permissions-dialog.component' import { ShareBundleDialogComponent } from '../../common/share-bundle-dialog/share-bundle-dialog.component' +import { ShareBundleManageDialogComponent } from '../../common/share-bundle-manage-dialog/share-bundle-manage-dialog.component' import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' import { CustomFieldsBulkEditDialogComponent } from './custom-fields-bulk-edit-dialog/custom-fields-bulk-edit-dialog.component' @@ -955,9 +956,10 @@ export class BulkEditorComponent } manageShareLinks() { - this.toastService.showInfo( - $localize`Bulk share link management is coming soon.` - ) + const modal = this.modalService.open(ShareBundleManageDialogComponent, { + backdrop: 'static', + size: 'lg', + }) } emailSelected() { diff --git a/src-ui/src/app/services/rest/share-bundle.service.ts b/src-ui/src/app/services/rest/share-bundle.service.ts index 0b66da77f..7fcb9fc4e 100644 --- a/src-ui/src/app/services/rest/share-bundle.service.ts +++ b/src-ui/src/app/services/rest/share-bundle.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core' import { Observable } from 'rxjs' +import { map } from 'rxjs/operators' import { ShareBundleCreatePayload, ShareBundleSummary, @@ -22,12 +23,9 @@ export class ShareBundleService extends AbstractNameFilterService(this.getResourceUrl(), payload) } - listBundlesForDocuments( - documentIds: number[] - ): Observable { - const params = { documents: documentIds.join(',') } - return this.http.get(this.getResourceUrl(), { - params, - }) + listAllBundles(): Observable { + return this.list(1, 1000, 'created', true).pipe( + map((response) => response.results) + ) } }