]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
add file-types bar to statistics widget (#2914)
authorTobias Schürg <tobiasschuerg@gmail.com>
Mon, 20 Mar 2023 04:06:59 +0000 (05:06 +0100)
committerGitHub <noreply@github.com>
Mon, 20 Mar 2023 04:06:59 +0000 (21:06 -0700)
src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html
src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.scss
src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.ts

index f85176fded312804d16f38d7a837f91b018aa182..f7af4a7dd40bd4179e175f7ca2bd334df5769135 100644 (file)
         <ng-container i18n>Total characters</ng-container>:
         <span class="badge bg-secondary text-light rounded-pill">{{statistics?.character_count | number}}</span>
       </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="d-flex flex-column flex-grow-1 filetypes-list">
-          <div *ngFor="let filetype of statistics?.document_file_type_counts; let i = index" class="d-flex justify-content-between align-items-center">
-            <span class="fst-italic text-muted text-truncate pe-3">{{filetype.mime_type}}</span>
-            <span class="badge bg-secondary text-light rounded-pill">{{getFileTypePercent(filetype) | number: '1.0-1'}}%</span>
-          </div>
+
+      <div class="list-group-item widget-container">
+        <div class="file-type-bar">
+          <ng-container
+            *ngFor="
+              let fileType of fileTypeDataArray;
+              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>
+        <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>
   </ng-container>
index 6b26f8f0088e708445cdaedbd6d3455c30119196..9a533ef4786dc7b416a902610cfd8d62fe95dbf1 100644 (file)
@@ -1,7 +1,26 @@
-.flex-column {
-    row-gap: 0.2rem;
+.file-type-bar {
+  display: flex;
+  height: 10px;
+  margin-bottom: 10px;
 }
-
-.filetypes-list {
-    max-width: 75%;
+.file-type {
+  height: 100%;
+}
+.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;
 }
index 0daecd91fa18baa1da8eb0c8dcb462130cdd11ad..cf8b14cfad087858993dae124f2b74df6fbbd5a9 100644 (file)
@@ -44,15 +44,26 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy {
     return this.http.get(`${environment.apiBaseUrl}statistics/`)
   }
 
+  fileTypeDataArray = []
+
+  private fileTypeColors = [
+    '#e84118', // red
+    '#00a8ff', // blue
+    '#4cd137', // green
+    '#9c88ff', // purple
+    '#fbc531', // yellow
+    '#7f8fa6', // gray
+  ]
+
   reload() {
     this.loading = true
     this.getStatistics().subscribe((statistics) => {
       this.loading = false
-      // truncate the list and sum others
-      if (statistics.document_file_type_counts?.length > 4) {
-        let others = statistics.document_file_type_counts.slice(4)
+      const fileTypeMax = 5
+      if (statistics.document_file_type_counts?.length > fileTypeMax) {
+        let others = statistics.document_file_type_counts.slice(fileTypeMax)
         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({
           mime_type: $localize`other`,
           mime_type_count: others.reduce(
@@ -63,9 +74,26 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy {
         })
       }
       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 {
     this.reload()
     this.subscription = this.consumerStatusService
@@ -88,7 +116,33 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy {
     ])
   }
 
-  getFileTypePercent(filetype: DocumentFileType): number {
-    return (filetype.mime_type_count / this.statistics?.documents_total) * 100
+  getMimeTypeName(mimeType: string): string {
+    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
   }
 }