Merge pull request #2904 from paperless-ngx/feature-improve-comments-ui

Enhancement: rename comments to notes and improve notes UI
This commit is contained in:
shamoon
2023-03-19 14:34:49 -07:00
committed by GitHub
49 changed files with 740 additions and 514 deletions

View File

@@ -26,7 +26,7 @@
</div>
<p class="card-text">
<span *ngIf="document.__search_hit__ && document.__search_hit__.highlights" [innerHtml]="document.__search_hit__.highlights"></span>
<span *ngFor="let highlight of searchCommentHighlights" class="d-block">
<span *ngFor="let highlight of searchNoteHighlights" class="d-block">
<svg width="1em" height="1em" fill="currentColor" class="me-2">
<use xlink:href="assets/bootstrap-icons.svg#chat-left-text"/>
</svg>
@@ -65,24 +65,31 @@
</a>
</div>
<div class="list-group list-group-horizontal border-0 card-info ms-md-auto mt-2 mt-md-0">
<button *ngIf="notesEnabled && document.notes.length" routerLink="/documents/{{document.id}}/notes" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2" title="View notes" i18n-title>
<svg class="metadata-icon me-2 text-muted" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#chat-left-text"/>
</svg>
<small i18n>{{document.notes.length}} Notes</small>
</button>
<button *ngIf="document.document_type" type="button" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2" title="Filter by document type" i18n-title
(click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()">
<svg class="metadata-icon me-2 text-muted bi bi-file-earmark" viewBox="0 0 16 16" fill="currentColor">
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
<svg class="metadata-icon me-2 text-muted" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#file-earmark"/>
</svg>
<small>{{(document.document_type$ | async)?.name}}</small>
</button>
<button *ngIf="document.storage_path" type="button" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2" title="Filter by storage path" i18n-title
(click)="clickStoragePath.emit(document.storage_path);$event.stopPropagation()">
<svg class="metadata-icon me-2 text-muted bi bi-folder" viewBox="0 0 16 16" fill="currentColor">
<path d="M0 2a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1v7.5a2.5 2.5 0 0 1-2.5 2.5h-9A2.5 2.5 0 0 1 1 12.5V5a1 1 0 0 1-1-1V2zm2 3v7.5A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5V5H2zm13-3H1v2h14V2zM5 7.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5z"/>
<svg class="metadata-icon me-2 text-muted" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#archive"/>
</svg>
<small>{{(document.storage_path$ | async)?.name}}</small>
</button>
<div *ngIf="document.archive_serial_number" class="list-group-item me-2 bg-light text-dark p-1 border-0">
<svg class="metadata-icon me-2 text-muted bi bi-upc-scan" viewBox="0 0 16 16" fill="currentColor">
<path d="M1.5 1a.5.5 0 0 0-.5.5v3a.5.5 0 0 1-1 0v-3A1.5 1.5 0 0 1 1.5 0h3a.5.5 0 0 1 0 1h-3zM11 .5a.5.5 0 0 1 .5-.5h3A1.5 1.5 0 0 1 16 1.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 1-.5-.5zM.5 11a.5.5 0 0 1 .5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 1 0 1h-3A1.5 1.5 0 0 1 0 14.5v-3a.5.5 0 0 1 .5-.5zm15 0a.5.5 0 0 1 .5.5v3a1.5 1.5 0 0 1-1.5 1.5h-3a.5.5 0 0 1 0-1h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 1 .5-.5zM3 4.5a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-7zm3 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7z"/>
<svg class="metadata-icon me-2 text-muted" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#upc-scan"/>
</svg>
<small>#{{document.archive_serial_number}}</small>
</div>
@@ -94,9 +101,8 @@
</div>
</ng-template>
<div class="list-group-item bg-light text-dark p-1 border-0" [ngbTooltip]="dateTooltip">
<svg class="metadata-icon me-2 text-muted bi bi-calendar-event" viewBox="0 0 16 16" fill="currentColor">
<path d="M11 6.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1z"/>
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
<svg class="metadata-icon me-2 text-muted" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#calendar-event"/>
</svg>
<small>{{document.created_date | customDate:'mediumDate'}}</small>
</div>

View File

@@ -73,12 +73,6 @@
}
}
.metadata-icon {
width: 0.9rem;
height: 0.9rem;
padding: 0.05rem;
}
.search-score {
padding-top: 0.35rem !important;
}

View File

@@ -73,16 +73,14 @@ export class DocumentCardLargeComponent extends ComponentWithPermissions {
}
}
get searchCommentHighlights() {
get searchNoteHighlights() {
let highlights = []
if (
this.document['__search_hit__'] &&
this.document['__search_hit__'].comment_highlights
this.document['__search_hit__'].note_highlights
) {
// only show comments with a match
highlights = (
this.document['__search_hit__'].comment_highlights as string
)
// only show notes with a match
highlights = (this.document['__search_hit__'].note_highlights as string)
.split(',')
.filter((higlight) => higlight.includes('<span'))
}
@@ -136,4 +134,8 @@ export class DocumentCardLargeComponent extends ComponentWithPermissions {
(this.document.content.length > 500 ? '...' : '')
)
}
get notesEnabled(): boolean {
return this.settingsService.get(SETTINGS_KEYS.NOTES_ENABLED)
}
}

