]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Re-implement file type progress bar
authorshamoon <4887959+shamoon@users.noreply.github.com>
Mon, 20 Mar 2023 04:11:29 +0000 (21:11 -0700)
committershamoon <4887959+shamoon@users.noreply.github.com>
Mon, 20 Mar 2023 06:22:28 +0000 (23:22 -0700)
src-ui/messages.xlf
src-ui/package-lock.json
src-ui/package.json
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
src-ui/src/styles.scss

index 1be4f94fe26ba661fff17f9e528de793fb4bf209..83152f56a86e7dd999f3ae9f7ae22d144419c0be 100644 (file)
           <context context-type="linenumber">13</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="6125391559813574136" datatype="html">
-        <source>File types</source>
-        <context-group purpose="location">
-          <context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html</context>
-          <context context-type="linenumber">17</context>
-        </context-group>
-      </trans-unit>
-      <trans-unit id="3881818169480672345" datatype="html">
-        <source>other</source>
+      <trans-unit id="8693603235657020323" datatype="html">
+        <source>Other</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.ts</context>
-          <context context-type="linenumber">56</context>
+          <context context-type="linenumber">87</context>
         </context-group>
       </trans-unit>
       <trans-unit id="8187573012244728580" datatype="html">
index 38c6d0664a88b1f6ca49b1b9ba5e59b7259b2924..6df75ac5c442124e39fe97a91d685177ab86bf55 100644 (file)
@@ -22,6 +22,7 @@
         "@popperjs/core": "^2.11.6",
         "bootstrap": "^5.2.3",
         "file-saver": "^2.0.5",
+        "mime-names": "^1.0.0",
         "ng2-pdf-viewer": "^9.1.2",
         "ngx-color": "^8.0.3",
         "ngx-cookie-service": "^15.0.0",
         "node": ">= 0.6"
       }
     },
+    "node_modules/mime-names": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/mime-names/-/mime-names-1.0.0.tgz",
+      "integrity": "sha512-vLNEfYU63fz34panv/L3Lh3eW3+v0BlOB+bSGFdntv/gBNnokCbSsaNuHR9vH/NS5oWbL0HqMQf/3we4fRJyIQ=="
+    },
     "node_modules/mime-types": {
       "version": "2.1.35",
       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
index 8ec1b80ab37ff316a24ebe7ca4f3cffb6495146a..934011a5bebeaa89f52c6344023ae7fd10cd7700 100644 (file)
@@ -27,6 +27,7 @@
     "@popperjs/core": "^2.11.6",
     "bootstrap": "^5.2.3",
     "file-saver": "^2.0.5",
+    "mime-names": "^1.0.0",
     "ng2-pdf-viewer": "^9.1.2",
     "ngx-color": "^8.0.3",
     "ngx-cookie-service": "^15.0.0",
index f7af4a7dd40bd4179e175f7ca2bd334df5769135..ec6e239d0b351760a59847180176fde0cf811325 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 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 *ngIf="statistics?.document_file_type_counts?.length > 1" class="list-group-item filetypes">
+        <div class="d-flex justify-content-between align-items-center my-2">
+          <div class="progress flex-grow-1">
+            <div *ngFor="let filetype of statistics?.document_file_type_counts; let i = index; let last = last"
+              class="progress-bar bg-primary text-primary-contrast"
+              role="progressbar"
+              [ngbPopover]="getFileTypeName(filetype)"
+              i18n-ngbPopover
+              triggers="mouseenter:mouseleave"
+              [attr.aria-label]="getFileTypeName(filetype)"
+              [class.me-1px]="!last"
+              [style.width]="getFileTypePercent(filetype) + '%'"
+              [style.opacity]="getItemOpacity(i)"
+              [attr.aria-valuenow]="getFileTypePercent(filetype)"
+              aria-valuemin="0"
+              aria-valuemax="100">
+            </div>
+          </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 class="d-flex flex-wrap align-items-start">
+          <div class="d-flex" *ngFor="let filetype of statistics?.document_file_type_counts; let i = index">
+            <div class="text-nowrap me-2">
+              <span class="badge rounded-pill bg-primary d-inline-block p-0 me-1" [style.opacity]="getItemOpacity(i)"></span>
+              <small class="text-nowrap"><span class="fw-bold">{{ getFileTypeExtension(filetype) }}</span>&nbsp;<span class="text-muted">({{getFileTypePercent(filetype) | number: '1.0-1'}}%)</span></small>
+            </div>
           </div>
-        </ng-container>
+        </div>
       </div>
     </div>
   </ng-container>
index 9a533ef4786dc7b416a902610cfd8d62fe95dbf1..bb2bc5b4f0a1010bfda112fcbc701990361423dc 100644 (file)
@@ -1,26 +1,10 @@
-.file-type-bar {
-  display: flex;
-  height: 10px;
-  margin-bottom: 10px;
-}
-.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;
+.filetypes {
+    .progress {
+        height: 0.6rem;
+    }
+
+    .badge {
+        height: 0.6rem;
+        width: 0.6rem;
+    }
 }
index cf8b14cfad087858993dae124f2b74df6fbbd5a9..d1de799c15ea4f8e4fdddb51d041a7602715dad8 100644 (file)
@@ -1,13 +1,11 @@
 import { HttpClient } from '@angular/common/http'
 import { Component, OnDestroy, OnInit } from '@angular/core'
 import { Observable, Subscription } from 'rxjs'
-import {
-  FILTER_HAS_TAGS_ALL,
-  FILTER_IS_IN_INBOX,
-} from 'src/app/data/filter-rule-type'
+import { FILTER_HAS_TAGS_ALL } from 'src/app/data/filter-rule-type'
 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'
 
 export interface Statistics {
   documents_total?: number
@@ -44,28 +42,17 @@ 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
       const fileTypeMax = 5
       if (statistics.document_file_type_counts?.length > fileTypeMax) {
-        let others = statistics.document_file_type_counts.slice(fileTypeMax)
+        const others = statistics.document_file_type_counts.slice(fileTypeMax)
         statistics.document_file_type_counts =
           statistics.document_file_type_counts.slice(0, fileTypeMax)
         statistics.document_file_type_counts.push({
-          mime_type: $localize`other`,
+          mime_type: $localize`Other`,
           mime_type_count: others.reduce(
             (currentValue, documentFileType) =>
               documentFileType.mime_type_count + currentValue,
@@ -74,26 +61,28 @@ 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++],
-        }
-      }
+  getFileTypeExtension(filetype: DocumentFileType): string {
+    return (
+      mimeTypeNames[filetype.mime_type]?.extensions[0]?.toUpperCase() ??
+      filetype.mime_type
     )
   }
 
+  getFileTypeName(filetype: DocumentFileType): string {
+    return mimeTypeNames[filetype.mime_type]?.name ?? filetype.mime_type
+  }
+
+  getFileTypePercent(filetype: DocumentFileType): number {
+    return (filetype.mime_type_count / this.statistics?.documents_total) * 100
+  }
+
+  getItemOpacity(i: number): number {
+    return 1 - i / this.statistics?.document_file_type_counts.length
+  }
+
   ngOnInit(): void {
     this.reload()
     this.subscription = this.consumerStatusService
@@ -115,34 +104,4 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy {
       },
     ])
   }
-
-  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
-  }
 }
index ed4efbe9db0193d1c58463571b4a1a663fbbb7e0..1b23d7a6c303ce4af06643f69750fd7c4889d42d 100644 (file)
@@ -623,3 +623,7 @@ code {
 .accordion-button::after {
   filter: invert(0.5) saturate(0);
 }
+
+.me-1px {
+  margin-right: 1px !important;
+}