</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/admin/trash/trash.component.html</context>
- <context context-type="linenumber">67</context>
+ <context context-type="linenumber">72</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/admin/trash/trash.component.html</context>
- <context context-type="linenumber">76</context>
+ <context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/admin/trash/trash.component.ts</context>
<source><x id="INTERPOLATION" equiv-text="{{ getDaysRemaining(document) }}"/> days</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/admin/trash/trash.component.html</context>
- <context context-type="linenumber">58</context>
+ <context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="6770769801335635194" datatype="html">
<source>Restore</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/admin/trash/trash.component.html</context>
- <context context-type="linenumber">66</context>
+ <context context-type="linenumber">71</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/admin/trash/trash.component.html</context>
- <context context-type="linenumber">73</context>
+ <context context-type="linenumber">78</context>
</context-group>
</trans-unit>
<trans-unit id="2308646316372333720" datatype="html">
<source>{VAR_PLURAL, plural, =1 {One document in trash} other {<x id="INTERPOLATION"/> total documents in trash}}</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/admin/trash/trash.component.html</context>
- <context context-type="linenumber">89</context>
+ <context context-type="linenumber">94</context>
</context-group>
</trans-unit>
<trans-unit id="9021887951960049161" datatype="html">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">68</context>
+ <context context-type="linenumber">63</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
- <context context-type="linenumber">140</context>
+ <context context-type="linenumber">135</context>
</context-group>
</trans-unit>
<trans-unit id="searchResults.noResults" datatype="html">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">62</context>
+ <context context-type="linenumber">60</context>
</context-group>
</trans-unit>
<trans-unit id="9195188695728229921" datatype="html">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.ts</context>
- <context context-type="linenumber">86</context>
+ <context context-type="linenumber">79</context>
</context-group>
</trans-unit>
<trans-unit id="2504502765849142619" datatype="html">
<source>Error loading preview</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/preview-popup/preview-popup.component.html</context>
- <context context-type="linenumber">4</context>
+ <context context-type="linenumber">10</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="3601402187462260332" datatype="html">
+ <source>Open preview</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/components/common/preview-popup/preview-popup.component.ts</context>
+ <context context-type="linenumber">37</context>
</context-group>
</trans-unit>
<trans-unit id="2984628903434675339" datatype="html">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">79</context>
+ <context context-type="linenumber">74</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
- <context context-type="linenumber">323</context>
+ <context context-type="linenumber">328</context>
</context-group>
</trans-unit>
<trans-unit id="157572966557284263" datatype="html">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">85</context>
+ <context context-type="linenumber">80</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
- <context context-type="linenumber">330</context>
+ <context context-type="linenumber">335</context>
</context-group>
</trans-unit>
<trans-unit id="8911158217491828773" datatype="html">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
- <context context-type="linenumber">299</context>
+ <context context-type="linenumber">304</context>
</context-group>
</trans-unit>
<trans-unit id="106713086593101376" datatype="html">
<source>View notes</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">74</context>
+ <context context-type="linenumber">69</context>
</context-group>
</trans-unit>
<trans-unit id="3727324658595204357" datatype="html">
<source>Created: <x id="INTERPOLATION" equiv-text="{{ document.created_date | customDate }}"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">98,99</context>
+ <context context-type="linenumber">93,94</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<source>Added: <x id="INTERPOLATION" equiv-text="{{ document.added | customDate }}"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">99,100</context>
+ <context context-type="linenumber">94,95</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<source>Modified: <x id="INTERPOLATION" equiv-text="{{ document.modified | customDate }}"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">100,101</context>
+ <context context-type="linenumber">95,96</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<source>{VAR_PLURAL, plural, =1 {1 page} other {<x id="INTERPOLATION"/> pages}}</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">117</context>
+ <context context-type="linenumber">112</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<source>Shared</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">127</context>
+ <context context-type="linenumber">122</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<source>Score:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
- <context context-type="linenumber">132</context>
+ <context context-type="linenumber">127</context>
</context-group>
</trans-unit>
<trans-unit id="3661756380991326939" datatype="html">
<source>Edit document</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
- <context context-type="linenumber">295</context>
+ <context context-type="linenumber">296</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="3420321797707163677" datatype="html">
+ <source>Preview document</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
+ <context context-type="linenumber">297</context>
</context-group>
</trans-unit>
<trans-unit id="2807800733729323332" datatype="html">
<source>Yes</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
- <context context-type="linenumber">351</context>
+ <context context-type="linenumber">356</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/pipes/yes-no.pipe.ts</context>
<source>No</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
- <context context-type="linenumber">351</context>
+ <context context-type="linenumber">356</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/pipes/yes-no.pipe.ts</context>
</tr>
}
@for (document of documentsInTrash; track document.id) {
- <tr (click)="toggleSelected(document); $event.stopPropagation();">
+ <tr (click)="toggleSelected(document); $event.stopPropagation();" (mouseleave)="popupPreview.close()">
<td>
<div class="form-check m-0 ms-2 me-n2">
<input type="checkbox" class="form-check-input" id="{{document.id}}" [checked]="selectedDocuments.has(document.id)" (click)="toggleSelected(document); $event.stopPropagation();">
<label class="form-check-label" for="{{document.id}}"></label>
</div>
</td>
- <td scope="row">{{ document.title }}</td>
+ <td scope="row">
+ {{ document.title }}
+ <pngx-preview-popup [document]="document" linkClasses="btn btn-sm btn-link" #popupPreview>
+ <i-bs name="eye"></i-bs>
+ </pngx-preview-popup>
+ </td>
<td scope="row" i18n>{{ getDaysRemaining(document) }} days</td>
<td scope="row">
<div class="btn-group d-block d-sm-none">
-<div class="preview-popup-container">
- @if (error) {
- <div class="w-100 h-100 position-relative">
- <p class="fst-italic position-absolute top-50 start-50 translate-middle" i18n>Error loading preview</p>
- </div>
- } @else {
- @if (renderAsObject) {
- @if (previewText) {
- <div class="bg-light p-3 overflow-auto whitespace-preserve" width="100%">{{previewText}}</div>
- } @else {
- <object [data]="previewURL | safeUrl" width="100%" class="bg-light" [class.p-2]="!isPdf"></object>
- }
+<a [href]="link ?? previewUrl" class="{{linkClasses}}" [target]="linkTarget" [title]="linkTitle"
+ [ngbPopover]="previewContent" [popoverTitle]="document.title | documentTitle" container="body"
+ autoClose="true" [popoverClass]="popoverClass" (mouseenter)="mouseEnterPreview()" (mouseleave)="mouseLeavePreview()" #popover="ngbPopover">
+ <ng-content></ng-content>
+</a>
+<ng-template #previewContent>
+ <div class="preview-popup-container">
+ @if (error) {
+ <div class="w-100 h-100 position-relative">
+ <p class="fst-italic position-absolute top-50 start-50 translate-middle" i18n>Error loading preview</p>
+ </div>
} @else {
- @if (requiresPassword) {
- <div class="w-100 h-100 position-relative">
- <i-bs width="2em" height="2em" class="position-absolute top-50 start-50 translate-middle" name="file-earmark-lock"></i-bs>
- </div>
- }
- @if (!requiresPassword) {
- <pdf-viewer
- [src]="previewURL"
- [original-size]="false"
- [show-borders]="false"
- [show-all]="true"
- (error)="onError($event)">
- </pdf-viewer>
+ @if (renderAsObject) {
+ @if (previewText) {
+ <div class="bg-light p-3 overflow-auto whitespace-preserve" width="100%">{{previewText}}</div>
+ } @else {
+ <object [data]="previewURL | safeUrl" width="100%" class="bg-light" [class.p-2]="!isPdf"></object>
+ }
+ } @else {
+ @if (requiresPassword) {
+ <div class="w-100 h-100 position-relative">
+ <i-bs width="2em" height="2em" class="position-absolute top-50 start-50 translate-middle" name="file-earmark-lock"></i-bs>
+ </div>
+ }
+ @if (!requiresPassword) {
+ <pdf-viewer
+ [src]="previewURL"
+ [original-size]="false"
+ [show-borders]="false"
+ [show-all]="true"
+ (error)="onError($event)">
+ </pdf-viewer>
+ }
}
}
- }
-</div>
+ </div>
+</ng-template>
-import { ComponentFixture, TestBed } from '@angular/core/testing'
+import {
+ ComponentFixture,
+ fakeAsync,
+ TestBed,
+ tick,
+} from '@angular/core/testing'
import { PreviewPopupComponent } from './preview-popup.component'
import { By } from '@angular/platform-browser'
withInterceptorsFromDi,
} from '@angular/common/http'
import { of, throwError } from 'rxjs'
+import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'
+import { DocumentTitlePipe } from 'src/app/pipes/document-title.pipe'
const doc = {
id: 10,
beforeEach(() => {
TestBed.configureTestingModule({
- declarations: [PreviewPopupComponent, SafeUrlPipe],
- imports: [NgxBootstrapIconsModule.pick(allIcons), PdfViewerModule],
+ declarations: [PreviewPopupComponent, SafeUrlPipe, DocumentTitlePipe],
+ imports: [
+ NgxBootstrapIconsModule.pick(allIcons),
+ PdfViewerModule,
+ NgbPopoverModule,
+ ],
providers: [
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting(),
it('should render object if native PDF viewer enabled', () => {
settingsService.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, true)
+ component.popover.open()
fixture.detectChanges()
expect(fixture.debugElement.query(By.css('object'))).not.toBeNull()
})
it('should render pngx viewer if native PDF viewer disabled', () => {
settingsService.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, false)
+ component.popover.open()
fixture.detectChanges()
expect(fixture.debugElement.query(By.css('object'))).toBeNull()
expect(fixture.debugElement.query(By.css('pdf-viewer'))).not.toBeNull()
it('should show lock icon on password error', () => {
settingsService.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, false)
+ component.popover.open()
component.onError({ name: 'PasswordException' })
fixture.detectChanges()
expect(component.requiresPassword).toBeTruthy()
component.document.original_file_name = 'sample.png'
component.document.mime_type = 'image/png'
component.document.archived_file_name = undefined
+ component.popover.open()
fixture.detectChanges()
expect(fixture.debugElement.query(By.css('object'))).not.toBeNull()
})
it('should show message on error', () => {
+ component.popover.open()
component.onError({})
fixture.detectChanges()
- expect(fixture.debugElement.nativeElement.textContent).toContain(
- 'Error loading preview'
- )
+ expect(
+ fixture.debugElement.query(By.css('.popover')).nativeElement.textContent
+ ).toContain('Error loading preview')
})
it('should get text content from http if appropriate', () => {
component.init()
expect(component.previewText).toEqual('Preview text')
})
+
+ it('should show preview on mouseover after delay to preload content', fakeAsync(() => {
+ component.mouseEnterPreview()
+ expect(component.popover.isOpen()).toBeTruthy()
+ tick(600)
+ component.close()
+
+ component.mouseEnterPreview()
+ tick(100)
+ component.mouseLeavePreview()
+ tick(600)
+ expect(component.popover.isOpen()).toBeFalsy()
+ }))
})
import { HttpClient } from '@angular/common/http'
-import { Component, Input, OnDestroy } from '@angular/core'
+import { Component, Input, OnDestroy, ViewChild } from '@angular/core'
+import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
import { first, Subject, takeUntil } from 'rxjs'
import { Document } from 'src/app/data/document'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
return this._document
}
+ @Input()
+ link: string
+
+ @Input()
+ linkClasses: string = 'btn btn-sm btn-outline-secondary'
+
+ @Input()
+ linkTarget: string = '_blank'
+
+ @Input()
+ linkTitle: string = $localize`Open preview`
+
unsubscribeNotifier: Subject<any> = new Subject()
error = false
previewText: string
+ @ViewChild('popover') popover: NgbPopover
+
+ mouseOnPreview: boolean
+
+ popoverClass: string = 'shadow popover-preview'
+
get renderAsObject(): boolean {
return (this.isPdf && this.useNativePdfViewer) || !this.isPdf
}
this.error = true
}
}
+
+ get previewUrl() {
+ return this.documentService.getPreviewUrl(this.document.id)
+ }
+
+ mouseEnterPreview() {
+ this.mouseOnPreview = true
+ if (!this.popover.isOpen()) {
+ // we're going to open but hide to pre-load content during hover delay
+ this.popover.open()
+ this.popoverClass = 'shadow popover-preview pe-none opacity-0'
+ setTimeout(() => {
+ if (this.mouseOnPreview) {
+ // show popover
+ this.popoverClass = this.popoverClass.replace('pe-none opacity-0', '')
+ } else {
+ this.popover.close()
+ }
+ }, 600)
+ }
+ }
+
+ mouseLeavePreview() {
+ this.mouseOnPreview = false
+ }
+
+ public close() {
+ this.popover.close(false)
+ }
}
-<div class="card mb-3 shadow-sm bg-light" [class.card-selected]="selected" [class.document-card]="selectable" [class.popover-hidden]="popoverHidden" (mouseleave)="mouseLeaveCard()">
+<div class="card mb-3 shadow-sm bg-light" [class.card-selected]="selected" [class.document-card]="selectable" (mouseleave)="mouseLeaveCard()">
<div class="row g-0">
<div class="col-md-2 doc-img-container rounded-start" (click)="this.toggleSelected.emit($event)" (dblclick)="dblClickDocument.emit()">
<img [src]="getThumbUrl()" class="card-img doc-img border-end rounded-start" [class.inverted]="getIsThumbInverted()">
<a routerLink="/documents/{{document.id}}" class="btn btn-sm btn-outline-secondary" *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.Document }">
<i-bs name="file-earmark-richtext"></i-bs> <span class="d-none d-md-inline" i18n>Open</span>
</a>
- <a class="btn btn-sm btn-outline-secondary" target="_blank" [href]="previewUrl"
- [ngbPopover]="previewContent" [popoverTitle]="document.title | documentTitle"
- autoClose="true" popoverClass="shadow popover-preview" (mouseenter)="mouseEnterPreview()" (mouseleave)="mouseLeavePreview()" #popover="ngbPopover">
+ <pngx-preview-popup [document]="document" #popupPreview>
<i-bs name="eye"></i-bs> <span class="d-none d-md-inline" i18n>View</span>
- </a>
- <ng-template #previewContent>
- <pngx-preview-popup [document]="document"></pngx-preview-popup>
- </ng-template>
+ </pngx-preview-popup>
<a class="btn btn-sm btn-outline-secondary" [href]="getDownloadUrl()">
<i-bs name="download"></i-bs> <span class="d-none d-md-inline" i18n>Download</span>
</a>
import { DatePipe } from '@angular/common'
import { provideHttpClientTesting } from '@angular/common/http/testing'
-import {
- ComponentFixture,
- TestBed,
- fakeAsync,
- tick,
-} from '@angular/core/testing'
+import { ComponentFixture, TestBed } from '@angular/core/testing'
import { By } from '@angular/platform-browser'
import { RouterTestingModule } from '@angular/router/testing'
import {
expect(fixture.nativeElement.textContent).toContain('8 pages')
})
- it('should show preview on mouseover after delay to preload content', fakeAsync(() => {
- component.mouseEnterPreview()
- expect(component.popover.isOpen()).toBeTruthy()
- expect(component.popoverHidden).toBeTruthy()
- tick(600)
- expect(component.popoverHidden).toBeFalsy()
- component.mouseLeaveCard()
-
- component.mouseEnterPreview()
- tick(100)
- component.mouseLeavePreview()
- tick(600)
- expect(component.popover.isOpen()).toBeFalsy()
- }))
-
it('should trim content', () => {
expect(component.contentTrimmed).toHaveLength(503) // includes ...
})
} from 'src/app/data/document'
import { DocumentService } from 'src/app/services/rest/document.service'
import { SettingsService } from 'src/app/services/settings.service'
-import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
+import { PreviewPopupComponent } from '../../common/preview-popup/preview-popup.component'
@Component({
selector: 'pngx-document-card-large',
@Output()
clickMoreLike = new EventEmitter()
- @ViewChild('popover') popover: NgbPopover
+ @ViewChild('popupPreview') popupPreview: PreviewPopupComponent
mouseOnPreview = false
popoverHidden = true
return this.documentService.getPreviewUrl(this.document.id)
}
- mouseEnterPreview() {
- this.mouseOnPreview = true
- if (!this.popover.isOpen()) {
- // we're going to open but hide to pre-load content during hover delay
- this.popover.open()
- this.popoverHidden = true
- setTimeout(() => {
- if (this.mouseOnPreview) {
- // show popover
- this.popoverHidden = false
- } else {
- this.popover.close()
- }
- }, 600)
- }
- }
-
- mouseLeavePreview() {
- this.mouseOnPreview = false
- }
-
mouseLeaveCard() {
- this.popover.close()
+ this.popupPreview.close()
}
get contentTrimmed() {
<div class="col p-2 h-100">
- <div class="card h-100 shadow-sm document-card" [class.card-selected]="selected" [class.popover-hidden]="popoverHidden" (mouseleave)="mouseLeaveCard()">
+ <div class="card h-100 shadow-sm document-card" [class.card-selected]="selected" (mouseleave)="mouseLeaveCard()">
<div class="border-bottom doc-img-container rounded-top" (click)="this.toggleSelected.emit($event)" (dblclick)="dblClickDocument.emit(this)">
<img class="card-img doc-img" [class.inverted]="getIsThumbInverted()" [src]="getThumbUrl()">
<a routerLink="/documents/{{document.id}}" class="btn btn-sm btn-outline-secondary" title="Open" i18n-title *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.Document }" i18n-title>
<i-bs name="file-earmark-richtext"></i-bs>
</a>
- <a [href]="previewUrl" target="_blank" class="btn btn-sm btn-outline-secondary"
- [ngbPopover]="previewContent" [popoverTitle]="document.title | documentTitle"
- autoClose="true" popoverClass="shadow popover-preview" (mouseenter)="mouseEnterPreview()" (mouseleave)="mouseLeavePreview()" #popover="ngbPopover">
+ <pngx-preview-popup [document]="document" #popupPreview>
<i-bs name="eye"></i-bs>
- </a>
- <ng-template #previewContent>
- <pngx-preview-popup [document]="document"></pngx-preview-popup>
- </ng-template>
+ </pngx-preview-popup>
<a [href]="getDownloadUrl()" class="btn btn-sm btn-outline-secondary" title="Download" i18n-title (click)="$event.stopPropagation()">
<i-bs name="download"></i-bs>
</a>
import { DatePipe } from '@angular/common'
import { provideHttpClientTesting } from '@angular/common/http/testing'
-import {
- ComponentFixture,
- TestBed,
- fakeAsync,
- tick,
-} from '@angular/core/testing'
+import { ComponentFixture, TestBed } from '@angular/core/testing'
import { RouterTestingModule } from '@angular/router/testing'
import {
NgbPopoverModule,
fixture.debugElement.queryAll(By.directive(TagComponent))
).toHaveLength(6)
})
-
- it('should show preview on mouseover after delay to preload content', fakeAsync(() => {
- component.mouseEnterPreview()
- expect(component.popover.isOpen()).toBeTruthy()
- expect(component.popoverHidden).toBeTruthy()
- tick(600)
- expect(component.popoverHidden).toBeFalsy()
- component.mouseLeaveCard()
-
- component.mouseEnterPreview()
- tick(100)
- component.mouseLeavePreview()
- tick(600)
- expect(component.popover.isOpen()).toBeFalsy()
- }))
})
} from 'src/app/data/document'
import { DocumentService } from 'src/app/services/rest/document.service'
import { SettingsService } from 'src/app/services/settings.service'
-import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
+import { PreviewPopupComponent } from '../../common/preview-popup/preview-popup.component'
@Component({
selector: 'pngx-document-card-small',
moreTags: number = null
- @ViewChild('popover') popover: NgbPopover
-
- mouseOnPreview = false
- popoverHidden = true
+ @ViewChild('popupPreview') popupPreview: PreviewPopupComponent
getIsThumbInverted() {
return this.settingsService.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED)
return this.documentService.getDownloadUrl(this.document.id)
}
- get previewUrl() {
- return this.documentService.getPreviewUrl(this.document.id)
- }
-
get privateName() {
return $localize`Private`
}
)
}
- mouseEnterPreview() {
- this.mouseOnPreview = true
- if (!this.popover.isOpen()) {
- // we're going to open but hide to pre-load content during hover delay
- this.popover.open()
- this.popoverHidden = true
- setTimeout(() => {
- if (this.mouseOnPreview) {
- // show popover
- this.popoverHidden = false
- } else {
- this.popover.close()
- }
- }, 600)
- }
- }
-
- mouseLeavePreview() {
- this.mouseOnPreview = false
- }
-
mouseLeaveCard() {
- this.popover.close()
+ this.popupPreview.close()
}
get notesEnabled(): boolean {
@if (activeDisplayFields.includes(DisplayField.TITLE) || activeDisplayFields.includes(DisplayField.TAGS)) {
<td width="30%">
@if (activeDisplayFields.includes(DisplayField.TITLE)) {
- <a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
+ <div class="d-inline-block" (mouseleave)="popupPreview.close()">
+ <a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
+ <pngx-preview-popup [document]="d" linkClasses="btn btn-sm btn-link text-secondary" linkTitle="Preview document" (click)="$event.stopPropagation()" i18n-linkTitle #popupPreview>
+ <i-bs name="eye"></i-bs>
+ </pngx-preview-popup>
+ </div>
}
@if (activeDisplayFields.includes(DisplayField.TAGS)) {
@for (t of d.tags$ | async; track t) {
}
}
-.popover-hidden .popover {
- opacity: 0;
- pointer-events: none;
-}
-
// Tour
.tour-active .popover {
min-width: 360px;
vertical-align: middle;
}
}
+
+// fixes for buttons in preview popup
+.btn-group pngx-preview-popup:not(:last-child) {
+ // Prevent double borders when buttons are next to each other
+ > .btn {
+ margin-left: calc(#{$btn-border-width} * -1);
+ }
+ > .btn {
+ @include border-end-radius(0);
+ }
+}
+.btn-group pngx-preview-popup:not(:first-child) {
+ > .btn {
+ @include border-start-radius(0);
+ }
+}
+.btn-group pngx-preview-popup {
+ position: relative;
+ flex: 1 1 auto;
+
+ > .btn {
+ display: block;
+ }
+}
)
def file_response(self, pk, request, disposition):
- doc = Document.objects.select_related("owner").get(id=pk)
+ doc = Document.global_objects.select_related("owner").get(id=pk)
if request.user is not None and not has_perms_owner_aware(
request.user,
"view_document",