mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	add file-types bar to statistics widget (#2914)
This commit is contained in:
		| @@ -13,14 +13,33 @@ | |||||||
|         <ng-container i18n>Total characters</ng-container>: |         <ng-container i18n>Total characters</ng-container>: | ||||||
|         <span class="badge bg-secondary text-light rounded-pill">{{statistics?.character_count | number}}</span> |         <span class="badge bg-secondary text-light rounded-pill">{{statistics?.character_count | number}}</span> | ||||||
|       </div> |       </div> | ||||||
|       <div class="list-group-item d-flex justify-content-between align-items-center"> |  | ||||||
|         <div class="flex-grow-1"><ng-container i18n>File types</ng-container>:</div> |       <div class="list-group-item widget-container"> | ||||||
|         <div class="d-flex flex-column flex-grow-1 filetypes-list"> |         <div class="file-type-bar"> | ||||||
|           <div *ngFor="let filetype of statistics?.document_file_type_counts; let i = index" class="d-flex justify-content-between align-items-center"> |           <ng-container | ||||||
|             <span class="fst-italic text-muted text-truncate pe-3">{{filetype.mime_type}}</span> |             *ngFor=" | ||||||
|             <span class="badge bg-secondary text-light rounded-pill">{{getFileTypePercent(filetype) | number: '1.0-1'}}%</span> |               let fileType of fileTypeDataArray; | ||||||
|           </div> |               let isFirst = first; | ||||||
|  |               let isLast = last | ||||||
|  |             " | ||||||
|  |           > | ||||||
|  |             <div | ||||||
|  |               class="file-type" | ||||||
|  |               [style.width.%]="fileType.percentage" | ||||||
|  |               [style.backgroundColor]="fileType.color" | ||||||
|  |               [ngClass]="{ 'rounded-left': isFirst, 'rounded-right': isLast }" | ||||||
|  |             ></div> | ||||||
|  |           </ng-container> | ||||||
|         </div> |         </div> | ||||||
|  |         <ng-container *ngFor="let fileType of fileTypeDataArray"> | ||||||
|  |           <div class="file-type-label"> | ||||||
|  |             <div | ||||||
|  |               class="file-type-color" | ||||||
|  |               [style.backgroundColor]="fileType.color" | ||||||
|  |             ></div> | ||||||
|  |             <span>{{ fileType.name }} ({{ fileType.percentage }}%)</span> | ||||||
|  |           </div> | ||||||
|  |         </ng-container> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   </ng-container> |   </ng-container> | ||||||
|   | |||||||
| @@ -1,7 +1,26 @@ | |||||||
| .flex-column { | .file-type-bar { | ||||||
|     row-gap: 0.2rem; |   display: flex; | ||||||
|  |   height: 10px; | ||||||
|  |   margin-bottom: 10px; | ||||||
| } | } | ||||||
|  | .file-type { | ||||||
| .filetypes-list { |   height: 100%; | ||||||
|     max-width: 75%; | } | ||||||
|  | .file-type-label { | ||||||
|  |   align-items: center; | ||||||
|  |   float: left; | ||||||
|  |   padding-right: 10px; | ||||||
|  | } | ||||||
|  | .file-type-color { | ||||||
|  |   width: 10px; | ||||||
|  |   height: 10px; | ||||||
|  |   border-radius: 50%; | ||||||
|  |   display: inline-block; | ||||||
|  |   margin-right: 5px; | ||||||
|  | } | ||||||
|  | .rounded-left { | ||||||
|  |   border-radius: 5px 0 0 5px; | ||||||
|  | } | ||||||
|  | .rounded-right { | ||||||
|  |   border-radius: 0 5px 5px 0; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -44,15 +44,26 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy { | |||||||
|     return this.http.get(`${environment.apiBaseUrl}statistics/`) |     return this.http.get(`${environment.apiBaseUrl}statistics/`) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   fileTypeDataArray = [] | ||||||
|  |  | ||||||
|  |   private fileTypeColors = [ | ||||||
|  |     '#e84118', // red | ||||||
|  |     '#00a8ff', // blue | ||||||
|  |     '#4cd137', // green | ||||||
|  |     '#9c88ff', // purple | ||||||
|  |     '#fbc531', // yellow | ||||||
|  |     '#7f8fa6', // gray | ||||||
|  |   ] | ||||||
|  |  | ||||||
|   reload() { |   reload() { | ||||||
|     this.loading = true |     this.loading = true | ||||||
|     this.getStatistics().subscribe((statistics) => { |     this.getStatistics().subscribe((statistics) => { | ||||||
|       this.loading = false |       this.loading = false | ||||||
|       // truncate the list and sum others |       const fileTypeMax = 5 | ||||||
|       if (statistics.document_file_type_counts?.length > 4) { |       if (statistics.document_file_type_counts?.length > fileTypeMax) { | ||||||
|         let others = statistics.document_file_type_counts.slice(4) |         let others = statistics.document_file_type_counts.slice(fileTypeMax) | ||||||
|         statistics.document_file_type_counts = |         statistics.document_file_type_counts = | ||||||
|           statistics.document_file_type_counts.slice(0, 4) |           statistics.document_file_type_counts.slice(0, fileTypeMax) | ||||||
|         statistics.document_file_type_counts.push({ |         statistics.document_file_type_counts.push({ | ||||||
|           mime_type: $localize`other`, |           mime_type: $localize`other`, | ||||||
|           mime_type_count: others.reduce( |           mime_type_count: others.reduce( | ||||||
| @@ -63,9 +74,26 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy { | |||||||
|         }) |         }) | ||||||
|       } |       } | ||||||
|       this.statistics = statistics |       this.statistics = statistics | ||||||
|  |  | ||||||
|  |       this.updateFileTypePercentages() | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   private updateFileTypePercentages() { | ||||||
|  |     let colorIndex = 0 | ||||||
|  |     this.fileTypeDataArray = this.statistics.document_file_type_counts.map( | ||||||
|  |       (fileType) => { | ||||||
|  |         const percentage = | ||||||
|  |           (fileType.mime_type_count / this.statistics?.documents_total) * 100 | ||||||
|  |         return { | ||||||
|  |           name: this.getMimeTypeName(fileType.mime_type), | ||||||
|  |           percentage: percentage.toFixed(2), | ||||||
|  |           color: this.fileTypeColors[colorIndex++], | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     ) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   ngOnInit(): void { |   ngOnInit(): void { | ||||||
|     this.reload() |     this.reload() | ||||||
|     this.subscription = this.consumerStatusService |     this.subscription = this.consumerStatusService | ||||||
| @@ -88,7 +116,33 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy { | |||||||
|     ]) |     ]) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   getFileTypePercent(filetype: DocumentFileType): number { |   getMimeTypeName(mimeType: string): string { | ||||||
|     return (filetype.mime_type_count / this.statistics?.documents_total) * 100 |     const mimeTypesMap: { [key: string]: string } = { | ||||||
|  |       'application/msword': 'Microsoft Word', | ||||||
|  |       'application/vnd.openxmlformats-officedocument.wordprocessingml.document': | ||||||
|  |         'Microsoft Word', | ||||||
|  |       'application/vnd.ms-excel': 'Microsoft Excel', | ||||||
|  |       'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': | ||||||
|  |         'Microsoft Excel', | ||||||
|  |       'application/vnd.ms-powerpoint': 'Microsoft PowerPoint', | ||||||
|  |       'application/vnd.openxmlformats-officedocument.presentationml.presentation': | ||||||
|  |         'Microsoft PowerPoint', | ||||||
|  |       'application/pdf': 'PDF', | ||||||
|  |       'application/vnd.oasis.opendocument.text': 'OpenDocument Text', | ||||||
|  |       'application/vnd.oasis.opendocument.spreadsheet': | ||||||
|  |         'OpenDocument Spreadsheet', | ||||||
|  |       'application/vnd.oasis.opendocument.presentation': | ||||||
|  |         'OpenDocument Presentation', | ||||||
|  |       'application/vnd.oasis.opendocument.graphics': 'OpenDocument Graphics', | ||||||
|  |       'application/rtf': 'Rich Text Format', | ||||||
|  |       'text/plain': 'Plain Text', | ||||||
|  |       'text/csv': 'CSV', | ||||||
|  |       'image/jpeg': 'JPEG', | ||||||
|  |       'image/png': 'PNG', | ||||||
|  |       'image/gif': 'GIF', | ||||||
|  |       'image/svg+xml': 'SVG', | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return mimeTypesMap[mimeType] || mimeType | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Tobias Schürg
					Tobias Schürg