View File

@@ -13,12 +13,20 @@
<div class="tags d-flex flex-column text-end position-absolute me-1 fs-6">
<app-tag *ngFor="let t of getTagsLimited$() | async" [tag]="t" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="true" linkTitle="Toggle tag filter" i18n-linkTitle></app-tag>
<div *ngIf="moreTags">
<span class="badge badge-secondary">+ {{moreTags}}</span>
<span class="badge text-dark">+ {{moreTags}}</span>
</div>
</div>
</div>
<div class="card-body p-2">
<a *ngIf="notesEnabled && document.notes.length" routerLink="/documents/{{document.id}}/notes" class="document-card-notes py-2 px-1">
<span class="badge rounded-pill bg-light border text-primary">
<svg class="metadata-icon ms-1 me-1" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#chat-left-text"/>
</svg>
{{document.notes.length}}</span>
</a>
<div class="card-body bg-light p-2">
<p class="card-text">
<ng-container *ngIf="document.correspondent">
<a title="Toggle correspondent filter" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name}}</a>:

View File

@@ -5,7 +5,7 @@
.doc-img {
object-fit: cover;
object-position: top left;
height: 175px;
height: 180px;
mix-blend-mode: multiply;
}
@@ -34,6 +34,12 @@
display: block;
}
.document-card-notes {
position: absolute;
right: 0;
top: 142px;
}
.card-selected {
border-color:var(--bs-primary);
@@ -58,12 +64,6 @@
color: var(--bs-primary);
}
}
.metadata-icon {
width: 0.9rem;
height: 0.9rem;
padding: 0.05rem;
}
}
.card-footer .btn {

View File

@@ -74,11 +74,12 @@ export class DocumentCardSmallComponent extends ComponentWithPermissions {
}
getTagsLimited$() {
const limit = this.document.notes.length > 0 ? 6 : 7
return this.document.tags$.pipe(
map((tags) => {
if (tags.length > 7) {
this.moreTags = tags.length - 6
return tags.slice(0, 6)
if (tags.length > limit) {
this.moreTags = tags.length - (limit - 1)
return tags.slice(0, limit - 1)
} else {
return tags
}
@@ -110,4 +111,8 @@ export class DocumentCardSmallComponent extends ComponentWithPermissions {
mouseLeaveCard() {
this.popover.close()
}
get notesEnabled(): boolean {
return this.settingsService.get(SETTINGS_KEYS.NOTES_ENABLED)
}
}

View File

@@ -139,6 +139,12 @@
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Title</th>
<th *ngIf="notesEnabled" class="d-none d-xl-table-cell"
appSortable="num_notes"
[currentSortField]="list.sortField"
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Notes</th>
<th class="d-none d-xl-table-cell"
appSortable="document_type__name"
[currentSortField]="list.sortField"
@@ -184,6 +190,15 @@
<a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
<app-tag [tag]="t" *ngFor="let t of d.tags$ | async" class="ms-1" clickable="true" linkTitle="Filter by tag" i18n-linkTitle (click)="clickTag(t.id);$event.stopPropagation()"></app-tag>
</td>
<td *ngIf="notesEnabled" class="d-none d-xl-table-cell">
<a *ngIf="d.notes.length" routerLink="/documents/{{d.id}}/notes" class="btn btn-sm p-0">
<span class="badge rounded-pill bg-light border text-primary">
<svg class="metadata-icon ms-1 me-1" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#chat-left-text"/>
</svg>
{{d.notes.length}}</span>
</a>
</td>
<td class="d-none d-xl-table-cell">
<ng-container *ngIf="d.document_type">
<a (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type" i18n-title>{{(d.document_type$ | async)?.name}}</a>

View File

@@ -17,6 +17,7 @@ import {
import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'
import { PaperlessDocument } from 'src/app/data/paperless-document'
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'
import { SETTINGS_KEYS } from 'src/app/data/paperless-uisettings'
import {
SortableDirective,
SortEvent,
@@ -29,6 +30,7 @@ import {
DOCUMENT_SORT_FIELDS_FULLTEXT,
} from 'src/app/services/rest/document.service'
import { SavedViewService } from 'src/app/services/rest/saved-view.service'
import { SettingsService } from 'src/app/services/settings.service'
import { ToastService } from 'src/app/services/toast.service'
import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
import { FilterEditorComponent } from './filter-editor/filter-editor.component'
@@ -51,7 +53,8 @@ export class DocumentListComponent
private toastService: ToastService,
private modalService: NgbModal,
private consumerStatusService: ConsumerStatusService,
public openDocumentsService: OpenDocumentsService
public openDocumentsService: OpenDocumentsService,
private settingsService: SettingsService
) {
super()
}
@@ -289,4 +292,8 @@ export class DocumentListComponent
trackByDocumentId(index, item: PaperlessDocument) {
return item.id
}
get notesEnabled(): boolean {
return this.settingsService.get(SETTINGS_KEYS.NOTES_ENABLED)
}
}