Enhancement: dashboard improvements, drag-n-drop reorder dashboard views (#4252)

* Updated dashboard

* Make entire screen dropzone on dashboard too

* Floating upload widget status alerts

* Visual tweaks: spacing, borders

* Better empty view widget

* Support drag + drop reorder of dashboard saved views

* Update messages.xlf

* Disable dashbaord dnd if global dnd active

* Remove ngx-file-drop dep, rebuild file-drop & upload files widget

* Revert custom file drop implementation

* Try patch-package fix

* Simplify dropzone transitions to make more reliable

* Update messages.xlf

* Update dashboard.spec.ts

* Fix coverage
This commit is contained in:
shamoon
2023-09-28 10:18:12 -07:00
committed by GitHub
parent 96176589ca
commit 6973691cce
45 changed files with 1715 additions and 534 deletions

View File

@@ -42,5 +42,32 @@
</div>
</div>
</div>
<div class="list-group border-light mt-3">
<ng-container *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Tag }">
<a *ngIf="statistics?.tag_count > 0" class="list-group-item d-flex justify-content-between align-items-center" routerLink="/tags/">
<ng-container i18n>Tags</ng-container>:
<span class="badge bg-secondary text-light rounded-pill">{{statistics?.tag_count | number}}</span>
</a>
</ng-container>
<ng-container *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Correspondent }">
<a *ngIf="statistics?.correspondent_count > 0" class="list-group-item d-flex justify-content-between align-items-center" routerLink="/correspondents/">
<ng-container i18n>Correspondents</ng-container>:
<span class="badge bg-secondary text-light rounded-pill">{{statistics?.correspondent_count | number}}</span>
</a>
</ng-container>
<ng-container *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.DocumentType }">
<a *ngIf="statistics?.document_type_count > 0" class="list-group-item d-flex justify-content-between align-items-center" routerLink="/documenttypes/">
<ng-container i18n>Document Types</ng-container>:
<span class="badge bg-secondary text-light rounded-pill">{{statistics?.document_type_count | number}}</span>
</a>
</ng-container>
<ng-container *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.StoragePath }">
<a *ngIf="statistics?.storage_path_count > 0" class="list-group-item d-flex justify-content-between align-items-center" routerLink="/documenttypes/">
<ng-container i18n>Storage Paths</ng-container>:
<span class="badge bg-secondary text-light rounded-pill">{{statistics?.storage_path_count | number}}</span>
</a>
</ng-container>
</div>
</ng-container>
</pngx-widget-frame>

View File

@@ -11,24 +11,42 @@ import { environment } from 'src/environments/environment'
import { RouterTestingModule } from '@angular/router/testing'
import { routes } from 'src/app/app-routing.module'
import { PermissionsGuard } from 'src/app/guards/permissions.guard'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { DndModule } from 'ngx-drag-drop'
import {
ConsumerStatusService,
FileStatus,
} from 'src/app/services/consumer-status.service'
import { Subject } from 'rxjs'
describe('StatisticsWidgetComponent', () => {
let component: StatisticsWidgetComponent
let fixture: ComponentFixture<StatisticsWidgetComponent>
let httpTestingController: HttpTestingController
let consumerStatusService: ConsumerStatusService
const fileStatusSubject = new Subject<FileStatus>()
beforeEach(async () => {
TestBed.configureTestingModule({
declarations: [StatisticsWidgetComponent, WidgetFrameComponent],
declarations: [
StatisticsWidgetComponent,
WidgetFrameComponent,
IfPermissionsDirective,
],
providers: [PermissionsGuard],
imports: [
HttpClientTestingModule,
NgbModule,
RouterTestingModule.withRoutes(routes),
DndModule,
],
}).compileComponents()
fixture = TestBed.createComponent(StatisticsWidgetComponent)
consumerStatusService = TestBed.inject(ConsumerStatusService)
jest
.spyOn(consumerStatusService, 'onDocumentConsumptionFinished')
.mockReturnValue(fileStatusSubject)
component = fixture.componentInstance
httpTestingController = TestBed.inject(HttpTestingController)
@@ -43,6 +61,12 @@ describe('StatisticsWidgetComponent', () => {
expect(req.request.method).toEqual('GET')
})
it('should reload after doc is consumed', () => {
const reloadSpy = jest.spyOn(component, 'reload')
fileStatusSubject.next(new FileStatus())
expect(reloadSpy).toHaveBeenCalled()
})
it('should display inbox link with count', () => {
const mockStats = {
documents_total: 200,
@@ -107,4 +131,62 @@ describe('StatisticsWidgetComponent', () => {
'CSV(10%)'
)
})
it('should limit mime types to 5 max', () => {
const mockStats = {
documents_total: 222,
documents_inbox: 18,
inbox_tag: 10,
document_file_type_counts: [
{
mime_type: 'application/pdf',
mime_type_count: 160,
},
{
mime_type: 'text/plain',
mime_type_count: 20,
},
{
mime_type: 'text/csv',
mime_type_count: 20,
},
{
mime_type: 'application/vnd.oasis.opendocument.text',
mime_type_count: 11,
},
{
mime_type: 'application/msword',
mime_type_count: 9,
},
{
mime_type: 'image/jpeg',
mime_type_count: 2,
},
],
character_count: 162312,
}
const req = httpTestingController.expectOne(
`${environment.apiBaseUrl}statistics/`
)
req.flush(mockStats)
fixture.detectChanges()
expect(fixture.nativeElement.textContent.replace(/\s/g, '')).toContain(
'PDF(72.1%)'
)
expect(fixture.nativeElement.textContent.replace(/\s/g, '')).toContain(
'TXT(9%)'
)
expect(fixture.nativeElement.textContent.replace(/\s/g, '')).toContain(
'CSV(9%)'
)
expect(fixture.nativeElement.textContent.replace(/\s/g, '')).toContain(
'ODT(5%)'
)
expect(fixture.nativeElement.textContent.replace(/\s/g, '')).toContain(
'Other(0.9%)'
)
})
})

View File

@@ -6,6 +6,7 @@ import { ConsumerStatusService } from 'src/app/services/consumer-status.service'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { environment } from 'src/environments/environment'
import * as mimeTypeNames from 'mime-names'
import { ComponentWithPermissions } from 'src/app/components/with-permissions/with-permissions.component'
export interface Statistics {
documents_total?: number
@@ -13,6 +14,10 @@ export interface Statistics {
inbox_tag?: number
document_file_type_counts?: DocumentFileType[]
character_count?: number
tag_count?: number
correspondent_count?: number
document_type_count?: number
storage_path_count?: number
}
interface DocumentFileType {
@@ -25,14 +30,19 @@ interface DocumentFileType {
templateUrl: './statistics-widget.component.html',
styleUrls: ['./statistics-widget.component.scss'],
})
export class StatisticsWidgetComponent implements OnInit, OnDestroy {
export class StatisticsWidgetComponent
extends ComponentWithPermissions
implements OnInit, OnDestroy
{
loading: boolean = true
constructor(
private http: HttpClient,
private consumerStatusService: ConsumerStatusService,
private documentListViewService: DocumentListViewService
) {}
) {
super()
}
statistics: Statistics = {}
@@ -87,7 +97,7 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy {
this.reload()
this.subscription = this.consumerStatusService
.onDocumentConsumptionFinished()
.subscribe((status) => {
.subscribe(() => {
this.reload()
})
}