diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 7a35f94fe..4655767fd 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -272,7 +272,7 @@ </context-group> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context> - <context context-type="linenumber">73</context> + <context context-type="linenumber">58</context> </context-group> </trans-unit> <trans-unit id="8582620835547864448" datatype="html"> @@ -735,7 +735,7 @@ </context-group> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/widget-frame/widget-frame.component.html</context> - <context context-type="linenumber">14</context> + <context context-type="linenumber">15</context> </context-group> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> @@ -6172,10 +6172,6 @@ <context context-type="sourcefile">src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html</context> <context context-type="linenumber">9</context> </context-group> - <context-group purpose="location"> - <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context> - <context context-type="linenumber">39</context> - </context-group> </trans-unit> <trans-unit id="8076495233090006322" datatype="html"> <source>Filter by correspondent</source> @@ -6314,69 +6310,54 @@ <context context-type="linenumber">83</context> </context-group> </trans-unit> - <trans-unit id="8187573012244728580" datatype="html"> - <source>Upload new documents</source> + <trans-unit id="3402055842664792382" datatype="html"> + <source>Upload documents</source> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context> - <context context-type="linenumber">1</context> + <context context-type="linenumber">6</context> </context-group> </trans-unit> - <trans-unit id="8161815301131859114" datatype="html"> - <source>Drop documents anywhere or</source> + <trans-unit id="6388681050646106203" datatype="html"> + <source>or drop files anywhere</source> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context> - <context context-type="linenumber">4</context> - </context-group> - </trans-unit> - <trans-unit id="8133800334834354642" datatype="html"> - <source>Browse files</source> - <context-group purpose="location"> - <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context> - <context context-type="linenumber">5</context> + <context context-type="linenumber">7</context> </context-group> </trans-unit> <trans-unit id="1749180330008942007" datatype="html"> <source>Dismiss completed</source> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context> - <context context-type="linenumber">20</context> + <context context-type="linenumber">23</context> </context-group> <note priority="1" from="description">This button dismisses all status messages about processed documents on the dashboard (failed and successful)</note> </trans-unit> - <trans-unit id="2330646618997399019" datatype="html"> - <source>{VAR_PLURAL, plural, =1 {One more document} other {<x id="INTERPOLATION"/> more documents}}</source> - <context-group purpose="location"> - <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context> - <context context-type="linenumber">37</context> - </context-group> - <note priority="1" from="description">This is shown as a summary line when there are more than 5 document in the processing pipeline.</note> - </trans-unit> <trans-unit id="6443586946875325554" datatype="html"> <source>Processing: <x id="PH" equiv-text="countUploadingAndProcessing"/></source> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context> - <context context-type="linenumber">67</context> + <context context-type="linenumber">61</context> </context-group> </trans-unit> <trans-unit id="9182918211699394982" datatype="html"> <source>Failed: <x id="PH" equiv-text="countFailed"/></source> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context> - <context context-type="linenumber">70</context> + <context context-type="linenumber">64</context> </context-group> </trans-unit> <trans-unit id="534116346205124059" datatype="html"> <source>Added: <x id="PH" equiv-text="countSuccess"/></source> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context> - <context context-type="linenumber">73</context> + <context context-type="linenumber">67</context> </context-group> </trans-unit> <trans-unit id="760986369763309193" datatype="html"> <source>, </source> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context> - <context context-type="linenumber">76</context> + <context context-type="linenumber">70</context> </context-group> <context-group purpose="location"> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> diff --git a/src-ui/src/app/components/dashboard/dashboard.component.html b/src-ui/src/app/components/dashboard/dashboard.component.html index 7472abc8c..99c725802 100644 --- a/src-ui/src/app/components/dashboard/dashboard.component.html +++ b/src-ui/src/app/components/dashboard/dashboard.component.html @@ -49,12 +49,8 @@ </div> <div class="col-12 col-lg-4 col-xl-3 col-sidebar"> <div class="row row-cols-1 g-4 mb-4 sticky-lg-top z-0"> - <div class="col"> - <pngx-statistics-widget *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.UISettings }"></pngx-statistics-widget> - </div> - <div class="col"> - <pngx-upload-file-widget></pngx-upload-file-widget> - </div> + <pngx-upload-file-widget></pngx-upload-file-widget> + <pngx-statistics-widget *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.UISettings }"></pngx-statistics-widget> </div> </div> </div> diff --git a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html index 677be66a4..b91d5ed62 100644 --- a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html +++ b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html @@ -1,12 +1,15 @@ -<pngx-widget-frame title="Upload new documents" i18n-title *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.Document }"> +<pngx-widget-frame *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.Document }" [cardless]="true"> <div content tourAnchor="tour.upload-widget"> - <form class="justify-content-center d-flex flex-column align-items-center py-3 px-2"> - <span class="text-muted" i18n>Drop documents anywhere or</span> - <button type="button" class="btn btn-sm btn-outline-primary mt-3" (click)="fileUpload.click()" i18n>Browse files</button> + <form class="justify-content-center d-flex flex-column align-items-center"> + <button type="button" class="btn btn-outline-dark bg-light shadow-sm w-100 h-100 pt-3 pb-2" (click)="fileUpload.click()"> + <i-bs class="text-primary" name="plus-circle"></i-bs> + <span class="text-primary" i18n>Upload documents</span> + <div class="text-muted smaller fst-italic" i18n>or drop files anywhere</div> + </button> <input type="file" class="visually-hidden" (change)="onFileSelected($event)" multiple #fileUpload> </form> @if (getStatus().length > 0) { - <div class="fixed-bottom p-2 p-md-4 d-flex justify-content-end pe-none max-vh100-40" [ngClass]="slimSidebarEnabled ? 'col-slim' : 'offset-md-3 offset-lg-2'"> + <div class="fixed-bottom p-2 p-md-4 d-flex justify-content-end pe-none consumer-status-list" [ngClass]="slimSidebarEnabled ? 'col-slim' : 'offset-md-3 offset-lg-2'"> <div class="col col-lg-4 col-xl-3 ps-0 pe-0 ps-lg-3 pe-lg-0 pe-auto overflow-y-scroll"> <div class="card shadow-sm consumer-status-card"> <div class="card-body"> @@ -30,24 +33,6 @@ <ng-container [ngTemplateOutlet]="consumerAlert" [ngTemplateOutletContext]="{ $implicit: status }"></ng-container> </div> } - @if (getStatusHidden().length) { - <div class="alerts-hidden"> - @if (!alertsExpanded) { - <p class="mt-3 mb-0 text-center"> - <span i18n="This is shown as a summary line when there are more than 5 document in the processing pipeline.">{getStatusHidden().length, plural, =1 {One more document} other {{{getStatusHidden().length}} more documents}}</span> - • - <a [routerLink]="[]" (click)="alertsExpanded = !alertsExpanded" aria-controls="hiddenAlerts" [attr.aria-expanded]="alertsExpanded" i18n>Show all</a> - </p> - } - <div #hiddenAlerts="ngbCollapse" [ngbCollapse]="!alertsExpanded" (ngbCollapseChange)="alertsExpanded = $event"> - @for (status of getStatusHidden(); track status) { - <div> - <ng-container [ngTemplateOutlet]="consumerAlert" [ngTemplateOutletContext]="{ $implicit: status }"></ng-container> - </div> - } - </div> - </div> - } </div> </div> </div> diff --git a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.scss b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.scss index 7a050ab43..315313bff 100644 --- a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.scss +++ b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.scss @@ -1,5 +1,13 @@ -form { - position: relative; +:host ::ng-deep i-bs svg { + margin-top: -3px; +} + +.btn-outline-dark { + --bs-btn-border-color: var(--bs-border-color-translucent); +} + +.smaller { + font-size: 0.75rem; } .alert-heading { @@ -40,6 +48,10 @@ form { background-color: rgba(var(--bs-body-bg-rgb), .95) !important; } -.max-vh100-40 { - max-height: calc(100vh - 40px); +.consumer-status-list { + max-height: calc(100vh - 315px); // e.g. below the upload button, mobile + + @media screen and (min-width: 768px) { + max-height: calc(100vh - 200px); // e.g. below the upload button + } } diff --git a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.spec.ts b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.spec.ts index 45ac9217a..32d1557ed 100644 --- a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.spec.ts +++ b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.spec.ts @@ -8,7 +8,6 @@ import { } from '@angular/core/testing' import { By } from '@angular/platform-browser' import { RouterTestingModule } from '@angular/router/testing' -import { NgbAlert, NgbCollapse } from '@ng-bootstrap/ng-bootstrap' import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons' import { routes } from 'src/app/app-routing.module' import { PermissionsGuard } from 'src/app/guards/permissions.guard' @@ -116,20 +115,6 @@ describe('UploadFileWidgetComponent', () => { expect(component.getStatusColor(successStatus)).toEqual('success') }) - it('should enforce a maximum number of alerts', () => { - mockConsumerStatuses(websocketStatusService) - fixture.detectChanges() - // 5 total, 1 hidden - expect(fixture.debugElement.queryAll(By.directive(NgbAlert))).toHaveLength( - 6 - ) - expect( - fixture.debugElement - .query(By.directive(NgbCollapse)) - .queryAll(By.directive(NgbAlert)) - ).toHaveLength(1) - }) - it('should allow dismissing an alert', () => { const dismissSpy = jest.spyOn(websocketStatusService, 'dismiss') component.dismiss(new FileStatus()) @@ -138,7 +123,6 @@ describe('UploadFileWidgetComponent', () => { it('should allow dismissing completed alerts', fakeAsync(() => { mockConsumerStatuses(websocketStatusService) - component.alertsExpanded = true fixture.detectChanges() jest .spyOn(component, 'getStatusCompleted') diff --git a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts index f60cdce60..478775ae4 100644 --- a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts +++ b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts @@ -4,7 +4,6 @@ import { RouterModule } from '@angular/router' import { NgbAlert, NgbAlertModule, - NgbCollapseModule, NgbProgressbarModule, } from '@ng-bootstrap/ng-bootstrap' import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' @@ -21,8 +20,6 @@ import { } from 'src/app/services/websocket-status.service' import { WidgetFrameComponent } from '../widget-frame/widget-frame.component' -const MAX_ALERTS = 5 - @Component({ selector: 'pngx-upload-file-widget', templateUrl: './upload-file-widget.component.html', @@ -34,15 +31,12 @@ const MAX_ALERTS = 5 NgTemplateOutlet, RouterModule, NgbAlertModule, - NgbCollapseModule, NgbProgressbarModule, NgxBootstrapIconsModule, TourNgBootstrapModule, ], }) export class UploadFileWidgetComponent extends ComponentWithPermissions { - alertsExpanded = false - @ViewChildren(NgbAlert) alerts: QueryList<NgbAlert> constructor( @@ -54,7 +48,7 @@ export class UploadFileWidgetComponent extends ComponentWithPermissions { } getStatus() { - return this.websocketStatusService.getConsumerStatus().slice(0, MAX_ALERTS) + return this.websocketStatusService.getConsumerStatus() } getStatusSummary() { @@ -77,13 +71,6 @@ export class UploadFileWidgetComponent extends ComponentWithPermissions { ) } - getStatusHidden() { - if (this.websocketStatusService.getConsumerStatus().length < MAX_ALERTS) - return [] - else - return this.websocketStatusService.getConsumerStatus().slice(MAX_ALERTS) - } - getStatusUploading() { return this.websocketStatusService.getConsumerStatus( FileStatusPhase.UPLOADING diff --git a/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.html b/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.html index 5ec00f500..101a489b9 100644 --- a/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.html +++ b/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.html @@ -1,23 +1,32 @@ -<div class="card shadow-sm bg-light fade" [class.show]="show" cdkDrag [cdkDragDisabled]="!draggable" cdkDragPreviewContainer="parent"> - <div class="card-header"> - <div class="d-flex justify-content-between align-items-center"> - <div class="d-flex"> - @if (draggable) { - <div class="ms-n2 me-1" cdkDragHandle> - <i-bs name="grip-vertical"></i-bs> - </div> +@if (!cardless) { + <div class="card shadow-sm bg-light fade" [class.show]="show" cdkDrag [cdkDragDisabled]="!draggable" cdkDragPreviewContainer="parent"> + <div class="card-header"> + <div class="d-flex justify-content-between align-items-center"> + <div class="d-flex"> + @if (draggable) { + <div class="ms-n2 me-1" cdkDragHandle> + <i-bs name="grip-vertical"></i-bs> + </div> + } + <h6 class="card-title mb-0">{{title}}</h6> + </div> + @if (loading) { + <div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div> + <div class="visually-hidden" i18n>Loading...</div> } - <h6 class="card-title mb-0">{{title}}</h6> + <ng-content select="[header-buttons]"></ng-content> </div> - @if (loading) { - <div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div> - <div class="visually-hidden" i18n>Loading...</div> - } - <ng-content select="[header-buttons]"></ng-content> </div> + <div class="card-body text-dark"> + <ng-container [ngTemplateOutlet]="content"></ng-container> + </div> + </div> +} @else { + <div class="fade" [class.show]="show"> + <ng-container [ngTemplateOutlet]="content"></ng-container> + </div> +} - </div> - <div class="card-body text-dark"> - <ng-content select="[content]"></ng-content> - </div> -</div> +<ng-template #content> + <ng-content select="[content]"></ng-content> +</ng-template> diff --git a/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.ts b/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.ts index 109608daa..728787e9e 100644 --- a/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.ts +++ b/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.ts @@ -1,4 +1,5 @@ import { DragDropModule } from '@angular/cdk/drag-drop' +import { NgTemplateOutlet } from '@angular/common' import { AfterViewInit, Component, Input } from '@angular/core' import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' import { LoadingComponentWithPermissions } from 'src/app/components/loading-component/loading.component' @@ -7,7 +8,7 @@ import { LoadingComponentWithPermissions } from 'src/app/components/loading-comp selector: 'pngx-widget-frame', templateUrl: './widget-frame.component.html', styleUrls: ['./widget-frame.component.scss'], - imports: [DragDropModule, NgxBootstrapIconsModule], + imports: [DragDropModule, NgxBootstrapIconsModule, NgTemplateOutlet], }) export class WidgetFrameComponent extends LoadingComponentWithPermissions @@ -26,6 +27,9 @@ export class WidgetFrameComponent @Input() draggable: any + @Input() + cardless: boolean = false + ngAfterViewInit(): void { setTimeout(() => { this.show = true