2023-09-14 14:03:28 -07:00
< pngx-page-header [ title ] = " getTitle ( ) " >
2020-10-27 01:10:18 +01:00
2024-03-04 17:00:19 -08:00
< div ngbDropdown class = "d-flex" >
2022-05-11 23:09:22 -07:00
< button class = "btn btn-sm btn-outline-primary" id = "dropdownSelect" ngbDropdownToggle >
2024-01-17 16:27:38 -08:00
< i-bs name = "text-indent-left" > < / i-bs >
2022-05-11 23:09:22 -07:00
< div class = "d-none d-sm-inline" > < ng-container i18n > Select< / ng-container > < / div >
2020-11-29 16:33:33 +01:00
< / button >
2020-12-14 23:14:19 -08:00
< div ngbDropdownMenu aria-labelledby = "dropdownSelect" class = "shadow" >
2020-12-28 15:39:53 +01:00
< button ngbDropdownItem ( click ) = " list . selectNone ( ) " i18n > Select none< / button >
< button ngbDropdownItem ( click ) = " list . selectPage ( ) " i18n > Select page< / button >
< button ngbDropdownItem ( click ) = " list . selectAll ( ) " i18n > Select all< / button >
2020-11-29 16:33:33 +01:00
< / div >
< / div >
2022-07-02 00:45:26 -07:00
< div class = "btn-group flex-fill" role = "group" >
2023-03-10 14:53:32 -08:00
< input type = "radio" class = "btn-check" [ ( ngModel ) ] = " displayMode " value = "details" ( ngModelChange ) = " saveDisplayMode ( ) " id = "displayModeDetails" name = "displayModeDetails" >
2022-07-02 00:45:26 -07:00
< label for = "displayModeDetails" class = "btn btn-outline-primary btn-sm" >
2024-01-17 16:27:38 -08:00
< i-bs name = "list-ul" > < / i-bs >
2020-10-27 01:10:18 +01:00
< / label >
2023-03-10 14:53:32 -08:00
< input type = "radio" class = "btn-check" [ ( ngModel ) ] = " displayMode " value = "smallCards" ( ngModelChange ) = " saveDisplayMode ( ) " id = "displayModeSmall" name = "displayModeSmall" >
2022-07-02 00:45:26 -07:00
< label for = "displayModeSmall" class = "btn btn-outline-primary btn-sm" >
2024-01-17 16:27:38 -08:00
< i-bs name = "grid" > < / i-bs >
2020-10-27 01:10:18 +01:00
< / label >
2023-03-10 14:53:32 -08:00
< input type = "radio" class = "btn-check" [ ( ngModel ) ] = " displayMode " value = "largeCards" ( ngModelChange ) = " saveDisplayMode ( ) " id = "displayModeLarge" name = "displayModeLarge" >
2022-07-02 00:45:26 -07:00
< label for = "displayModeLarge" class = "btn btn-outline-primary btn-sm" >
2024-01-17 16:27:38 -08:00
< i-bs name = "hdd-stack" > < / i-bs >
2020-10-27 01:10:18 +01:00
< / label >
< / div >
2020-12-08 23:08:02 -08:00
2024-03-04 17:00:19 -08:00
< div ngbDropdown class = "btn-group flex-fill" >
2021-01-11 12:52:42 -08:00
< button class = "btn btn-outline-primary btn-sm" id = "dropdownBasic1" ngbDropdownToggle i18n > Sort< / button >
< div ngbDropdownMenu aria-labelledby = "dropdownBasic1" class = "shadow dropdown-menu-right" >
2022-07-02 00:45:26 -07:00
< div class = "w-100 d-flex pb-2 mb-1 border-bottom" >
< input type = "radio" class = "btn-check" [ value ] = " false " [ ( ngModel ) ] = " listSortReverse " id = "listSortReverseFalse" >
< label class = "btn btn-outline-primary btn-sm mx-2 flex-fill" for = "listSortReverseFalse" >
2024-01-17 16:27:38 -08:00
< i-bs name = "sort-alpha-down" > < / i-bs >
2021-01-11 12:52:42 -08:00
< / label >
2022-07-02 00:45:26 -07:00
< input type = "radio" class = "btn-check" [ value ] = " true " [ ( ngModel ) ] = " listSortReverse " id = "listSortReverseTrue" >
< label class = "btn btn-outline-primary btn-sm me-2 flex-fill" for = "listSortReverseTrue" >
2024-01-17 16:27:38 -08:00
< i-bs name = "sort-alpha-up-alt" > < / i-bs >
2021-01-11 12:52:42 -08:00
< / label >
< / div >
< div >
2023-12-19 15:02:05 -08:00
@for (f of getSortFields(); track f) {
< button ngbDropdownItem ( click ) = " setSortField ( f . field ) "
[class.active]="list.sortField === f.field">{{f.name}}
< / button >
}
2020-10-27 01:10:18 +01:00
< / div >
< / div >
< / div >
2020-10-30 22:46:43 +01:00
2024-03-04 17:00:19 -08:00
< div class = "btn-group flex-fill" * pngxIfPermissions = "{ action: PermissionAction.View, type: PermissionType.SavedView }" ngbDropdown role = "group" >
2022-10-29 23:14:33 -07:00
< button class = "btn btn-sm btn-outline-primary dropdown-toggle flex-fill" tourAnchor = "tour.documents-views" ngbDropdownToggle >
< ng-container i18n > Views< / ng-container >
2023-12-19 15:02:05 -08:00
@if (savedViewIsModified) {
< div class = "position-absolute top-0 start-100 p-2 translate-middle badge bg-secondary border border-light rounded-circle" >
< span class = "visually-hidden" > selected< / span >
< / div >
}
2022-10-29 23:14:33 -07:00
< / button >
2021-01-11 12:52:42 -08:00
< div class = "dropdown-menu shadow dropdown-menu-right" ngbDropdownMenu >
2023-12-19 15:02:05 -08:00
@if (!list.activeSavedViewId) {
@for (view of savedViewService.allViews; track view) {
< button ngbDropdownItem ( click ) = " loadViewConfig ( view . id ) " > {{view.name}}< / button >
}
@if (savedViewService.allViews.length > 0) {
< div class = "dropdown-divider" > < / div >
}
}
2020-12-08 23:08:02 -08:00
2023-09-14 14:03:28 -07:00
< div * pngxIfPermissions = "{ action: PermissionAction.Change, type: PermissionType.SavedView }" >
2023-12-19 15:02:05 -08:00
@if (list.activeSavedViewId) {
< button ngbDropdownItem ( click ) = " saveViewConfig ( ) " [ disabled ] = " ! savedViewIsModified " i18n > Save "{{list.activeSavedViewTitle}}"< / button >
}
2022-11-11 18:33:04 +00:00
< / div >
2023-09-14 14:03:28 -07:00
< button ngbDropdownItem ( click ) = " saveViewConfigAs ( ) " * pngxIfPermissions = "{ action: PermissionAction.Add, type: PermissionType.SavedView }" i18n > Save as...< / button >
2020-10-30 22:46:43 +01:00
< / div >
< / div >
2020-12-08 23:08:02 -08:00
2023-09-14 14:03:28 -07:00
< / pngx-page-header >
2020-10-27 01:10:18 +01:00
2023-11-19 16:13:38 -08:00
< div class = "row sticky-top py-3 mt-n2 mt-md-n3 bg-body" >
2023-09-14 14:03:28 -07:00
< pngx-filter-editor [ hidden ] = " isBulkEditing " [ ( filterRules ) ] = " list . filterRules " [ unmodifiedFilterRules ] = " unmodifiedFilterRules " [ selectionData ] = " list . selectionData " # filterEditor > < / pngx-filter-editor >
< pngx-bulk-editor [ hidden ] = " ! isBulkEditing " > < / pngx-bulk-editor >
2020-12-18 21:19:49 -08:00
< / div >
2022-09-21 21:44:15 -07:00
2022-03-15 00:58:58 -07:00
< ng-template # pagination >
2023-05-03 19:37:36 -07:00
< div class = "d-flex flex-wrap gap-3 justify-content-between align-items-center mb-3" >
< div class = "d-flex align-items-center" >
2023-12-19 15:02:05 -08:00
@if (list.isReloading) {
2022-03-15 00:58:58 -07:00
< div class = "spinner-border spinner-border-sm me-2" role = "status" > < / div >
< ng-container i18n > Loading...< / ng-container >
2023-12-19 15:02:05 -08:00
}
@if (list.selected.size > 0) {
< span i18n > {list.collectionSize, plural, =1 {Selected {{list.selected.size}} of one document} other {Selected {{list.selected.size}} of {{list.collectionSize || 0}} documents}}< / span >
}
@if (!list.isReloading) {
@if (list.selected.size === 0) {
< span i18n > {list.collectionSize, plural, =1 {One document} other {{{list.collectionSize || 0}} documents}}< / span >
} @if (isFiltered) {
< span i18n > (filtered)< / span >
}
}
@if (!list.isReloading & & isFiltered) {
< button class = "btn btn-link py-0" ( click ) = " resetFilters ( ) " >
2024-01-17 16:27:38 -08:00
< i-bs width = "1em" height = "1em" name = "x" > < / i-bs > < small i18n > Reset filters< / small >
2023-12-19 15:02:05 -08:00
< / button >
}
< / div >
@if (list.collectionSize) {
< ngb-pagination [ pageSize ] = " list . currentPageSize " [ collectionSize ] = " list . collectionSize " [ ( page ) ] = " list . currentPage " [ maxSize ] = " 5 "
[rotate]="true" aria-label="Default pagination" size="sm">< / ngb-pagination >
}
2023-05-03 19:37:36 -07:00
< / div >
2023-12-19 15:02:05 -08:00
< / ng-template >
2021-04-14 09:00:30 -07:00
2023-12-19 15:02:05 -08:00
< div tourAnchor = "tour.documents" >
2022-03-15 00:58:58 -07:00
< ng-container * ngTemplateOutlet = "pagination" > < / ng-container >
< / div >
2021-04-14 09:00:30 -07:00
2023-12-19 15:02:05 -08:00
@if (list.error ) {
< div class = "alert alert-danger" role = "alert" > < ng-container i18n > Error while loading documents< / ng-container > : {{list.error}}< / div >
} @else {
@if (displayMode === 'largeCards') {
< div >
@for (d of list.documents; track trackByDocumentId($index, d)) {
< pngx-document-card-large [ selected ] = " list . isSelected ( d ) " ( toggleSelected ) = " toggleSelected ( d , $ event ) " ( dblClickDocument ) = " openDocumentDetail ( d ) " [ document ] = " d " ( clickTag ) = " clickTag ( $ event ) " ( clickCorrespondent ) = " clickCorrespondent ( $ event ) " ( clickDocumentType ) = " clickDocumentType ( $ event ) " ( clickStoragePath ) = " clickStoragePath ( $ event ) " ( clickMoreLike ) = " clickMoreLike ( d . id ) " >
< / pngx-document-card-large >
}
< / div >
}
@if (displayMode === 'details') {
< table class = "table table-sm align-middle border shadow-sm" >
< thead >
< th > < / th >
< th class = "d-none d-lg-table-cell"
pngxSortable="archive_serial_number"
title="Sort by ASN" i18n-title
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>ASN< / th >
< th class = "d-none d-md-table-cell"
pngxSortable="correspondent__name"
title="Sort by correspondent" i18n-title
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Correspondent< / th >
< th
pngxSortable="title"
title="Sort by title" i18n-title
class="w-40"
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Title< / th >
< th class = "d-none d-xl-table-cell"
pngxSortable="owner"
title="Sort by owner" i18n-title
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Owner< / th >
@if (notesEnabled) {
< th class = "d-none d-xl-table-cell"
pngxSortable="num_notes"
title="Sort by notes" i18n-title
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Notes< / th >
}
< th class = "d-none d-xl-table-cell"
pngxSortable="document_type__name"
title="Sort by document type" i18n-title
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Document type< / th >
< th class = "d-none d-xl-table-cell"
pngxSortable="storage_path__name"
title="Sort by storage path" i18n-title
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Storage path< / th >
< th
pngxSortable="created"
title="Sort by created date" i18n-title
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Created< / th >
< th class = "d-none d-xl-table-cell"
pngxSortable="added"
title="Sort by added date" i18n-title
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Added< / th >
< / thead >
< tbody >
@for (d of list.documents; track trackByDocumentId($index, d)) {
< tr ( click ) = " toggleSelected ( d , $ event ) ; $ event . stopPropagation ( ) ; " ( dblclick ) = " openDocumentDetail ( d ) " [ ngClass ] = " list . isSelected ( d ) ? ' table-row-selected ' : ' ' " >
< td >
< div class = "form-check" >
< input type = "checkbox" class = "form-check-input" id = "docCheck{{d.id}}" [ checked ] = " list . isSelected ( d ) " ( click ) = " toggleSelected ( d , $ event ) ; $ event . stopPropagation ( ) ; " >
< label class = "form-check-label" for = "docCheck{{d.id}}" > < / label >
< / div >
< / td >
< td class = "d-none d-lg-table-cell" >
{{d.archive_serial_number}}
< / td >
< td class = "d-none d-md-table-cell" >
@if (d.correspondent) {
< a ( click ) = " clickCorrespondent ( d . correspondent ) ; $ event . stopPropagation ( ) " title = "Filter by correspondent" i18n-title > {{(d.correspondent$ | async)?.name}}< / a >
}
< / td >
< td >
< a routerLink = "/documents/{{d.id}}" title = "Edit document" i18n-title style = "overflow-wrap: anywhere;" > {{d.title | documentTitle}}< / a >
@for (t of d.tags$ | async; track t) {
< pngx-tag [ tag ] = " t " class = "ms-1" clickable = "true" linkTitle = "Filter by tag" i18n-linkTitle ( click ) = " clickTag ( t . id ) ; $ event . stopPropagation ( ) " > < / pngx-tag >
}
< / td >
< td >
{{d.owner | username}}
< / td >
@if (notesEnabled) {
< td class = "d-none d-xl-table-cell" >
@if (d.notes.length) {
< a routerLink = "/documents/{{d.id}}/notes" class = "btn btn-sm p-0" >
< span class = "badge rounded-pill bg-light border text-primary" >
2024-02-06 14:50:08 -08:00
< i-bs width = "1.2em" height = "1.2em" class = "ms-1 me-1" name = "chat-left-text" > < / i-bs >
2023-12-19 15:02:05 -08:00
{{d.notes.length}}< / span >
< / a >
}
< / td >
}
< td class = "d-none d-xl-table-cell" >
@if (d.document_type) {
< a ( click ) = " clickDocumentType ( d . document_type ) ; $ event . stopPropagation ( ) " title = "Filter by document type" i18n-title > {{(d.document_type$ | async)?.name}}< / a >
}
< / td >
< td class = "d-none d-xl-table-cell" >
@if (d.storage_path) {
< a ( click ) = " clickStoragePath ( d . storage_path ) ; $ event . stopPropagation ( ) " title = "Filter by storage path" i18n-title > {{(d.storage_path$ | async)?.name}}< / a >
}
< / td >
< td >
{{d.created_date | customDate}}
< / td >
< td class = "d-none d-xl-table-cell" >
{{d.added | customDate}}
< / td >
< / tr >
}
< / tbody >
< / table >
}
@if (displayMode === 'smallCards') {
< div class = "row row-cols-paperless-cards" >
@for (d of list.documents; track trackByDocumentId($index, d)) {
< pngx-document-card-small class = "p-0" [ selected ] = " list . isSelected ( d ) " ( toggleSelected ) = " toggleSelected ( d , $ event ) " ( dblClickDocument ) = " openDocumentDetail ( d ) " [ document ] = " d " ( clickTag ) = " clickTag ( $ event ) " ( clickCorrespondent ) = " clickCorrespondent ( $ event ) " ( clickStoragePath ) = " clickStoragePath ( $ event ) " ( clickDocumentType ) = " clickDocumentType ( $ event ) " > < / pngx-document-card-small >
}
< / div >
}
@if (list.documents?.length > 15) {
< div class = "mt-3" >
< ng-container * ngTemplateOutlet = "pagination" > < / ng-container >
< / div >
}
}